diff -ur globus_common-7.20.orig/library/globus_libc.c globus_common-7.20/library/globus_libc.c --- globus_common-7.20.orig/library/globus_libc.c 2005-04-19 00:59:31.000000000 +0200 +++ globus_common-7.20/library/globus_libc.c 2006-10-26 13:56:26.000000000 +0200 @@ -17,10 +17,10 @@ CVS Information: $Source: /home/globdev/CVS/globus-packages/common/source/library/globus_libc.c,v $ - $Date: 2005/04/18 22:59:31 $ - $Revision: 1.48 $ + $Date: 2006/10/03 23:13:57 $ + $Revision: 1.48.4.1 $ $State: Exp $ - $Author: mlink $ + $Author: kettimut $ ******************************************************************************/ /****************************************************************************** @@ -361,6 +361,26 @@ } /* globus_libc_write() */ /****************************************************************************** +Function: globus_libc_umask() + +Description: + +Parameters: + +Returns: +******************************************************************************/ +#undef globus_libc_umask +mode_t +globus_libc_umask(mode_t mask) +{ + mode_t oldmask; + globus_libc_lock(); + oldmask = umask(mask); + globus_libc_unlock(); + return(oldmask); +} /* globus_libc_umask */ + +/****************************************************************************** Function: globus_libc_fstat() Description: @@ -1071,6 +1091,13 @@ */ #if defined(TARGET_ARCH_WIN32) +/* As there isn't a equivalent of umask() for windows, this is a noop */ +mode_t +globus_libc_umask_win32(mode_t mask) +{ + return mask; +} + int globus_libc_system_memory( globus_off_t * mem) diff -ur globus_common-7.20.orig/library/globus_libc.h globus_common-7.20/library/globus_libc.h --- globus_common-7.20.orig/library/globus_libc.h 2005-04-19 00:59:31.000000000 +0200 +++ globus_common-7.20/library/globus_libc.h 2006-10-26 13:56:26.000000000 +0200 @@ -117,6 +117,7 @@ extern int globus_libc_write(int fd, char *buf, int nbytes); extern int globus_libc_writev(int fd, struct iovec *iov, int iovcnt); extern int globus_libc_fstat(int fd, struct stat *buf); +extern int globus_libc_umask(mode_t mask); extern DIR *globus_libc_opendir(char *filename); extern long globus_libc_telldir(DIR *dirp); @@ -130,6 +131,7 @@ #define globus_libc_close close #define globus_libc_read read #define globus_libc_write write +#define globus_libc_umask umask #if defined(HAVE_WRITEV) #define globus_libc_writev writev #else @@ -160,10 +162,17 @@ struct dirent ** result); #else /* TARGET_ARCH_WIN32 */ + +extern +mode_t +globus_libc_umask_win32( + mode_t mask); + # define globus_libc_open _open # define globus_libc_close _close # define globus_libc_read _read # define globus_libc_write _write +# define globus_libc_umask globus_libc_umask_win32 # define globus_libc_writev(fd,iov,iovcnt) \ write(fd,iov[0].iov_base,iov[0].iov_len) # define uid_t int diff -ur globus_gssapi_gsi-4.9.orig/library/globus_i_gsi_gss_utils.c globus_gssapi_gsi-4.9/library/globus_i_gsi_gss_utils.c --- globus_gssapi_gsi-4.9.orig/library/globus_i_gsi_gss_utils.c 2005-05-04 02:19:37.000000000 +0200 +++ globus_gssapi_gsi-4.9/library/globus_i_gsi_gss_utils.c 2006-11-21 23:52:15.000000000 +0100 @@ -15,11 +15,11 @@ * @author Sam Lang, Sam Meder * * $RCSfile: globus_i_gsi_gss_utils.c,v $ - * $Revision: 1.38.4.1 $ - * $Date: 2005/05/04 00:19:37 $ + * $Revision: 1.38.4.1.4.2 $ + * $Date: 2006/11/07 00:37:47 $ */ -static char *rcsid = "$Id: globus_i_gsi_gss_utils.c,v 1.38.4.1 2005/05/04 00:19:37 meder Exp $"; +static char *rcsid = "$Id: globus_i_gsi_gss_utils.c,v 1.38.4.1.4.2 2006/11/07 00:37:47 kettimut Exp $"; #include "gssapi_openssl.h" #include "globus_i_gsi_gss_utils.h" @@ -2075,6 +2075,13 @@ goto exit; } + /* + * post-0.9.8 versions of the SSL library seem to move part of the + * cipher setup code into SSL_library_init(). Without this call, the + * SSL_CTX_new routine comaplains at not being able to initialize the + * list of ciphers. + */ + SSL_library_init(); cred_handle->ssl_context = SSL_CTX_new(SSLv23_method()); if(cred_handle->ssl_context == NULL) { @@ -2132,8 +2139,20 @@ */ SSL_CTX_set_purpose(cred_handle->ssl_context, X509_PURPOSE_ANY); + /* + * post OpenSSL-0.9.8, existence of this call creates problem when + * the server (for eg. GridFTP server) is run as a user and thus the + * cert presented is proxy cert. As the OpenSSL code does not + * recognize Globus legacy proxies, we need to explicitly set the + * proxy flag in the cert and we do it only when our callback is + * called by OpenSSL with the critical extension error, so this call + * is removed for post OpenSSL-0.9.8. + */ + + #if (OPENSSL_VERSION_NUMBER < 0x0090707fL) X509_STORE_set_flags(SSL_CTX_get_cert_store(cred_handle->ssl_context), X509_V_FLAG_IGNORE_CRITICAL); + #endif if(anon_ctx != GLOBUS_I_GSI_GSS_ANON_CONTEXT) { diff -ur globus_gsi_sysconfig-1.20.orig/library/globus_gsi_system_config.c globus_gsi_sysconfig-1.20/library/globus_gsi_system_config.c --- globus_gsi_sysconfig-1.20.orig/library/globus_gsi_system_config.c 2006-08-01 17:28:02.000000000 +0200 +++ globus_gsi_sysconfig-1.20/library/globus_gsi_system_config.c 2006-11-21 23:52:15.000000000 +0100 @@ -15,8 +15,8 @@ * @author Sam Lang, Sam Meder * * $RCSfile: globus_gsi_system_config.c,v $ - * $Revision: 1.73.4.3 $ - * $Date: 2006/08/01 15:28:02 $ + * $Revision: 1.73.4.4 $ + * $Date: 2006/10/03 23:13:32 $ */ #endif @@ -3764,13 +3764,16 @@ char * filename) { globus_result_t result = GLOBUS_SUCCESS; - int fd = -1; + int fd = -1; + mode_t oldmask; struct stat stx, stx2; static char * _function_name_ = "globus_gsi_sysconfig_set_key_permissions_unix"; GLOBUS_I_GSI_SYSCONFIG_DEBUG_ENTER; - if((fd = open(filename, O_RDONLY|O_CREAT|O_NONBLOCK)) < 0) + oldmask = globus_libc_umask(0077); + if((fd = globus_libc_open( + filename, O_RDONLY|O_CREAT|O_EXCL, S_IRUSR|S_IWUSR)) < 0) { result = globus_error_put( globus_error_wrap_errno_error( @@ -3858,6 +3861,7 @@ close(fd); } + globus_libc_umask(oldmask); GLOBUS_I_GSI_SYSCONFIG_DEBUG_EXIT; return result; } diff -ur globus_gsi_credential-1.9.orig/library/globus_gsi_credential.c globus_gsi_credential-1.9/library/globus_gsi_credential.c --- globus_gsi_credential-1.9.orig/library/globus_gsi_credential.c 2006-07-31 20:21:42.000000000 +0200 +++ globus_gsi_credential-1.9/library/globus_gsi_credential.c 2006-11-21 23:52:15.000000000 +0100 @@ -15,8 +15,8 @@ * @author Sam Lang, Sam Meder * * $RCSfile: globus_gsi_credential.c,v $ - * $Revision: 1.36.4.1 $ - * $Date: 2006/07/31 18:21:42 $ + * $Revision: 1.36.4.2 $ + * $Date: 2006/10/03 23:13:32 $ */ #endif @@ -1590,12 +1590,20 @@ { globus_result_t result = GLOBUS_SUCCESS; BIO * proxy_bio = NULL; + mode_t oldmask; + FILE * temp_proxy_fp = NULL; + int temp_proxy_fd = -1; static char * _function_name_ = "globus_gsi_cred_write_proxy"; GLOBUS_I_GSI_CRED_DEBUG_ENTER; + /* + * For systems that does not support a third (mode) argument in open() + */ + oldmask = globus_libc_umask(0077); + if(handle == NULL) { GLOBUS_GSI_CRED_ERROR_RESULT( @@ -1605,8 +1613,22 @@ goto exit; } - result = GLOBUS_GSI_SYSCONFIG_SET_KEY_PERMISSIONS(proxy_filename); - if(result != GLOBUS_SUCCESS) + /* + * We always unlink the file first; it is the only way to be + * certain that the file we open has never in its entire lifetime + * had the world-readable bit set. + */ + unlink(proxy_filename); + + /* + * Now, we must open w/ O_EXCL to make certain that WE are + * creating the file, so we know that the file was BORN w/ mode 0600. + * As a bonus, O_EXCL flag will cause a failure in the presence + * of a symlink, so we are safe from zaping a file due to the + * presence of a symlink. + */ + if ((temp_proxy_fd = globus_libc_open( + proxy_filename, O_WRONLY|O_EXCL|O_CREAT, S_IRUSR|S_IWUSR)) < 0) { GLOBUS_GSI_CRED_ERROR_CHAIN_RESULT( result, @@ -1614,15 +1636,35 @@ goto exit; } - if(!(proxy_bio = BIO_new_file(proxy_filename, "w"))) + /* Finally, we have a safe fd. Make it a stream like ssl wants. */ + temp_proxy_fp = fdopen(temp_proxy_fd,"w"); + + /* Hand the stream over to ssl */ + if( !(temp_proxy_fp) || + !(proxy_bio = BIO_new_fp(temp_proxy_fp, BIO_CLOSE))) { GLOBUS_GSI_CRED_OPENSSL_ERROR_RESULT( result, GLOBUS_GSI_CRED_ERROR_WRITING_PROXY_CRED, (_GCRSL("Can't open bio stream for writing to file: %s"), proxy_filename)); + if ( temp_proxy_fp ) + { + fclose(temp_proxy_fp); + } + else if (temp_proxy_fd >= 0 ) + { + /* close underlying fd if we do not have a stream */ + close(temp_proxy_fd); + } + goto exit; } + /* + * Note: at this point, calling BIO_free(proxy_bio) will + * fclose the temp_proxy_fp, which in turn should close temp_proxy_fd. + */ + result = globus_gsi_cred_write(handle, proxy_bio); if(result != GLOBUS_SUCCESS) { @@ -1649,6 +1691,7 @@ exit: + globus_libc_umask(oldmask); GLOBUS_I_GSI_CRED_DEBUG_EXIT; return result; } diff -ur globus_gsi_credential-1.9.orig/library/globus_gsi_cred_handle.c globus_gsi_credential-1.9/library/globus_gsi_cred_handle.c --- globus_gsi_credential-1.9.orig/library/globus_gsi_cred_handle.c 2006-02-27 18:19:10.000000000 +0100 +++ globus_gsi_credential-1.9/library/globus_gsi_cred_handle.c 2006-11-21 23:52:15.000000000 +0100 @@ -15,8 +15,8 @@ * @author Sam Lang, Sam Meder * * $RCSfile: globus_gsi_cred_handle.c,v $ - * $Revision: 1.28.4.3 $ - * $Date: 2006/02/27 17:19:10 $ + * $Revision: 1.28.4.3.2.2 $ + * $Date: 2006/11/07 00:37:46 $ */ #endif @@ -1721,7 +1721,18 @@ store_context, callback_data_index, (void *)callback_data); - + + /* + * If this is not set, OpenSSL-0.9.8 (check_chain_extensions() + * called by x509_verify_cert()) treats the cert next to proxy + * in the chain to be CA cert and throws invalid CA error + */ + + #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) + X509_STORE_CTX_set_flags( + store_context, X509_V_FLAG_ALLOW_PROXY_CERTS); + #endif + if(!X509_verify_cert(store_context)) { globus_result_t callback_error; diff -ur globus_gsi_callback-0.23.orig/library/globus_gsi_callback.c globus_gsi_callback-0.23/library/globus_gsi_callback.c --- globus_gsi_callback-0.23.orig/library/globus_gsi_callback.c 2005-05-27 02:12:40.000000000 +0200 +++ globus_gsi_callback-0.23/library/globus_gsi_callback.c 2006-11-21 23:52:15.000000000 +0100 @@ -16,8 +16,8 @@ * @author Sam Meder, Sam Lang * * $RCSfile: globus_gsi_callback.c,v $ - * $Revision: 1.30.4.1 $ - * $Date: 2005/05/27 00:12:40 $ + * $Revision: 1.30.4.1.4.2 $ + * $Date: 2006/11/07 00:37:44 $ */ #endif @@ -375,6 +375,22 @@ * we want to override so we can replace some of the checks. */ context->check_issued = globus_gsi_callback_check_issued; + /* + * If this is not set, OpenSSL-0.9.8 assumes the proxy cert + * as an EEC and the next level cert in the chain as a CA cert + * and throws an invalid CA error. If we set this, the callback + * (globus_gsi_callback_handshake_callback) gets called with + * preverify_ok = 0 with an error "unhandled critical extension" + * and "path length exceeded". + * globus_i_gsi_callback_cred_verify() called by + * globus_gsi_callback_handshake_callback() checks for these + * errors and returns success. globus_i_gsi_callback_cred_verify() + * will check the critical extension later. + */ + #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) + X509_STORE_CTX_set_flags( + context, X509_V_FLAG_ALLOW_PROXY_CERTS); + #endif result = X509_verify_cert(context); GLOBUS_I_GSI_CALLBACK_DEBUG_EXIT; @@ -626,7 +642,9 @@ X509_STORE_CTX * x509_context) { globus_result_t result = GLOBUS_SUCCESS; + globus_gsi_cert_utils_cert_type_t cert_type; X509 * tmp_cert = NULL; + X509 * prev_cert = NULL; static char * _function_name_ = "globus_i_gsi_callback_cred_verify"; @@ -641,6 +659,14 @@ { case X509_V_ERR_PATH_LENGTH_EXCEEDED: + /* + * OpenSSL-0.9.8 has this error (0.9.7d did not have this) + * So we will ignore the errors now and do our checks later + * on (as explained below). + */ + #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) + case X509_V_ERR_PROXY_PATH_LENGTH_EXCEEDED: + GLOBUS_I_GSI_CALLBACK_DEBUG_PRINT( 2, "X509_V_ERR_PATH_LENGTH_EXCEEDED\n"); /* @@ -652,7 +678,74 @@ */ result = GLOBUS_SUCCESS; break; - + #endif + #if (OPENSSL_VERSION_NUMBER >= 0x0090706fL) + /* + * In the later version (097g+) OpenSSL does know about + * proxies, but not non-rfc compliant proxies, it will + * count them as unhandled critical extensions. + * So we will ignore the errors and do our + * own checks later on, when we check the last + * certificate in the chain we will check the chain. + * As OpenSSL does not recognize legacy proxies + */ + case X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION: + GLOBUS_I_GSI_CALLBACK_DEBUG_PRINT( + 2, "X509_V_ERR_UNHANDLED_CRITICAL_EXTENSION\n"); + /* + * Setting this for 098 or later versions avoid the invalid + * CA error but would result in proxy path len exceeded which + * is handled above. For versions less than 098 and greater + * than or equal to 097g causes a seg fault in + * check_chain_extensions (line 498 in crypto/x509/x509_vfy.c) + * If this flag is set, openssl assumes proxy extensions would + * definitely be there and tries to access the extensions but + * the extension is not there really, as it not recognized by + * openssl. So openssl versions >= 097g and < 098 would + * consider our proxy as an EEC and higher level proxy in the + * cert chain (if any) or EEC as a CA cert and thus would throw + * as invalid CA error. We handle that error below. + */ + #if (OPENSSL_VERSION_NUMBER >= 0x0090800fL) + x509_context->current_cert->ex_flags |= EXFLAG_PROXY; + #endif + result = GLOBUS_SUCCESS; + break; + #endif + + #if (OPENSSL_VERSION_NUMBER < 0x0090800fL) + #if (OPENSSL_VERSION_NUMBER >= 0x0090706fL) + case X509_V_ERR_INVALID_CA: + /* + * If the previous cert in the chain is a proxy cert then + * we get this error just because openssl does not recognize + * our proxy and treats it as an EEC. And thus, it would + * treat higher level proxies (if any) or EEC as CA cert + * (which are not actually CA certs) and would throw this + * error. As long as the previous cert in the chain is a + * proxy cert, we ignore this error. + */ + prev_cert = sk_X509_value( + x509_context->chain, x509_context->error_depth-1); + result = globus_gsi_cert_utils_get_cert_type(prev_cert, &cert_type); + if(result != GLOBUS_SUCCESS) + { + result = (globus_result_t)GLOBUS_FAILURE; + } + else + { + if(GLOBUS_GSI_CERT_UTILS_IS_PROXY(cert_type)) + { + result = GLOBUS_SUCCESS; + } + else + { + result = (globus_result_t)GLOBUS_FAILURE; + } + } + break; + #endif + #endif default: result = (globus_result_t)GLOBUS_FAILURE; break;