/* * NIST guidance in Section 5.1 of [SP800-132] requires that a portion * of the salt of at least 128 bits shall be randomly generated. */ static krb5_error_code add_random_to_salt(krb5_context context, krb5_salt *in, krb5_salt *out) { krb5_error_code ret; char *p; unsigned char random[16]; char *s; int slen; krb5_generate_random_block(random, sizeof(random)); slen = rk_base64_encode(random, sizeof(random), &s); if (slen < 0) return ENOMEM; ret = krb5_data_alloc(&out->saltvalue, slen + in->saltvalue.length); if (ret) { free(s); return ret; } p = out->saltvalue.data; memcpy(p, s, slen); memcpy(&p[slen], in->saltvalue.data, in->saltvalue.length); out->salttype = in->salttype; free(s); return 0; }
int sec_vfprintf(FILE *f, const char *fmt, va_list ap) { char *buf; void *enc; int len; if(!sec_complete) return vfprintf(f, fmt, ap); if (vasprintf(&buf, fmt, ap) == -1) { printf("Failed to allocate command.\n"); return -1; } len = (*mech->encode)(app_data, buf, strlen(buf), command_prot, &enc); free(buf); if(len < 0) { printf("Failed to encode command.\n"); return -1; } if(rk_base64_encode(enc, len, &buf) < 0){ free(enc); printf("Out of memory base64-encoding.\n"); return -1; } free(enc); #ifdef FTP_SERVER if(command_prot == prot_safe) fprintf(f, "631 %s\r\n", buf); else if(command_prot == prot_private) fprintf(f, "632 %s\r\n", buf); else if(command_prot == prot_confidential) fprintf(f, "633 %s\r\n", buf); #else if(command_prot == prot_safe) fprintf(f, "MIC %s", buf); else if(command_prot == prot_private) fprintf(f, "ENC %s", buf); else if(command_prot == prot_confidential) fprintf(f, "CONF %s", buf); #endif free(buf); return 0; }
static heim_string_t to_base64(heim_data_t data, heim_error_t *error) { char *b64 = NULL; heim_string_t s = NULL; const heim_octet_string *d; int ret; d = heim_data_get_data(data); ret = rk_base64_encode(d->data, d->length, &b64); if (ret < 0 || b64 == NULL) goto enomem; s = heim_string_ref_create(b64, free); if (s == NULL) goto enomem; return s; enomem: free(b64); if (error) *error = heim_error_create_enomem(); return NULL; }
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 = 0; 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) { rk_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) || n >= 4) { 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 = rk_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; }
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(rk_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; }