static int retr_proxy( SNET *sn, char *login, SNET *pushersn ) { char cookiebuf[ 128 ], lpath[ MAXPATHLEN ]; char cbuf[ MAXCOOKIELEN ], spath[ MAXPATHLEN ]; struct proxies *proxy; int rc; /* S: 241-[cookiename] [hostname to use cookie with] * S: 241- ... * S: 241 Cookies registered and sent. */ if (( al->al_flag & AL_PROXY ) == 0 ) { syslog( LOG_ERR, "%s cannot retrieve cookies", al->al_hostname ); snet_writef( sn, "%d RETR: %s cannot retrieve cookies.\r\n", 443, al->al_hostname ); return( 1 ); } for ( proxy = al->al_proxies; proxy != NULL; proxy = proxy->pr_next ) { if ( mkcookie( sizeof( cookiebuf ), cookiebuf ) != 0 ) { syslog( LOG_ERR, "retr_proxy: mkcookie error" ); return( -1 ); } if ( snprintf( cbuf, sizeof( cbuf ), "%s=%s", proxy->pr_cookie, cookiebuf ) >= sizeof( cbuf )) { syslog( LOG_ERR, "retr_proxy: full cookie too long" ); return( -1 ); } if ( mkcookiepath( NULL, hashlen, cbuf, spath, sizeof( spath )) < 0 ) { syslog( LOG_ERR, "retr_proxy: mkcookiepath error" ); return( 1 ); } if ( mkcookiepath( NULL, hashlen, login, lpath, sizeof( lpath )) < 0 ) { syslog( LOG_ERR, "retr_proxy: mkcookiepath error" ); return( 1 ); } if (( rc = do_register( login, lpath, spath )) < 0 ) { continue; } if (( pushersn != NULL ) && ( !replicated )) { snet_writef( pushersn, "REGISTER %s - %s\r\n", login, cbuf ); } snet_writef( sn, "%d-%s %s\r\n", 241, cbuf, proxy->pr_hostname ); } snet_writef( sn, "%d Cookies registered and sent\r\n", 241 ); return( 0 ); }
int f_check( SNET *sn, int ac, char *av[], SNET *pushersn ) { struct cinfo ci; struct timeval tv; char login[ MAXCOOKIELEN ], path[ MAXPATHLEN ]; char rekeybuf[ 128 ], rcookie[ 256 ], scpath[ MAXPATHLEN ]; char *p; int status; double rate; /* * C: CHECK servicecookie * S: 231 ip principal realm */ /* * C: CHECK logincookie * S: 232 ip principal realm */ /* * C: REKEY servicecookie * S: 233 ip principal realm rekeyed-cookie */ if (( al->al_key != CGI ) && ( al->al_key != SERVICE )) { syslog( LOG_ERR, "f_check: %s not allowed", al->al_hostname ); snet_writef( sn, "%d %s: %s not allowed to check.\r\n", 430, av[ 0 ], al->al_hostname ); return( 1 ); } if ( ac < 2 || ac > 3 ) { syslog( LOG_ERR, "f_check: %s: wrong number of args. " "Expected 2 or 3, got %d", al->al_hostname, ac ); snet_writef( sn, "%d %s: Wrong number of args.\r\n", 530, av[ 0 ] ); return( 1 ); } if ( mkcookiepath( NULL, hashlen, av[ 1 ], path, sizeof( path )) < 0 ) { syslog( LOG_ERR, "f_check: mkcookiepath error" ); snet_writef( sn, "%d %s: Invalid cookie name.\r\n", 531, av[ 0 ] ); return( 1 ); } if ( strncmp( av[ 1 ], "cosign-", 7 ) == 0 ) { if ( strict_checks && service_valid( av[ 1 ] ) == NULL ) { snet_writef( sn, "%d %s: Invalid cookie\r\n", 534, av[ 0 ] ); return( 1 ); } status = 231; if ( service_to_login( path, login ) != 0 ) { if (( rate = rate_tick( &checkunknown )) != 0.0 ) { syslog( LOG_NOTICE, "STATS CHECK %s: UNKNOWN %.5f / sec", inet_ntoa( cosign_sin.sin_addr), rate ); } snet_writef( sn, "%d %s: cookie not in db!\r\n", 533, av[ 0 ] ); return( 1 ); } if ( COSIGN_PROTO_SUPPORTS_REKEY( protocol )) { if ( strcasecmp( av[ 0 ], "REKEY" ) == 0 ) { /* save service cookie path for rekeying below. */ if ( strlen( path ) >= sizeof( scpath )) { syslog( LOG_ERR, "f_check: %s exceeds bounds.", path ); snet_writef( sn, "%d %s: Invalid cookie name.\r\n", 531, av[ 0 ]); return( 1 ); } strcpy( scpath, path ); status = 233; } } if ( mkcookiepath( NULL, hashlen, login, path, sizeof( path )) < 0 ) { syslog( LOG_ERR, "f_check: mkcookiepath error.." ); snet_writef( sn, "%d %s: Invalid cookie name.\r\n", 532, av[ 0 ] ); return( 1 ); } } else if ( strncmp( av[ 1 ], "cosign=", 7 ) == 0 ) { status = 232; } else { syslog( LOG_ERR, "f_check: unknown cookie prefix." ); snet_writef( sn, "%d %s: unknown cookie prefix!\r\n", 432, av[ 0 ] ); return( 1 ); } if ( read_cookie( path, &ci ) != 0 ) { if (( rate = rate_tick( &checkunknown )) != 0.0 ) { syslog( LOG_NOTICE, "STATS CHECK %s: UNKNOWN %.5f / sec", inet_ntoa( cosign_sin.sin_addr), rate); } snet_writef( sn, "%d %s: Who me? Dunno.\r\n", 534, av[ 0 ] ); return( 1 ); } if ( ci.ci_state == 0 ) { if (( rate = rate_tick( &checkfail )) != 0.0 ) { syslog( LOG_NOTICE, "STATS CHECK %s: FAIL %.5f / sec", inet_ntoa( cosign_sin.sin_addr), rate); } snet_writef( sn, "%d %s: Already logged out\r\n", 430, av[ 0 ] ); return( 1 ); } /* check for idle timeout, and if so, log'em out */ if ( gettimeofday( &tv, NULL ) != 0 ){ syslog( LOG_ERR, "f_check: gettimeofday: %m" ); return( -1 ); } if ( tv.tv_sec - ci.ci_itime >= idle_out_time ) { if ( tv.tv_sec - ci.ci_itime < ( idle_out_time + grey_time )) { if (( rate = rate_tick( &checkunknown )) != 0.0 ) { syslog( LOG_NOTICE, "STATS CHECK %s: UNKNOWN %.5f / sec", inet_ntoa( cosign_sin.sin_addr ), rate ); } syslog( LOG_NOTICE, "f_check: idle grey window" ); snet_writef( sn, "%d %s: Idle Grey Window\r\n", 531, av[ 0 ] ); return( 1 ); } if (( rate = rate_tick( &checkfail )) != 0.0 ) { syslog( LOG_NOTICE, "STATS CHECK %s: FAIL %.5f / sec", inet_ntoa( cosign_sin.sin_addr), rate); } snet_writef( sn, "%d %s: Idle logged out\r\n", 431, av[ 0 ] ); if ( do_logout( path ) < 0 ) { syslog( LOG_ERR, "f_check: %s: %m", login ); return( -1 ); } return( 1 ); } /* prevent idle out if we are actually using it */ utime( path, NULL ); if (( rate = rate_tick( &checkpass )) != 0.0 ) { syslog( LOG_NOTICE, "STATS CHECK %s: PASS %.5f / sec", inet_ntoa( cosign_sin.sin_addr), rate); } if ( status == 233 ) { /* rekey service cookie. */ if ( mkcookie( sizeof( rekeybuf ), rekeybuf ) != 0 ) { syslog( LOG_ERR, "f_check: rekey: mkcookie failed" ); snet_writef( sn, "%d %s: rekey failed.\r\n", 536, av[ 0 ] ); return( 1 ); } if (( p = strchr( av[ 1 ], '=' )) == NULL ) { syslog( LOG_ERR, "f_check: rekey: bad service name \"%s\".", av[1]); snet_writef( sn, "%d %s rekey failed.\r\n", 536, av[ 0 ] ); return( 1 ); } *p = '\0'; if ( snprintf( rcookie, sizeof( rcookie ), "%s=%s", av[ 1 ], rekeybuf ) >= sizeof( rcookie )) { syslog( LOG_ERR, "f_check: rekey: new cookie too long." ); snet_writef( sn, "%d %s rekey failed.\r\n", 536, av[ 0 ] ); return( 1 ); } *p = '='; if ( mkcookiepath( NULL, hashlen, rcookie, path, sizeof( path )) < 0 ) { syslog( LOG_ERR, "f_check: rekey: mkcookiepath error." ); snet_writef( sn, "%d %s: rekey failed.\r\n", 536, av[ 0 ] ); return( 1 ); } if ( rename( scpath, path ) != 0 ) { syslog( LOG_ERR, "f_check: rekey: rename %s to %s failed: %s.", scpath, path, strerror( errno )); snet_writef( sn, "%d %s: rekey failed.\r\n", 536, av[ 0 ] ); return( 1 ); } } if ( COSIGN_PROTO_SUPPORTS_FACTORS( protocol )) { snet_writef( sn, "%d %s %s %s %s\r\n", status, ci.ci_ipaddr_cur, ci.ci_user, ci.ci_realm, ( status == 233 ? rcookie : "" )); } else { /* if there is more than one realm, we just give the first */ if (( p = strtok( ci.ci_realm, " " )) != NULL ) { snet_writef( sn, "%d %s %s %s\r\n", status, ci.ci_ipaddr, ci.ci_user, p ); } else { snet_writef( sn, "%d %s %s %s\r\n", status, ci.ci_ipaddr, ci.ci_user, ci.ci_realm ); } } return( 0 ); }
int f_login( SNET *sn, int ac, char *av[], SNET *pushersn ) { FILE *tmpfile; ACAV *facav; char tmppath[ MAXCOOKIELEN ], path[ MAXPATHLEN ]; char tmpkrb[ 16 ], krbpath [ MAXPATHLEN ]; char *sizebuf, *line; char buf[ 8192 ]; char **fv; int fd, i, j, fc, already_krb = 0; int krb = 0, err = 1, addinfo = 0, newinfo = 0; struct timeval tv; struct cinfo ci; unsigned int len, rc; extern int errno; /* * C: LOGIN login_cookie ip principal factor [factor2] * S: 200 LOGIN successful: Cookie Stored. */ /* * C: LOGIN login_cookie ip principal factor "kerberos" * S: 300 LOGIN: Send length then file. * C: [length] * C: [data] * C: . */ if ( al->al_key != CGI ) { syslog( LOG_ERR, "%s not allowed to login", al->al_hostname ); snet_writef( sn, "%d LOGIN: %s not allowed to login.\r\n", 400, al->al_hostname ); return( 1 ); } if ( ac < 5 ) { syslog( LOG_ERR, "f_login: got %d args, need at least 5", ac ); snet_writef( sn, "%d LOGIN: Wrong number of args.\r\n", 500 ); return( 1 ); } if ( ac >= 6 ) { if ( strcmp( av[ ac - 1 ], "kerberos" ) == 0 ) { krb = 1; ac--; if ( mkcookie( sizeof( tmpkrb ), tmpkrb ) != 0 ) { syslog( LOG_ERR, "f_login: mkcookie error." ); return( -1 ); } if ( snprintf( krbpath, sizeof( krbpath ), "%s/%s", cosign_tickets, tmpkrb ) >= sizeof( krbpath )) { syslog( LOG_ERR, "f_login: krbpath too long." ); return( -1 ); } } } if ( mkcookiepath( NULL, hashlen, av[ 1 ], path, sizeof( path )) < 0 ) { syslog( LOG_ERR, "f_login: mkcookiepath error" ); snet_writef( sn, "%d LOGIN: Invalid cookie path.\r\n", 501 ); return( 1 ); } if ( read_cookie( path, &ci ) == 0 ) { addinfo = 1; if ( ci.ci_state == 0 ) { syslog( LOG_ERR, "f_login: %s already logged out", av[ 1 ] ); snet_writef( sn, "%d LOGIN: Already logged out\r\n", 505 ); return( 1 ); } if ( strcmp( av[ 3 ], ci.ci_user ) != 0 ) { syslog( LOG_ERR, "%s in cookie %s does not match %s", ci.ci_user, av[ 1 ], av[ 3 ] ); snet_writef( sn, "%d user name given does not match cookie\r\n", 402 ); return( 1 ); } } if ( gettimeofday( &tv, NULL ) != 0 ) { syslog( LOG_ERR, "f_login: gettimeofday: %m" ); return( -1 ); } if ( snprintf( tmppath, sizeof( tmppath ), "%x%x.%i", (int)tv.tv_sec, (int)tv.tv_usec, (int)getpid()) >= sizeof( tmppath )) { syslog( LOG_ERR, "f_login: tmppath too long" ); return( -1 ); } if (( fd = open( tmppath, O_CREAT|O_EXCL|O_WRONLY, 0644 )) < 0 ) { syslog( LOG_ERR, "f_login: open: %s: %m", tmppath ); return( -1 ); } if (( tmpfile = fdopen( fd, "w" )) == NULL ) { /* close */ if ( unlink( tmppath ) != 0 ) { syslog( LOG_ERR, "f_login: unlink: %m" ); } syslog( LOG_ERR, "f_login: fdopen: %m" ); return( -1 ); } fprintf( tmpfile, "v2\n" ); fprintf( tmpfile, "s1\n" ); /* 1 is logged in, 0 is logged out */ if ( strlen( av[ 2 ] ) >= sizeof( ci.ci_ipaddr )) { goto file_err; } if ( addinfo ) { fprintf( tmpfile, "i%s\n", ci.ci_ipaddr ); } else { fprintf( tmpfile, "i%s\n", av[ 2 ] ); } if ( addinfo ) { if ( strcmp( ci.ci_ipaddr_cur, av[ 2 ] ) != 0 ) { newinfo = 1; } } if ( strlen( av[ 2 ] ) >= sizeof( ci.ci_ipaddr_cur )) { goto file_err; } fprintf( tmpfile, "j%s\n", av[ 2 ] ); if ( strlen( av[ 3 ] ) >= sizeof( ci.ci_user )) { goto file_err; } fprintf( tmpfile, "p%s\n", av[ 3 ] ); if ( strlen( av[ 4 ] ) >= sizeof( ci.ci_realm )) { goto file_err; } if ( addinfo ) { if (( facav = acav_alloc()) == NULL ) { syslog( LOG_ERR, "acav_alloc: %m" ); goto file_err; } if (( fc = acav_parse( facav, ci.ci_realm, &fv )) < 0 ) { syslog( LOG_ERR, "acav_parse: %m" ); goto file_err; } fprintf( tmpfile, "r%s", fv[ 0 ] ); for ( i = 1; i < fc; i++ ) { fprintf( tmpfile, " %s", fv[ i ] ); } for ( i = 4; i < ac; i++ ) { for ( j = 0; j < fc; j++ ) { if ( strcmp( fv[ j ], av[ i ] ) == 0 ) { break; } } if ( j >= fc ) { fprintf( tmpfile, " %s", av[ i ] ); newinfo = 1; } } if ( newinfo == 0 ) { snet_writef( sn, "%d LOGIN Cookie Already Stored.\r\n", 202 ); if ( fclose ( tmpfile ) != 0 ) { syslog( LOG_ERR, "f_login: fclose: %m" ); } if ( unlink( tmppath ) != 0 ) { syslog( LOG_ERR, "f_login: unlink %s: %m", tmppath ); } return( 0 ); } } else { fprintf( tmpfile, "r%s", av[ 4 ] ); for ( i = 5; i < ac; i++ ) { fprintf( tmpfile, " %s", av[ i ] ); } } fprintf( tmpfile, "\n" ); if ( addinfo ) { fprintf( tmpfile, "t%lu\n", ci.ci_itime); } else { fprintf( tmpfile, "t%lu\n", tv.tv_sec ); } if ( krb ) { if (( addinfo ) && ( *ci.ci_krbtkt != '\0' )) { fprintf( tmpfile, "k%s\n", ci.ci_krbtkt ); already_krb = 1; } else { fprintf( tmpfile, "k%s\n", krbpath ); } } else if ( *ci.ci_krbtkt != '\0' ) { fprintf( tmpfile, "k%s\n", ci.ci_krbtkt ); already_krb = 1; } if ( fclose ( tmpfile ) != 0 ) { if ( unlink( tmppath ) != 0 ) { syslog( LOG_ERR, "f_login: unlink %s: %m", tmppath ); } syslog( LOG_ERR, "f_login: fclose: %m" ); return( -1 ); } if ( addinfo ) { if ( rename( tmppath, path ) != 0 ) { syslog( LOG_ERR, "f_login: rename %s to %s: %m", tmppath, path ); err = -1; goto file_err2; } } else { if ( link( tmppath, path ) != 0 ) { syslog( LOG_ERR, "f_login: link %s to %s: %m", tmppath, path ); err = -1; goto file_err2; } if ( unlink( tmppath ) != 0 ) { syslog( LOG_ERR, "f_login: unlink %s: %m", tmppath ); } } if (( !krb ) || ( already_krb )) { snet_writef( sn, "%d LOGIN successful: Cookie Stored.\r\n", 200 ); if (( pushersn != NULL ) && ( !replicated )) { snet_writef( pushersn, "LOGIN %s %s %s %s\r\n", av[ 1 ], av[ 2 ], av[ 3 ], av[ 4 ]); } if ( !replicated ) { syslog( LOG_INFO, "LOGIN %s %s %s", av[ 3 ], av [ 4 ], av [ 2 ] ); } return( 0 ); } snet_writef( sn, "%d LOGIN: Send length then file.\r\n", 300 ); if (( fd = open( krbpath, O_CREAT|O_EXCL|O_WRONLY, 0644 )) < 0 ) { syslog( LOG_ERR, "f_login: open: %s: %m", krbpath ); return( -1 ); } tv = cosign_net_timeout; if (( sizebuf = snet_getline( sn, &tv )) == NULL ) { syslog( LOG_ERR, "f_login: snet_getline: %m" ); return( -1 ); } for ( len = atoi( sizebuf ); len > 0; len -= rc ) { tv = cosign_net_timeout; if (( rc = snet_read( sn, buf, (int)MIN( len, sizeof( buf )), &tv )) <= 0 ) { syslog( LOG_ERR, "f_login: snet_read: %m" ); return( -1 ); } if ( write( fd, buf, rc ) != rc ) { syslog( LOG_ERR, "f_login: write to %s: %m", krbpath ); snet_writef( sn, "%d %s: %s\r\n", 504, krbpath, strerror( errno )); return( 1 ); } } if ( close( fd ) < 0 ) { syslog( LOG_ERR, "f_login: close %s: %m", krbpath ); snet_writef( sn, "%d %s: %s\r\n", 504, krbpath, strerror( errno )); return( 1 ); } tv = cosign_net_timeout; tv.tv_usec = 0; if (( line = snet_getline( sn, &tv )) == NULL ) { syslog( LOG_ERR, "f_login: snet_getline: %m" ); return( -1 ); } /* make sure client agrees we're at the end */ if ( strcmp( line, "." ) != 0 ) { snet_writef( sn, "%d Length doesn't match sent data\r\n", 505 ); (void)unlink( krbpath ); /* if the krb tkt didn't store, unlink the cookie as well */ if ( unlink( av[ 1 ] ) != 0 ) { syslog( LOG_ERR, "f_login: unlink: %m" ); } tv = cosign_net_timeout; tv.tv_usec = 0; for (;;) { if (( line = snet_getline( sn, &tv )) == NULL ) { syslog( LOG_ERR, "f_login: snet_getline: %m" ); exit( 1 ); } if ( strcmp( line, "." ) == 0 ) { break; } } exit( 1 ); } snet_writef( sn, "%d LOGIN successful: Cookie & Ticket Stored.\r\n", 201 ); if (( pushersn != NULL ) && ( !replicated )) { snet_writef( pushersn, "LOGIN %s %s %s %s %s\r\n", av[ 1 ], av[ 2 ], av[ 3 ], av[ 4 ], av[ 5 ]); } if ( !replicated ) { syslog( LOG_INFO, "LOGIN %s %s %s", av[ 3 ], av [ 4 ], av [ 2 ] ); } return( 0 ); file_err: (void)fclose( tmpfile ); if ( unlink( tmppath ) != 0 ) { syslog( LOG_ERR, "f_login: unlink: %m" ); } syslog( LOG_ERR, "f_login: bad file format" ); snet_writef( sn, "%d LOGIN Syntax Error: Bad File Format\r\n", 504 ); return( 1 ); file_err2: if ( unlink( tmppath ) != 0 ) { syslog( LOG_ERR, "f_login: unlink: %m" ); } return( err ); }
int cosign_login_krb5( struct connlist *head, char *cosignname, char *id, char *realm, char *passwd, char *ip_addr, char *cookie, struct subparams *sp, char **msg ) { krb5_error_code kerror = 0; krb5_context kcontext; krb5_principal kprinc; krb5_principal sprinc; krb5_get_init_creds_opt kopts; krb5_verify_init_creds_opt kvic_opts[ 1 ]; krb5_creds kcreds; krb5_ccache kccache; krb5_keytab keytab = 0; char *tmpl = ERROR_HTML; char *sprinc_name = NULL; char ktbuf[ MAX_KEYTAB_NAME_LEN + 1 ]; char tmpkrb[ 16 ], krbpath [ MAXPATHLEN ]; int i; lcgi_configure(); if (( kerror = krb5_init_context( &kcontext ))) { sl[ SL_ERROR ].sl_data = (char *)error_message( kerror ); sl[ SL_TITLE ].sl_data = "Authentication Required ( kerberos error )"; subfile( tmpl, sl, 0 ); exit( 0 ); } if (( kerror = krb5_parse_name( kcontext, id, &kprinc ))) { sl[ SL_ERROR ].sl_data = (char *)error_message( kerror ); sl[ SL_TITLE ].sl_data = "Authentication Required ( kerberos error )"; subfile( tmpl, sl, 0 ); exit( 0 ); } /* need to get realm out */ if ( realm == NULL || *realm == '\0' ) { if (( kerror = krb5_get_default_realm( kcontext, &realm )) != 0 ) { sl[ SL_ERROR ].sl_data = (char *)error_message( kerror ); sl[ SL_TITLE ].sl_data = "Authentication Required " "( krb realm error )"; subfile( tmpl, sl, 0 ); exit( 0 ); } } if ( store_tickets ) { if ( mkcookie( sizeof( tmpkrb ), tmpkrb ) != 0 ) { sl[ SL_ERROR ].sl_data = "An unknown error occurred."; sl[ SL_TITLE ].sl_data = "Authentication Required (kerberos error)"; subfile( tmpl, sl, 0 ); exit( 0 ); } if ( snprintf( krbpath, sizeof( krbpath ), "%s/%s", ticket_path, tmpkrb ) >= sizeof( krbpath )) { sl[ SL_ERROR ].sl_data = "An unknown error occurred."; sl[ SL_TITLE ].sl_data = "Authentication Required (krbpath error)"; subfile( tmpl, sl, 0 ); exit( 0 ); } if (( kerror = krb5_cc_resolve( kcontext, krbpath, &kccache )) != 0 ) { sl[ SL_ERROR ].sl_data = (char *)error_message( kerror ); sl[ SL_TITLE ].sl_data = "Authentication Required (kerberos error)"; subfile( tmpl, sl, 0 ); exit( 0 ); } } krb5_get_init_creds_opt_init( &kopts ); krb5_get_init_creds_opt_set_tkt_life( &kopts, tkt_life ); krb5_get_init_creds_opt_set_renew_life( &kopts, 0 ); krb5_get_init_creds_opt_set_forwardable( &kopts, 1 ); krb5_get_init_creds_opt_set_proxiable( &kopts, 0 ); if (( kerror = krb5_get_init_creds_password( kcontext, &kcreds, kprinc, passwd, NULL, NULL, 0, NULL /*keytab */, &kopts ))) { if (( kerror == KRB5KRB_AP_ERR_BAD_INTEGRITY ) || ( kerror == KRB5KDC_ERR_PREAUTH_FAILED ) || ( kerror == KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN )) { return( COSIGN_CGI_ERROR ); /* draw login or reauth page */ } else if ( kerror == KRB5KDC_ERR_KEY_EXP ) { *msg = (char *)error_message( kerror ); return( COSIGN_CGI_PASSWORD_EXPIRED ); } else { sl[ SL_ERROR ].sl_data = (char *)error_message( kerror ); sl[ SL_TITLE ].sl_data = "Error"; subfile( tmpl, sl, 0 ); exit( 0 ); } } /* verify no KDC spoofing */ if ( *keytab_path != '\0' ) { if ( strlen( keytab_path ) > MAX_KEYTAB_NAME_LEN ) { sl[ SL_ERROR ].sl_data = "server configuration error"; sl[ SL_TITLE ].sl_data = "Ticket Verification Error"; subfile( tmpl, sl, 0 ); exit( 0 ); } strcpy( ktbuf, keytab_path ); /* from mdw */ krb5_verify_init_creds_opt_init( kvic_opts ); krb5_verify_init_creds_opt_set_ap_req_nofail( kvic_opts, 1 ); if (( kerror = krb5_kt_resolve( kcontext, ktbuf, &keytab )) != 0 ) { sl[ SL_ERROR ].sl_data = (char *)error_message( kerror ); sl[ SL_TITLE ].sl_data = "KT Resolve Error"; subfile( tmpl, sl, 0 ); exit( 0 ); } if ( cosign_princ ) { kerror = krb5_parse_name( kcontext, cosign_princ, &sprinc ); } else { kerror = krb5_sname_to_principal( kcontext, NULL, "cosign", KRB5_NT_SRV_HST, &sprinc ); } if ( kerror != 0 ) { sl[ SL_ERROR ].sl_data = (char *)error_message( kerror ); sl[ SL_TITLE ].sl_data = "Server Principal Error"; subfile( tmpl, sl, 0 ); exit( 0 ); } if (( kerror = krb5_verify_init_creds( kcontext, &kcreds, sprinc, keytab, NULL, kvic_opts )) != 0 ) { if ( krb5_unparse_name( kcontext, sprinc, &sprinc_name ) == 0 ) { fprintf( stderr, "ticket verify error for " "user %s, keytab principal %s", id, sprinc_name ); free( sprinc_name ); } else { fprintf( stderr, "ticket verify error for user %s", id ); } sl[ SL_ERROR ].sl_data = (char *)error_message( kerror ); sl[ SL_TITLE ].sl_data = "Ticket Verify Error"; subfile( tmpl, sl, 0 ); krb5_free_principal( kcontext, sprinc ); exit( 0 ); } (void)krb5_kt_close( kcontext, keytab ); krb5_free_principal( kcontext, sprinc ); } for ( i = 0; i < COSIGN_MAXFACTORS - 1; i++ ) { if ( new_factors[ i ] == NULL ) { new_factors[ i ] = strdup( realm ); new_factors[ i + 1 ] = NULL; break; } if ( strcmp( new_factors[ i ], realm ) == 0 ) { break; } } if ( sp->sp_reauth && sp->sp_ipchanged == 0 ) { return( COSIGN_CGI_OK ); } if ( store_tickets ) { if (( kerror = krb5_cc_initialize( kcontext, kccache, kprinc )) != 0 ) { sl[ SL_ERROR ].sl_data = (char *)error_message( kerror ); sl[ SL_TITLE ].sl_data = "CC Initialize Error"; subfile( tmpl, sl, 0 ); exit( 0 ); } if (( kerror = krb5_cc_store_cred( kcontext, kccache, &kcreds )) != 0 ) { sl[ SL_ERROR ].sl_data = (char *)error_message( kerror ); sl[ SL_TITLE ].sl_data = "CC Storing Error"; subfile( tmpl, sl, 0 ); exit( 0 ); } krb5_cc_close( kcontext, kccache ); } krb5_free_cred_contents( kcontext, &kcreds ); krb5_free_principal( kcontext, kprinc ); krb5_free_context( kcontext ); /* password has been accepted, tell cosignd */ if ( cosign_login( head, cookie, ip_addr, cosignname, realm, ( store_tickets ? krbpath : NULL )) < 0 ) { fprintf( stderr, "cosign_login_krb5: login failed\n") ; sl[ SL_ERROR ].sl_data = "We were unable to contact the " "authentication server. Please try again later."; sl[ SL_TITLE ].sl_data = "Error: Please try later"; subfile( tmpl, sl, 0 ); exit( 0 ); } return( COSIGN_CGI_OK ); }
static int netretr_ticket( char *scookie, struct sinfo *si, SNET *sn, char *tkt_prefix, void *s ) { char *line; char tmpkrb[ 16 ], krbpath [ MAXPATHLEN ]; char buf[ 8192 ]; int fd; size_t size = 0; ssize_t rr; struct timeval tv; extern int errno; /* clear it, in case we can't get it later */ *si->si_krb5tkt = '\0'; /* RETR service-cookie TicketType */ if ( snet_writef( sn, "RETR %s tgt\r\n", scookie ) < 0 ) { cosign_log( APLOG_ERR, s, "mod_cosign: netretr_ticket: snet_writef failed"); return( COSIGN_ERROR ); } tv = timeout; if (( line = snet_getline_multi( sn, logger, &tv )) == NULL ) { cosign_log( APLOG_ERR, s, "mod_cosign: netretr_ticket: %s", strerror( errno )); return( COSIGN_ERROR ); } switch( *line ) { case '2': break; case '4': cosign_log( APLOG_ERR, s, "mod_cosign: netretr_ticket: %s", line ); return( COSIGN_LOGGED_OUT ); case '5': /* choose another connection */ cosign_log( APLOG_ERR, s, "mod_cosign: netretr_ticket: 5xx" ); return( COSIGN_RETRY ); default: cosign_log( APLOG_ERR, s, "mod_cosign: netretr_ticket: %s", line ); return( COSIGN_ERROR ); } if ( mkcookie( sizeof( tmpkrb ), tmpkrb ) != 0 ) { cosign_log( APLOG_ERR, s, "mod_cosign: netretr_ticket: mkcookie failed" ); return( COSIGN_ERROR ); } if ( snprintf( krbpath, sizeof( krbpath ), "%s/%s", tkt_prefix, tmpkrb ) >= sizeof( krbpath )) { cosign_log( APLOG_ERR, s, "mod_cosign: netretr_ticket: krbpath too long" ); return( COSIGN_ERROR ); } tv = timeout; if (( line = snet_getline( sn, &tv )) == NULL ) { cosign_log( APLOG_ERR, s, "mod_cosign: netretr_ticket: failed for %s", scookie ); return( COSIGN_ERROR ); } size = atoi( line ); if (( fd = open( krbpath, O_WRONLY | O_CREAT | O_EXCL, 0600 )) < 0 ) { perror( krbpath ); return( COSIGN_ERROR ); } /* Get file from server */ while ( size > 0 ) { tv = timeout; if (( rr = snet_read( sn, buf, (int)MIN( sizeof( buf ), size ), &tv )) <= 0 ) { cosign_log( APLOG_ERR, s, "mod_cosign: retrieve tgt failed: %s", strerror( errno )); goto error2; } if ( write( fd, buf, (size_t)rr ) != rr ) { perror( krbpath ); goto error2; } size -= rr; } if ( close( fd ) != 0 ) { perror( krbpath ); goto error1; } if ( size != 0 ) { cosign_log( APLOG_ERR, s, "mod_cosign: retrieve tickets: size from server did " "not match size read from server" ); goto error1; } tv = timeout; if (( line = snet_getline( sn, &tv )) == NULL ) { cosign_log( APLOG_ERR, s, "mod_cosign: retrieve for %s failed: %s", scookie, strerror( errno )); goto error1; } if ( strcmp( line, "." ) != 0 ) { cosign_log( APLOG_ERR, s, "mod_cosign: netretr_ticket: %s", line ); goto error1; } /* copy the path to the ticket file */ if ( strlen( krbpath ) >= sizeof( si->si_krb5tkt )) { cosign_log( APLOG_ERR, s, "mod_cosign: netretr_ticket: krb5tkt path too long" ); goto error1; } strcpy( si->si_krb5tkt, krbpath ); return( COSIGN_OK ); error2: close( fd ); error1: unlink( krbpath ); return( COSIGN_ERROR ); }