📄 certauth_extensions.c
字号:
/* * CA extension implementation file * */#include "myproxy_common.h"#define BUF_SIZE 16384#ifndef MIN#define MIN(x,y) ((x) < (y) ? (x) : (y))#endif#define SECONDS_PER_HOUR (60 * 60)static int read_cert_request(GSI_SOCKET *self, unsigned char **buffer, size_t *length) { int return_value = 1; unsigned char * input_buffer = NULL; size_t input_buffer_length; if (self == NULL) { verror_put_string("read_cert_request(): Socket is null"); goto error; } if (GSI_SOCKET_read_token(self, &input_buffer, &input_buffer_length) == GSI_SOCKET_ERROR) { verror_put_string("read_cert_request(): Read from socket failed"); goto error; } *buffer = input_buffer; *length = input_buffer_length; return_value = 0; error: if ( return_value ) { if ( input_buffer != NULL ) { myproxy_debug("freeing buffer"); free(input_buffer); input_buffer = NULL; } } return return_value;}static int send_certificate(GSI_SOCKET *self, unsigned char *buffer, size_t length) { if (GSI_SOCKET_write_buffer(self, (const char *)buffer, length) == GSI_SOCKET_ERROR) { verror_put_string("Error writing certificate to client!"); return 1; } return 0;}static void add_key_value( char * key, char * value, char buffer[] ) { strcat( buffer, key ); strcat( buffer, "=" ); if ( value == NULL ) { strcat( buffer, "NULL" ); } else { strcat( buffer, value ); } strcat( buffer, "\n" );}static int external_callout( X509_REQ *request, X509 **cert, myproxy_request_t *client_request, myproxy_server_context_t *server_context) { int return_value = 1; char buffer[BUF_SIZE]; char intbuf[128]; pid_t pid; int p0[2], p1[2], p2[2]; int status; FILE * pipestream = NULL; X509 * certificate = NULL; memset(buffer, '\0', BUF_SIZE); memset(intbuf, '\0', 128); myproxy_debug("callout using: %s", server_context->certificate_issuer_program); /* create pipe */ if ( pipe(p0) < 0 || pipe(p1) < 0 || pipe(p2) < 0 ) { verror_put_string("pipe() failed"); verror_put_errno(errno); goto error; } /* create child */ if ( (pid = fork()) < 0 ) { verror_put_string("fork() failed"); verror_put_errno(errno); goto error; } /* attach pipes to appropriate streams in child and exec */ if (pid == 0) { close(p0[1]); close(p1[0]); close(p2[0]); dup2(p0[0], 0); /*in*/ dup2(p1[1], 1); /*out*/ dup2(p2[1], 2); /*error*/ execl(server_context->certificate_issuer_program, server_context->certificate_issuer_program, NULL); perror("exec"); fprintf(stderr, "failed to run %s: %s\n", server_context->certificate_issuer_program, strerror(errno)); exit(1); } /* close unused pipes on the parent side */ close(p0[0]); close(p1[1]); close(p2[1]); /* writing to program */ pipestream = fdopen( p0[1], "w" ); if ( pipestream == NULL ) { verror_put_string("File stream to stdin pipe creation problem."); return 1; } add_key_value( "username", client_request->username, buffer ); add_key_value( "passphrase", client_request->passphrase, buffer ); sprintf( intbuf, "%d", client_request->proxy_lifetime ); add_key_value( "proxy_lifetime", (char*)intbuf, buffer ); memset(intbuf, '\0', 128); add_key_value( "retrievers", client_request->retrievers, buffer ); add_key_value( "renewers", client_request->renewers, buffer ); add_key_value( "credname", client_request->credname, buffer ); add_key_value( "creddesc", client_request->creddesc, buffer ); add_key_value( "authzcreds", client_request->authzcreds, buffer ); add_key_value( "keyretrieve", client_request->keyretrieve, buffer ); add_key_value( "trusted_retrievers", client_request->trusted_retrievers, buffer ); sprintf( intbuf, "%d", server_context->max_cert_lifetime ); add_key_value( "max_cert_lifetime", (char*)intbuf, buffer ); memset(intbuf, '\0', 128); fprintf( pipestream, "%s\n", buffer ); PEM_write_X509_REQ( pipestream, request ); fflush( pipestream ); fclose( pipestream ); close(p0[1]); /* wait for program to exit */ if( waitpid(pid, &status, 0) == -1 ) { verror_put_string("waitpid() failed for external callout child"); verror_put_errno(errno); goto error; } /* check status and read appropriate content */ /* if exit != 0 - read and log message from program stderr */ if ( status != 0 ) { verror_put_string("external process exited abnormally\n"); memset(buffer, '\0', BUF_SIZE); if ( read( p2[0], buffer, BUF_SIZE ) > 0 ) { verror_put_string(buffer); } else { verror_put_string("did not recieve an error string from callout"); } goto error; } /* retrieve the certificate */ pipestream = fdopen( p1[0], "r" ); if ( pipestream == NULL ) { verror_put_string("File stream to stdout pipe creation problem."); goto error; } certificate = PEM_read_X509( pipestream, NULL, NULL, NULL ); if (certificate == NULL) { verror_put_string("Error reading certificate from external program."); goto error; } else { myproxy_debug("Recieved certificate from external callout."); } fclose( pipestream ); close(p1[0]); close(p2[0]); /* good to go */ *cert = certificate; return_value = 0; error: memset(buffer, '\0', BUF_SIZE); memset(intbuf, '\0', 128); return return_value;}static int tokenize_to_x509_name( char * dn, X509_NAME * name ) { int return_value = 0; char * tmp; char * tok; char * tmpTok = NULL; char * subtok; char * toksplit; int i; myproxy_debug( "tokenizing: %s", dn ); tmp = strdup(dn); tok = strtok( tmp, "/" ); while ( tok != NULL ) { subtok = strchr( tok, '=' ); toksplit = subtok; subtok++; *toksplit = '\0'; /* if short prefixes are being used, they need to be capped before feeding to the add entry function. tok must be strdup()ed because messing with the strtok() buffer is bad. */ tmpTok = strdup( tok ); if ( strlen( tmpTok ) < 3 ) { i = 0; while( i < strlen( tmpTok ) ) { tmpTok[i] = toupper( tmpTok[i] ); i = i + 1; } } myproxy_debug( "adding: %s = %s", tmpTok, subtok ); if (!X509_NAME_add_entry_by_txt( name, tmpTok, MBSTRING_ASC, (unsigned char *) subtok, -1, -1, 0 )) { verror_put_string("Error adding %s = %s to x509 name", tmpTok, subtok ); verror_put_string("Invalid field name"); return_value = 1; goto end; } subtok = NULL; toksplit = NULL; free( tmpTok ); tmpTok = NULL; tok = strtok( NULL, "/" ); } end: free(tmp); return return_value;}/* Use fcntl() for POSIX file locking. Lock is released when file is closed. */static intlock_file(int fd){ struct flock fl; fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; fl.l_start = 0; fl.l_len = 0; while( fcntl( fd, F_SETLKW, &fl ) < 0 ) { if ( errno != EINTR ) { return -1; } } return 0;}/* * serial number handling liberally borrowed from KCA with the addition * of file locking */static int assign_serial_number( X509 *cert, myproxy_server_context_t *server_context ) { int increment = 1; int retval = 1; long serialset; BIGNUM * serial = NULL; ASN1_INTEGER * current = NULL, * next = NULL; char buf[1024]; char *serialfile = NULL; /* all the io variables */ BIO * serialbio = NULL; int fd; FILE * serialstream = NULL; myproxy_debug("Assigning serial number"); serial = BN_new(); current = ASN1_INTEGER_new(); if ( (serial ==NULL) || (current==NULL) ) { verror_put_string("Bignum/asn1 INT init failure\n"); goto error; } if (server_context->certificate_serialfile) { serialfile = server_context->certificate_serialfile; } else { const char *sdir; sdir = myproxy_get_storage_dir(); if (sdir == NULL) { goto error; } serialfile = malloc(strlen(sdir)+strlen("/serial")+1); sprintf(serialfile, "%s/serial", sdir); } /* open(), lock, open stream and create BIO */ fd = open( serialfile, O_RDWR|O_CREAT, 0600 ); if ( fd == -1 ) { verror_put_string("Call to open() failed on %s\n", serialfile); goto error; } if ( lock_file(fd) == -1 ) { verror_put_string("Failed to get lock on file descriptor\n"); verror_put_errno(errno); goto error; } serialstream = fdopen( fd, "w+" ); if ( serialstream == NULL ) { verror_put_string("Unable to open file stream\n"); goto error; } /* check if file is empty, and if so, initialize with 1 */ if (fseek(serialstream, 0L, SEEK_END) < 0) { verror_put_string("Unable to seek file stream\n"); goto error; } serialset = ftell(serialstream); if (serialset) rewind(serialstream); serialbio = BIO_new_fp( serialstream, BIO_CLOSE ); if ( serialbio == NULL ) { verror_put_string("BIO_new_fp failure.\n"); goto error; } if (serialset) { if (!a2i_ASN1_INTEGER(serialbio, current, buf, sizeof(buf))) { verror_put_string("Asn1 int read/conversion error\n"); goto error; } else { myproxy_debug("Loaded serial number %s from %s", buf, serialfile); } } else { ASN1_INTEGER_set(current, 1); } serial = BN_bin2bn( current->data, current->length, serial ); if ( serial == NULL ) { verror_put_string("Error converting to bignum\n"); goto error; } if (!BN_add_word(serial, increment)) { verror_put_string("Error incrementing serial number\n"); goto error; } if (!(next = BN_to_ASN1_INTEGER(serial, NULL))) { verror_put_string("Error converting new serial to ASN1\n"); goto error; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -