static int gss_auth(void *app_data, char *host) { OM_uint32 maj_stat, min_stat; gss_name_t target_name; gss_buffer_desc input, output_token; int context_established = 0; char *p; int n; gss_channel_bindings_t bindings; struct gss_data *d = app_data; const char *knames[] = { "ftp", "host", NULL }, **kname = knames; if(import_name(*kname++, host, &target_name)) return AUTH_ERROR; input.length = 0; input.value = NULL; bindings = malloc(sizeof(*bindings)); sockaddr_to_gss_address (myctladdr, &bindings->initiator_addrtype, &bindings->initiator_address); sockaddr_to_gss_address (hisctladdr, &bindings->acceptor_addrtype, &bindings->acceptor_address); bindings->application_data.length = 0; bindings->application_data.value = NULL; while(!context_established) { maj_stat = gss_init_sec_context(&min_stat, GSS_C_NO_CREDENTIAL, &d->context_hdl, target_name, GSS_C_NO_OID, GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG | GSS_C_DELEG_FLAG, 0, bindings, &input, NULL, &output_token, NULL, NULL); if (GSS_ERROR(maj_stat)) { OM_uint32 new_stat; OM_uint32 msg_ctx = 0; gss_buffer_desc status_string; if(min_stat == KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN && *kname != NULL) { if(import_name(*kname++, host, &target_name)) return AUTH_ERROR; continue; } gss_display_status(&new_stat, min_stat, GSS_C_MECH_CODE, GSS_C_NO_OID, &msg_ctx, &status_string); printf("Error initializing security context: %s\n", (char*)status_string.value); gss_release_buffer(&new_stat, &status_string); return AUTH_CONTINUE; } gss_release_buffer(&min_stat, &input); if (output_token.length != 0) { base64_encode(output_token.value, output_token.length, &p); gss_release_buffer(&min_stat, &output_token); n = ftp_cmd("ADAT %s", p); free(p); } if (GSS_ERROR(maj_stat)) { if (d->context_hdl != GSS_C_NO_CONTEXT) gss_delete_sec_context (&min_stat, &d->context_hdl, GSS_C_NO_BUFFER); break; } if (maj_stat & GSS_S_CONTINUE_NEEDED) { p = strstr(ftp->reply, "ADAT="); if(p == NULL){ printf("Error: expected ADAT in reply. got: %s\n", ftp->reply); return AUTH_ERROR; } else { p+=5; input.value = malloc(strlen(p)); input.length = base64_decode(p, input.value); } } else { if(ftp->fullcode != 235) { printf("Unrecognized response code: %d\n", ftp->fullcode); return AUTH_ERROR; } context_established = 1; } } return AUTH_OK; }
static int gss_auth(void *app_data, char *host) { OM_uint32 maj_stat, min_stat; gss_name_t target_name; gss_buffer_desc input, output_token; int context_established = 0; char *p; int n; gss_channel_bindings_t bindings; struct gssapi_data *d = app_data; OM_uint32 mech_flags = GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG; const char *knames[] = { "ftp", "host", NULL }, **kname = knames; if(import_name(*kname++, host, &target_name)) return AUTH_ERROR; input.length = 0; input.value = NULL; if (ftp_do_gss_bindings) { bindings = malloc(sizeof(*bindings)); if (bindings == NULL) errx(1, "out of memory"); sockaddr_to_gss_address (myctladdr, &bindings->initiator_addrtype, &bindings->initiator_address); sockaddr_to_gss_address (hisctladdr, &bindings->acceptor_addrtype, &bindings->acceptor_address); bindings->application_data.length = 0; bindings->application_data.value = NULL; } else bindings = GSS_C_NO_CHANNEL_BINDINGS; if (ftp_do_gss_delegate) mech_flags |= GSS_C_DELEG_FLAG; while(!context_established) { maj_stat = gss_init_sec_context(&min_stat, GSS_C_NO_CREDENTIAL, &d->context_hdl, target_name, GSS_C_NO_OID, mech_flags, 0, bindings, &input, NULL, &output_token, NULL, NULL); if (GSS_ERROR(maj_stat)) { OM_uint32 new_stat; OM_uint32 msg_ctx = 0; gss_buffer_desc status_string; d->context_hdl = GSS_C_NO_CONTEXT; gss_release_name(&min_stat, &target_name); if(*kname != NULL) { if(import_name(*kname++, host, &target_name)) { if (bindings != GSS_C_NO_CHANNEL_BINDINGS) free(bindings); return AUTH_ERROR; } continue; } if (bindings != GSS_C_NO_CHANNEL_BINDINGS) free(bindings); gss_display_status(&new_stat, min_stat, GSS_C_MECH_CODE, GSS_C_NO_OID, &msg_ctx, &status_string); printf("Error initializing security context: %.*s\n", (int)status_string.length, (char*)status_string.value); gss_release_buffer(&new_stat, &status_string); return AUTH_CONTINUE; } if (input.value) { free(input.value); input.value = NULL; input.length = 0; } if (output_token.length != 0) { base64_encode(output_token.value, output_token.length, &p); gss_release_buffer(&min_stat, &output_token); n = command("ADAT %s", p); free(p); } if (GSS_ERROR(maj_stat)) { if (d->context_hdl != GSS_C_NO_CONTEXT) gss_delete_sec_context (&min_stat, &d->context_hdl, GSS_C_NO_BUFFER); break; } if (maj_stat & GSS_S_CONTINUE_NEEDED) { p = strstr(reply_string, "ADAT="); if(p == NULL){ printf("Error: expected ADAT in reply. got: %s\n", reply_string); if (bindings != GSS_C_NO_CHANNEL_BINDINGS) free(bindings); return AUTH_ERROR; } else { p+=5; input.value = malloc(strlen(p)); input.length = base64_decode(p, input.value); } } else { if(code != 235) { printf("Unrecognized response code: %d\n", code); if (bindings != GSS_C_NO_CHANNEL_BINDINGS) free(bindings); return AUTH_ERROR; } context_established = 1; } } gss_release_name(&min_stat, &target_name); if (bindings != GSS_C_NO_CHANNEL_BINDINGS) free(bindings); if (input.value) free(input.value); { gss_name_t targ_name; maj_stat = gss_inquire_context(&min_stat, d->context_hdl, NULL, &targ_name, NULL, NULL, NULL, NULL, NULL); if (GSS_ERROR(maj_stat) == 0) { gss_buffer_desc name; maj_stat = gss_display_name (&min_stat, targ_name, &name, NULL); if (GSS_ERROR(maj_stat) == 0) { printf("Authenticated to <%.*s>\n", (int)name.length, (char *)name.value); gss_release_buffer(&min_stat, &name); } gss_release_name(&min_stat, &targ_name); } else printf("Failed to get gss name of peer.\n"); } return AUTH_OK; }
int gss_check(int sock) { struct sockaddr_in remote, local; socklen_t addrlen; char *name; gss_buffer_desc input_token, output_token; gss_cred_id_t delegated_cred_handle = GSS_C_NO_CREDENTIAL; OM_uint32 maj_stat, min_stat; gss_name_t client_name; gss_buffer_desc export_name; gss_channel_bindings_t input_chan_bindings; tunnel_ctx_t* tunnel_ctx = createGssContext(sock); if( tunnel_ctx == NULL ) { return -1; } #ifndef MIT_KRB5 # if 0 /*VP This does not work neither with GT4 nor Heimdal */ delegated_cred_handle = malloc(sizeof(*delegated_cred_handle)); memset((char *) delegated_cred_handle, 0, sizeof(*delegated_cred_handle)); # endif #endif /* ! MIT_KRB5 */ addrlen = sizeof(local); if (getsockname(sock, (struct sockaddr *) & local, &addrlen) < 0 || addrlen != sizeof(local)) { #ifdef SHOW_ERROR perror("getsockname"); #endif return -1; } addrlen = sizeof(remote); if (getpeername(sock, (struct sockaddr *) & remote, &addrlen) < 0 || addrlen != sizeof(remote)) { #ifdef SHOW_ERROR perror("getpeername"); #endif return -1; } input_chan_bindings = malloc(sizeof(struct gss_channel_bindings_struct)); sockaddr_to_gss_address((struct sockaddr *) & local, &input_chan_bindings->initiator_addrtype, &input_chan_bindings->initiator_address); sockaddr_to_gss_address((struct sockaddr *) & remote, &input_chan_bindings->acceptor_addrtype, &input_chan_bindings->acceptor_address); input_chan_bindings->application_data.length = 0; input_chan_bindings->application_data.value = NULL; do { input_token.value = malloc(MAXBUF); input_token.length = eRead(sock, input_token.value, MAXBUF); maj_stat = gss_accept_sec_context(&min_stat, &tunnel_ctx->context_hdl, GSS_C_NO_CREDENTIAL, &input_token, input_chan_bindings, &client_name, NULL, &output_token, NULL, NULL, &delegated_cred_handle); if (GSS_ERROR(maj_stat)) { gss_print_errors(maj_stat); } gss_release_buffer(&min_stat, &input_token); if (output_token.length != 0) { eWrite(sock, output_token.value, output_token.length); printf("sended token %d\n", output_token.length); gss_release_buffer(&min_stat, &output_token); } if (maj_stat == GSS_S_COMPLETE) { printf("GSS OK\n"); if (GSS_ERROR(maj_stat)) { gss_print_errors(maj_stat); } maj_stat = gss_export_name(&min_stat, client_name, &export_name); if (GSS_ERROR(maj_stat)) { gss_print_errors(maj_stat); } name = realloc(export_name.value, export_name.length + 1); name[export_name.length] = '\0'; #if 0 printf("name = %s\n", name); fflush(stdout); #endif } } while( maj_stat == GSS_S_CONTINUE_NEEDED ) ; return 0; }
static int gss_adat(void *app_data, void *buf, size_t len) { char *p = NULL; gss_buffer_desc input_token, output_token; OM_uint32 maj_stat, min_stat; gss_name_t client_name; struct gssapi_data *d = app_data; gss_channel_bindings_t bindings; if (ftp_do_gss_bindings) { bindings = malloc(sizeof(*bindings)); if (bindings == NULL) errx(1, "out of memory"); sockaddr_to_gss_address (his_addr, &bindings->initiator_addrtype, &bindings->initiator_address); sockaddr_to_gss_address (ctrl_addr, &bindings->acceptor_addrtype, &bindings->acceptor_address); bindings->application_data.length = 0; bindings->application_data.value = NULL; } else bindings = GSS_C_NO_CHANNEL_BINDINGS; input_token.value = buf; input_token.length = len; maj_stat = gss_accept_sec_context (&min_stat, &d->context_hdl, GSS_C_NO_CREDENTIAL, &input_token, bindings, &client_name, NULL, &output_token, NULL, NULL, &d->delegated_cred_handle); if (bindings != GSS_C_NO_CHANNEL_BINDINGS) free(bindings); if(output_token.length) { if(base64_encode(output_token.value, output_token.length, &p) < 0) { reply(535, "Out of memory base64-encoding."); return -1; } gss_release_buffer(&min_stat, &output_token); } if(maj_stat == GSS_S_COMPLETE){ d->client_name = client_name; client_name = GSS_C_NO_NAME; if(p) reply(235, "ADAT=%s", p); else reply(235, "ADAT Complete"); sec_complete = 1; } else if(maj_stat == GSS_S_CONTINUE_NEEDED) { if(p) reply(335, "ADAT=%s", p); else reply(335, "OK, need more data"); } else { OM_uint32 new_stat; OM_uint32 msg_ctx = 0; gss_buffer_desc status_string; gss_display_status(&new_stat, min_stat, GSS_C_MECH_CODE, GSS_C_NO_OID, &msg_ctx, &status_string); syslog(LOG_ERR, "gss_accept_sec_context: %.*s", (int)status_string.length, (char*)status_string.value); gss_release_buffer(&new_stat, &status_string); reply(431, "Security resource unavailable"); } if (client_name) gss_release_name(&min_stat, &client_name); free(p); return 0; }
int gssAuth(int sock, tunnel_ctx_t* tunnel_ctx, const char *hostname, const char *service) { struct sockaddr_in6 remote, local; socklen_t addrlen; gss_buffer_desc real_input_token, real_output_token; gss_buffer_t input_token = &real_input_token, output_token = &real_output_token; OM_uint32 maj_stat, min_stat; gss_name_t server = GSS_C_NO_NAME; gss_channel_bindings_t input_chan_bindings; if (import_name(service, hostname, &server) < 0) { return -1; } addrlen = sizeof(local); if (getsockname(sock, (struct sockaddr *) & local, &addrlen) < 0 || addrlen > sizeof(local)) { #ifdef SHOW_ERROR perror("sockname"); #endif return -1; } addrlen = sizeof(remote); if (getpeername(sock, (struct sockaddr *) & remote, &addrlen) < 0 || addrlen > sizeof(remote)) { #ifdef SHOW_ERROR perror("getpeer"); #endif return -1; } input_token->length = 0; input_token->value = NULL; output_token->length = 0; output_token->value = NULL; #ifdef GSIGSS input_chan_bindings = GSS_C_NO_CHANNEL_BINDINGS; #else input_chan_bindings = malloc(sizeof(struct gss_channel_bindings_struct)); sockaddr_to_gss_address((struct sockaddr *) & local, &input_chan_bindings->initiator_addrtype, &input_chan_bindings->initiator_address); sockaddr_to_gss_address((struct sockaddr *) & remote, &input_chan_bindings->acceptor_addrtype, &input_chan_bindings->acceptor_address); input_chan_bindings->application_data.length = 0; input_chan_bindings->application_data.value = NULL; #endif while (!tunnel_ctx->isAuthentificated) { maj_stat = gss_init_sec_context(&min_stat, GSS_C_NO_CREDENTIAL, &tunnel_ctx->context_hdl, server, GSS_C_NO_OID, GSS_C_MUTUAL_FLAG | GSS_C_SEQUENCE_FLAG, 0, input_chan_bindings, input_token, NULL, output_token, NULL, NULL); if (tunnel_ctx->context_hdl == NULL) { gss_print_errors(min_stat); /* send a waste to the server */ eWrite(sock, "123", 3); return -1; } if ((maj_stat != GSS_S_CONTINUE_NEEDED) && (maj_stat != GSS_S_COMPLETE)) { gss_print_errors(min_stat); /* send a waste to the server */ eWrite(sock, "123", 3); return -1; } if (output_token->length > 0) { eWrite(sock, output_token->value, output_token->length); gss_release_buffer(&min_stat, output_token); } if (maj_stat & GSS_S_CONTINUE_NEEDED) { if( input_token->value == NULL ) { input_token->value = malloc(MAXBUF); } if( input_token->value == NULL ) { return -1; } input_token->length = eRead(sock, input_token->value, MAXBUF); if( (input_token->length < 0 ) || (input_token->length > MAXBUF) ) { /* incorrect length */ free(input_token->value); input_token->value = NULL; return -1; } } else { tunnel_ctx->isAuthentificated = 1; } } return 1; }