krb5_error_code KRB5_CALLCONV krb5_copy_creds(krb5_context context, const krb5_creds *incred, krb5_creds **outcred) { krb5_creds *tempcred; krb5_error_code retval; krb5_data *scratch; if (!(tempcred = (krb5_creds *)malloc(sizeof(*tempcred)))) return ENOMEM; *tempcred = *incred; retval = krb5_copy_principal(context, incred->client, &tempcred->client); if (retval) goto cleanlast; retval = krb5_copy_principal(context, incred->server, &tempcred->server); if (retval) goto cleanclient; retval = krb5_copy_keyblock_contents(context, &incred->keyblock, &tempcred->keyblock); if (retval) goto cleanserver; retval = krb5_copy_addresses(context, incred->addresses, &tempcred->addresses); if (retval) goto cleanblock; retval = krb5_copy_data(context, &incred->ticket, &scratch); if (retval) goto cleanaddrs; tempcred->ticket = *scratch; krb5_xfree(scratch); retval = krb5_copy_data(context, &incred->second_ticket, &scratch); if (retval) goto cleanticket; tempcred->second_ticket = *scratch; krb5_xfree(scratch); retval = krb5_copy_authdata(context, incred->authdata,&tempcred->authdata); if (retval) goto clearticket; *outcred = tempcred; return 0; clearticket: memset(tempcred->ticket.data,0,tempcred->ticket.length); cleanticket: free(tempcred->ticket.data); cleanaddrs: krb5_free_addresses(context, tempcred->addresses); cleanblock: krb5_xfree(tempcred->keyblock.contents); cleanserver: krb5_free_principal(context, tempcred->server); cleanclient: krb5_free_principal(context, tempcred->client); cleanlast: krb5_xfree(tempcred); return retval; }
static krb5_error_code prof_locate_server (krb5_context context, const krb5_data *realm, char ***hostlist, enum locate_service_type svc) { const char *realm_srv_names[4]; char **hl, *host, *profname; krb5_error_code code; int i, j, count; *hostlist = NULL; /* default - indicate no KDCs found */ switch (svc) { case locate_service_kdc: profname = "kdc"; break; case locate_service_master_kdc: profname = "master_kdc"; break; case locate_service_kadmin: profname = "admin_server"; break; case locate_service_krb524: profname = "krb524_server"; break; case locate_service_kpasswd: profname = "kpasswd_server"; break; default: return EINVAL; } if ((host = malloc(realm->length + 1)) == NULL) return ENOMEM; (void) strncpy(host, realm->data, realm->length); host[realm->length] = '\0'; hl = 0; realm_srv_names[0] = "realms"; realm_srv_names[1] = host; realm_srv_names[2] = profname; realm_srv_names[3] = 0; code = profile_get_values(context->profile, realm_srv_names, &hl); if (code) { Tprintf ("config file lookup failed: %s\n", error_message(code)); if (code == PROF_NO_SECTION || code == PROF_NO_RELATION) code = KRB5_REALM_UNKNOWN; krb5_xfree(host); return code; } krb5_xfree(host); *hostlist = hl; return 0; }
static krb5_error_code krb5_compat_recvauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointer fdp, /* IN */ krb5_principal server, /* IN */ krb5_int32 flags, /* IN */ krb5_keytab keytab, /* IN */ krb5_ticket **ticket, /* OUT */ krb5_int32 *auth_sys, /* OUT */ krb5_data *version) /* OUT */ { krb5_int32 vlen; char *buf; int len, length; krb5_int32 retval; int fd = *((int *)fdp); if ((retval = krb5_net_read(context, fd, (char *)&vlen, 4)) != 4) return ((retval < 0) ? errno : ECONNABORTED); /* * Assume that we're talking to a V5 recvauth; read in the * the version string, and make sure it matches. */ len = (int)ntohl(vlen); if (len < 0 || len > 255) return (KRB5_SENDAUTH_BADAUTHVERS); buf = malloc(len); if (buf == NULL) return (ENOMEM); length = krb5_net_read(context, fd, buf, len); if (len != length) { krb5_xfree(buf); return ((len < 0) ? errno : ECONNABORTED); } if (strcmp(buf, KRB_V5_SENDAUTH_VERS) != 0) { krb5_xfree(buf); return (KRB5_SENDAUTH_BADAUTHVERS); } krb5_xfree(buf); *auth_sys = KRB5_RECVAUTH_V5; retval = krb5_recvauth_version(context, auth_context, fdp, server, flags | KRB5_RECVAUTH_SKIP_VERSION, keytab, ticket, version); return (retval); }
void sess_finalize(struct rekey_session *sess) { OM_uint32 min; if (sess->state == REKEY_SESSION_SENDING) prtmsg("warning: session closed before reply sent"); if (sess->ssl) { SSL_shutdown(sess->ssl); SSL_free(sess->ssl); } if (sess->kadm_handle) kadm5_destroy(sess->kadm_handle); if (sess->realm) { #if defined(HAVE_KRB5_REALM) krb5_xfree(sess->realm); #else krb5_free_default_realm(sess->kctx, sess->realm); #endif } if (sess->princ) krb5_free_principal(sess->kctx, sess->princ); if (sess->kctx) krb5_free_context(sess->kctx); if (sess->gctx) (void)gss_delete_sec_context(&min, &sess->gctx, GSS_C_NO_BUFFER); if (sess->name) (void)gss_release_name(&min, &sess->name); if (sess->dbh) sqlite3_close(sess->dbh); free(sess->hostname); free(sess->plain_name); memset(&sess, 0, sizeof(sess)); }
krb5_error_code KRB5_CALLCONV krb5_ktsrvtab_close(krb5_context context, krb5_keytab id) /* * This routine is responsible for freeing all memory allocated * for this keytab. There are no system resources that need * to be freed nor are there any open files. * * This routine should undo anything done by krb5_ktsrvtab_resolve(). */ { krb5_xfree(KTFILENAME(id)); krb5_xfree(id->data); id->ops = 0; krb5_xfree(id); return (0); }
/*ARGSUSED*/ krb5_error_code KRB5_CALLCONV krb5_copy_data(krb5_context context, const krb5_data *indata, krb5_data **outdata) { krb5_data *tempdata; if (!indata) { *outdata = 0; return 0; } if (!(tempdata = (krb5_data *)malloc(sizeof(*tempdata)))) return ENOMEM; tempdata->length = indata->length; if (tempdata->length) { if (!(tempdata->data = malloc(tempdata->length))) { krb5_xfree(tempdata); return ENOMEM; } memcpy((char *)tempdata->data, (char *)indata->data, tempdata->length); } else tempdata->data = 0; tempdata->magic = KV5M_DATA; *outdata = tempdata; return 0; }
/* * krb5_principal_externalize() - Externalize the krb5_principal. */ static krb5_error_code krb5_principal_externalize(krb5_context kcontext, krb5_pointer arg, krb5_octet **buffer, size_t *lenremain) { krb5_error_code kret; krb5_principal principal; size_t required; krb5_octet *bp; size_t remain; char *fname; required = 0; bp = *buffer; remain = *lenremain; kret = EINVAL; if ((principal = (krb5_principal) arg)) { kret = ENOMEM; if (!krb5_principal_size(kcontext, arg, &required) && (required <= remain)) { if (!(kret = krb5_unparse_name(kcontext, principal, &fname))) { (void) krb5_ser_pack_int32(KV5M_PRINCIPAL, &bp, &remain); (void) krb5_ser_pack_int32((krb5_int32) strlen(fname), &bp, &remain); (void) krb5_ser_pack_bytes((krb5_octet *) fname, strlen(fname), &bp, &remain); (void) krb5_ser_pack_int32(KV5M_PRINCIPAL, &bp, &remain); *buffer = bp; *lenremain = remain; krb5_xfree(fname); } } } return(kret); }
krb5_error_code KRB5_CALLCONV krb5_rc_dfl_resolve(krb5_context context, krb5_rcache id, char *name) { struct dfl_data *t = 0; krb5_error_code retval; /* allocate id? no */ if (!(t = (struct dfl_data *) malloc(sizeof(struct dfl_data)))) return KRB5_RC_MALLOC; id->data = (krb5_pointer) t; memset(t, 0, sizeof(struct dfl_data)); if (name) { t->name = malloc(strlen(name)+1); if (!t->name) { retval = KRB5_RC_MALLOC; goto cleanup; } strcpy(t->name, name); } else t->name = 0; t->numhits = t->nummisses = 0; t->hsize = HASHSIZE; /* no need to store---it's memory-only */ t->h = (struct authlist **) malloc(t->hsize*sizeof(struct authlist *)); if (!t->h) { retval = KRB5_RC_MALLOC; goto cleanup; } memset(t->h, 0, t->hsize*sizeof(struct authlist *)); t->a = (struct authlist *) 0; #ifndef NOIOSTUFF t->d.fd = -1; #endif t->recovering = 0; return 0; cleanup: if (t) { if (t->name) krb5_xfree(t->name); if (t->h) krb5_xfree(t->h); krb5_xfree(t); } return retval; }
void krb5_free_realm_tree(krb5_context context, krb5_principal *realms) { register krb5_principal *nrealms = realms; while (*nrealms) { krb5_free_principal(context, *nrealms); nrealms++; } krb5_xfree(realms); }
void krb5_ldap_free_krbcontainer_params(krb5_ldap_krbcontainer_params *cparams) { if (cparams == NULL) return; if (cparams->policyreference) krb5_xfree(cparams->policyreference); if (cparams->parent) krb5_xfree(cparams->parent); if (cparams->DN) krb5_xfree(cparams->DN); krb5_xfree(cparams); return; }
static krb5_error_code kcm_get_cache_next(krb5_context context, krb5_cc_cursor cursor, const krb5_cc_ops *ops, krb5_ccache *id) { krb5_error_code ret; krb5_kcm_cursor c = KCMCURSOR(cursor); krb5_storage *request, *response; krb5_data response_data; ssize_t sret; char *name; *id = NULL; again: if (c->offset >= c->length) return KRB5_CC_END; ret = krb5_kcm_storage_request(context, KCM_OP_GET_CACHE_BY_UUID, &request); if (ret) return ret; sret = krb5_storage_write(request, &c->uuids[c->offset], sizeof(c->uuids[c->offset])); c->offset++; if (sret != sizeof(c->uuids[c->offset])) { krb5_storage_free(request); krb5_clear_error_message(context); return ENOMEM; } ret = krb5_kcm_call(context, request, &response, &response_data); krb5_storage_free(request); if (ret == KRB5_FCC_NOFILE) { /* cache no longer exists, try next */ goto again; } else if (ret) return ret; ret = krb5_ret_stringz(response, &name); krb5_storage_free(response); krb5_data_free(&response_data); if (ret) return ret; ret = _krb5_cc_allocate(context, ops, id); if (ret == 0) ret = kcm_alloc(context, name, id); krb5_xfree(name); return ret; }
static CFStringRef CFStringCreateFromPrincipal(krb5_context context, krb5_principal principal) { CFStringRef str; char *p; if (krb5_unparse_name(context, principal, &p) != 0) return NULL; str = CFStringCreateWithCString(NULL, p, kCFStringEncodingUTF8); krb5_xfree(p); return str; }
/*ARGSUSED*/ static krb5_error_code krb5_get_as_key_keytab( krb5_context context, krb5_principal client, krb5_enctype etype, krb5_prompter_fct prompter, void *prompter_data, krb5_data *salt, krb5_data *params, krb5_keyblock *as_key, void *gak_data) { krb5_keytab keytab = (krb5_keytab) gak_data; krb5_error_code ret; krb5_keytab_entry kt_ent; krb5_keyblock *kt_key; /* if there's already a key of the correct etype, we're done. if the etype is wrong, free the existing key, and make a new one. */ if (as_key->length) { if (as_key->enctype == etype) return(0); krb5_free_keyblock_contents(context, as_key); as_key->length = 0; } if (!krb5_c_valid_enctype(etype)) return(KRB5_PROG_ETYPE_NOSUPP); /* Solaris Kerberos */ if ((ret = krb5_kt_get_entry(context, keytab, client, 0, /* don't have vno available */ etype, &kt_ent)) != NULL) return(ret); ret = krb5_copy_keyblock(context, &kt_ent.key, &kt_key); /* again, krb5's memory management is lame... */ *as_key = *kt_key; krb5_xfree(kt_key); (void) krb5_kt_free_entry(context, &kt_ent); return(ret); }
static krb5_error_code KRB5_CALLCONV krb5_ktsrvtab_resolve(krb5_context context, const char *name, krb5_keytab *id) { krb5_ktsrvtab_data *data; FILE *fp; /* Make sure we can open the srvtab file for reading. */ fp = fopen(name, "r"); if (!fp) return(errno); fclose(fp); if ((*id = (krb5_keytab) malloc(sizeof(**id))) == NULL) return(ENOMEM); (*id)->ops = &krb5_kts_ops; data = (krb5_ktsrvtab_data *)malloc(sizeof(krb5_ktsrvtab_data)); if (data == NULL) { krb5_xfree(*id); return(ENOMEM); } data->name = (char *)malloc(strlen(name) + 1); if (data->name == NULL) { krb5_xfree(data); krb5_xfree(*id); return(ENOMEM); } (void) strcpy(data->name, name); data->openf = 0; (*id)->data = (krb5_pointer)data; (*id)->magic = KV5M_KEYTAB; return(0); }
void kssl_krb5_free_data_contents(krb5_context context, krb5_data *data) { #ifdef KRB5_HEIMDAL data->length = 0; if (data->data) free(data->data); #elif defined(KRB5_MIT_OLD11) if (data->data) { krb5_xfree(data->data); data->data = 0; } #else krb5_free_data_contents(NULL, data); #endif }
std::string KRB5Principal::name() { char *principal_string; krb5_error_code ret = krb5_unparse_name(g_context.get(), m_princ, &principal_string); if (ret) { throw KRB5Exception("krb5_unparse_name", ret); } std::string result(principal_string); #ifdef HEIMDAL krb5_xfree(principal_string); #else krb5_free_unparsed_name(g_context.get(), principal_string); #endif return result; }
krb5_error_code krb5int_copy_data_contents(krb5_context context, const krb5_data *indata, krb5_data *outdata) { if (!indata) { return EINVAL; } outdata->length = indata->length; if (outdata->length) { if (!(outdata->data = malloc(outdata->length))) { krb5_xfree(outdata); return ENOMEM; } memcpy((char *)outdata->data, (char *)indata->data, outdata->length); } else outdata->data = 0; outdata->magic = KV5M_DATA; return 0; }
static krb5_error_code get_keytab(krb5_context context, krb5_keytab *keytab) { krb5_error_code kret; HEIMDAL_MUTEX_lock(&gssapi_keytab_mutex); if (_gsskrb5_keytab != NULL) { char *name = NULL; kret = krb5_kt_get_full_name(context, _gsskrb5_keytab, &name); if (kret == 0) { kret = krb5_kt_resolve(context, name, keytab); krb5_xfree(name); } } else kret = krb5_kt_default(context, keytab); HEIMDAL_MUTEX_unlock(&gssapi_keytab_mutex); return (kret); }
/* * krb5_principal_size() - Determine the size required to externalize * the krb5_principal. */ static krb5_error_code krb5_principal_size(krb5_context kcontext, krb5_pointer arg, size_t *sizep) { krb5_error_code kret; krb5_principal principal; char *fname; /* * krb5_principal requires: * krb5_int32 for KV5M_PRINCIPAL * krb5_int32 for flattened name size * strlen(name) for name. * krb5_int32 for KV5M_PRINCIPAL */ kret = EINVAL; if ((principal = (krb5_principal) arg) && !(kret = krb5_unparse_name(kcontext, principal, &fname))) { *sizep += (3*sizeof(krb5_int32)) + strlen(fname); krb5_xfree(fname); } return(kret); }
static krb5_error_code bind_principal(krb5_context context, sqlite3 *db, sqlite3_stmt *stmt, int col, krb5_const_principal principal) { krb5_error_code ret; char *str; ret = krb5_unparse_name(context, principal, &str); if (ret) return ret; ret = sqlite3_bind_text(stmt, col, str, -1, free_krb5); if (ret != SQLITE_OK) { krb5_xfree(str); krb5_set_error_message(context, ENOMEM, N_("scache bind principal: %s", ""), sqlite3_errmsg(db)); return ENOMEM; } return 0; }
static const char* KRB5_CALLCONV acc_get_name(krb5_context context, krb5_ccache id) { krb5_acc *a = ACACHE(id); int32_t error; if (a->cache_name == NULL) { krb5_error_code ret; krb5_principal principal; char *name; ret = _krb5_get_default_principal_local(context, &principal); if (ret) return NULL; ret = krb5_unparse_name(context, principal, &name); krb5_free_principal(context, principal); if (ret) return NULL; error = (*a->context->func->create_new_ccache)(a->context, cc_credentials_v5, name, &a->ccache); krb5_xfree(name); if (error) return NULL; error = get_cc_name(a); if (error) return NULL; } return a->cache_name; }
static krb5_error_code resolve_by_uuid_oid(krb5_context context, const krb5_cc_ops *ops, krb5_ccache id, krb5_uuid uuid) { krb5_storage *request, *response; krb5_data response_data; krb5_error_code ret; char *name; ssize_t sret; ret = krb5_kcm_storage_request(context, KCM_OP_GET_CACHE_BY_UUID, &request); if (ret) return ret; sret = krb5_storage_write(request, uuid, sizeof(krb5_uuid)); if (sret != sizeof(krb5_uuid)) { krb5_storage_free(request); krb5_clear_error_message(context); return ENOMEM; } ret = krb5_kcm_call(context, request, &response, &response_data); krb5_storage_free(request); if (ret) return ret; ret = krb5_ret_stringz(response, &name); krb5_storage_free(response); krb5_data_free(&response_data); if (ret) return ret; ret = kcm_alloc(context, name, &id); krb5_xfree(name); return ret; }
static krb5_error_code krb5_rd_req_decoded_opt(krb5_context context, krb5_auth_context *auth_context, const krb5_ap_req *req, krb5_const_principal server, krb5_keytab keytab, krb5_flags *ap_req_options, krb5_ticket **ticket, int check_valid_flag) { krb5_error_code retval = 0; krb5_timestamp currenttime; krb5_principal_data princ_data; req->ticket->enc_part2 == NULL; if (server && krb5_is_referral_realm(&server->realm)) { char *realm; princ_data = *server; server = &princ_data; retval = krb5_get_default_realm(context, &realm); if (retval) return retval; princ_data.realm.data = realm; princ_data.realm.length = strlen(realm); } if (server && !krb5_principal_compare(context, server, req->ticket->server)) { char *found_name = 0, *wanted_name = 0; if (krb5_unparse_name(context, server, &wanted_name) == 0 && krb5_unparse_name(context, req->ticket->server, &found_name) == 0) krb5_set_error_message(context, KRB5KRB_AP_WRONG_PRINC, "Wrong principal in request (found %s, wanted %s)", found_name, wanted_name); krb5_free_unparsed_name(context, wanted_name); krb5_free_unparsed_name(context, found_name); retval = KRB5KRB_AP_WRONG_PRINC; goto cleanup; } /* if (req->ap_options & AP_OPTS_USE_SESSION_KEY) do we need special processing here ? */ /* decrypt the ticket */ if ((*auth_context)->keyblock) { /* User to User authentication */ if ((retval = krb5_decrypt_tkt_part(context, (*auth_context)->keyblock, req->ticket))) goto cleanup; krb5_free_keyblock(context, (*auth_context)->keyblock); (*auth_context)->keyblock = NULL; } else { if ((retval = krb5_rd_req_decrypt_tkt_part(context, req, keytab))) goto cleanup; } /* XXX this is an evil hack. check_valid_flag is set iff the call is not from inside the kdc. we can use this to determine which key usage to use */ if ((retval = decrypt_authenticator(context, req, &((*auth_context)->authentp), check_valid_flag))) goto cleanup; if (!krb5_principal_compare(context, (*auth_context)->authentp->client, req->ticket->enc_part2->client)) { retval = KRB5KRB_AP_ERR_BADMATCH; goto cleanup; } if ((*auth_context)->remote_addr && !krb5_address_search(context, (*auth_context)->remote_addr, req->ticket->enc_part2->caddrs)) { retval = KRB5KRB_AP_ERR_BADADDR; goto cleanup; } /* okay, now check cross-realm policy */ #if defined(_SINGLE_HOP_ONLY) /* Single hop cross-realm tickets only */ { krb5_transited *trans = &(req->ticket->enc_part2->transited); /* If the transited list is empty, then we have at most one hop */ if (trans->tr_contents.data && trans->tr_contents.data[0]) retval = KRB5KRB_AP_ERR_ILL_CR_TKT; } #elif defined(_NO_CROSS_REALM) /* No cross-realm tickets */ { char * lrealm; krb5_data * realm; krb5_transited * trans; realm = krb5_princ_realm(context, req->ticket->enc_part2->client); trans = &(req->ticket->enc_part2->transited); /* * If the transited list is empty, then we have at most one hop * So we also have to check that the client's realm is the local one */ krb5_get_default_realm(context, &lrealm); if ((trans->tr_contents.data && trans->tr_contents.data[0]) || strlen(lrealm) != realm->length || memcmp(lrealm, realm->data, strlen(lrealm))) { retval = KRB5KRB_AP_ERR_ILL_CR_TKT; } free(lrealm); } #else /* Hierarchical Cross-Realm */ { krb5_data * realm; krb5_transited * trans; realm = krb5_princ_realm(context, req->ticket->enc_part2->client); trans = &(req->ticket->enc_part2->transited); /* * If the transited list is not empty, then check that all realms * transited are within the hierarchy between the client's realm * and the local realm. */ if (trans->tr_contents.data && trans->tr_contents.data[0]) { retval = krb5_check_transited_list(context, &(trans->tr_contents), realm, krb5_princ_realm (context, server)); } } #endif if (retval) goto cleanup; /* only check rcache if sender has provided one---some services may not be able to use replay caches (such as datagram servers) */ if ((*auth_context)->rcache) { krb5_donot_replay rep; krb5_tkt_authent tktauthent; tktauthent.ticket = req->ticket; tktauthent.authenticator = (*auth_context)->authentp; if (!(retval = krb5_auth_to_rep(context, &tktauthent, &rep))) { retval = krb5_rc_store(context, (*auth_context)->rcache, &rep); krb5_xfree(rep.server); krb5_xfree(rep.client); } if (retval) goto cleanup; } retval = krb5_validate_times(context, &req->ticket->enc_part2->times); if (retval != 0) goto cleanup; if ((retval = krb5_timeofday(context, ¤ttime))) goto cleanup; if (!in_clock_skew((*auth_context)->authentp->ctime)) { retval = KRB5KRB_AP_ERR_SKEW; goto cleanup; } if (check_valid_flag) { if (req->ticket->enc_part2->flags & TKT_FLG_INVALID) { retval = KRB5KRB_AP_ERR_TKT_INVALID; goto cleanup; } } /* check if the various etypes are permitted */ if ((*auth_context)->auth_context_flags & KRB5_AUTH_CONTEXT_PERMIT_ALL) { /* no etype check needed */; } else if ((*auth_context)->permitted_etypes == NULL) { int etype; /* check against the default set */ if ((!krb5_is_permitted_enctype(context, etype = req->ticket->enc_part.enctype)) || (!krb5_is_permitted_enctype(context, etype = req->ticket->enc_part2->session->enctype)) || (((*auth_context)->authentp->subkey) && !krb5_is_permitted_enctype(context, etype = (*auth_context)->authentp->subkey->enctype))) { char enctype_name[30]; retval = KRB5_NOPERM_ETYPE; if (krb5_enctype_to_string(etype, enctype_name, sizeof(enctype_name)) == 0) krb5_set_error_message(context, retval, "Encryption type %s not permitted", enctype_name); goto cleanup; } } else { /* check against the set in the auth_context */ int i; for (i=0; (*auth_context)->permitted_etypes[i]; i++) if ((*auth_context)->permitted_etypes[i] == req->ticket->enc_part.enctype) break; if (!(*auth_context)->permitted_etypes[i]) { char enctype_name[30]; retval = KRB5_NOPERM_ETYPE; if (krb5_enctype_to_string(req->ticket->enc_part.enctype, enctype_name, sizeof(enctype_name)) == 0) krb5_set_error_message(context, retval, "Encryption type %s not permitted", enctype_name); goto cleanup; } for (i=0; (*auth_context)->permitted_etypes[i]; i++) if ((*auth_context)->permitted_etypes[i] == req->ticket->enc_part2->session->enctype) break; if (!(*auth_context)->permitted_etypes[i]) { char enctype_name[30]; retval = KRB5_NOPERM_ETYPE; if (krb5_enctype_to_string(req->ticket->enc_part2->session->enctype, enctype_name, sizeof(enctype_name)) == 0) krb5_set_error_message(context, retval, "Encryption type %s not permitted", enctype_name); goto cleanup; } if ((*auth_context)->authentp->subkey) { for (i=0; (*auth_context)->permitted_etypes[i]; i++) if ((*auth_context)->permitted_etypes[i] == (*auth_context)->authentp->subkey->enctype) break; if (!(*auth_context)->permitted_etypes[i]) { char enctype_name[30]; retval = KRB5_NOPERM_ETYPE; if (krb5_enctype_to_string((*auth_context)->authentp->subkey->enctype, enctype_name, sizeof(enctype_name)) == 0) krb5_set_error_message(context, retval, "Encryption type %s not permitted", enctype_name); goto cleanup; } } } (*auth_context)->remote_seq_number = (*auth_context)->authentp->seq_number; if ((*auth_context)->authentp->subkey) { if ((retval = krb5_copy_keyblock(context, (*auth_context)->authentp->subkey, &((*auth_context)->recv_subkey)))) goto cleanup; retval = krb5_copy_keyblock(context, (*auth_context)->authentp->subkey, &((*auth_context)->send_subkey)); if (retval) { krb5_free_keyblock(context, (*auth_context)->recv_subkey); (*auth_context)->recv_subkey = NULL; goto cleanup; } } else { (*auth_context)->recv_subkey = 0; (*auth_context)->send_subkey = 0; } if ((retval = krb5_copy_keyblock(context, req->ticket->enc_part2->session, &((*auth_context)->keyblock)))) goto cleanup; /* * If not AP_OPTS_MUTUAL_REQUIRED then and sequence numbers are used * then the default sequence number is the one's complement of the * sequence number sent ot us. */ if ((!(req->ap_options & AP_OPTS_MUTUAL_REQUIRED)) && (*auth_context)->remote_seq_number) { (*auth_context)->local_seq_number ^= (*auth_context)->remote_seq_number; } if (ticket) if ((retval = krb5_copy_ticket(context, req->ticket, ticket))) goto cleanup; if (ap_req_options) *ap_req_options = req->ap_options; retval = 0; cleanup: if (server == &princ_data) krb5_free_default_realm(context, princ_data.realm.data); if (retval) { /* only free if we're erroring out...otherwise some applications will need the output. */ if (req->ticket->enc_part2) krb5_free_enc_tkt_part(context, req->ticket->enc_part2); req->ticket->enc_part2 = NULL; } return retval; }
/* * This function will create a krbcontainer and realm on the LDAP Server, with * the specified attributes. */ krb5_error_code krb5_ldap_create(krb5_context context, char *conf_section, char **db_args) { krb5_error_code status = 0; char **t_ptr = db_args; krb5_ldap_realm_params *rparams = NULL; kdb5_dal_handle *dal_handle = NULL; krb5_ldap_context *ldap_context=NULL; krb5_boolean realm_obj_created = FALSE; krb5_boolean krbcontainer_obj_created = FALSE; krb5_ldap_krbcontainer_params kparams = {0}; int srv_cnt = 0; int mask = 0; /* Clear the global error string */ krb5_clear_error_message(context); ldap_context = malloc(sizeof(krb5_ldap_context)); if (ldap_context == NULL) { status = ENOMEM; goto cleanup; } memset(ldap_context, 0, sizeof(*ldap_context)); ldap_context->kcontext = context; /* populate ldap_context with ldap specific options */ while (t_ptr && *t_ptr) { char *opt = NULL, *val = NULL; if ((status = krb5_ldap_get_db_opt(*t_ptr, &opt, &val)) != 0) { goto cleanup; } if (opt && !strcmp(opt, "binddn")) { if (ldap_context->bind_dn) { free (opt); free (val); status = EINVAL; krb5_set_error_message (context, status, "'binddn' missing"); goto cleanup; } if (val == NULL) { status = EINVAL; krb5_set_error_message (context, status, "'binddn' value missing"); free(opt); goto cleanup; } ldap_context->bind_dn = strdup(val); if (ldap_context->bind_dn == NULL) { free (opt); free (val); status = ENOMEM; goto cleanup; } } else if (opt && !strcmp(opt, "nconns")) { if (ldap_context->max_server_conns) { free (opt); free (val); status = EINVAL; krb5_set_error_message (context, status, "'nconns' missing"); goto cleanup; } if (val == NULL) { status = EINVAL; krb5_set_error_message (context, status, "'nconns' value missing"); free(opt); goto cleanup; } ldap_context->max_server_conns = atoi(val) ? atoi(val) : DEFAULT_CONNS_PER_SERVER; } else if (opt && !strcmp(opt, "bindpwd")) { if (ldap_context->bind_pwd) { free (opt); free (val); status = EINVAL; krb5_set_error_message (context, status, "'bindpwd' missing"); goto cleanup; } if (val == NULL) { status = EINVAL; krb5_set_error_message (context, status, "'bindpwd' value missing"); free(opt); goto cleanup; } ldap_context->bind_pwd = strdup(val); if (ldap_context->bind_pwd == NULL) { free (opt); free (val); status = ENOMEM; goto cleanup; } } else if (opt && !strcmp(opt, "host")) { if (val == NULL) { status = EINVAL; krb5_set_error_message (context, status, "'host' value missing"); free(opt); goto cleanup; } if (ldap_context->server_info_list == NULL) ldap_context->server_info_list = (krb5_ldap_server_info **) calloc(SERV_COUNT+1, sizeof(krb5_ldap_server_info *)); if (ldap_context->server_info_list == NULL) { free (opt); free (val); status = ENOMEM; goto cleanup; } ldap_context->server_info_list[srv_cnt] = (krb5_ldap_server_info *) calloc(1, sizeof(krb5_ldap_server_info)); if (ldap_context->server_info_list[srv_cnt] == NULL) { free (opt); free (val); status = ENOMEM; goto cleanup; } ldap_context->server_info_list[srv_cnt]->server_status = NOTSET; ldap_context->server_info_list[srv_cnt]->server_name = strdup(val); if (ldap_context->server_info_list[srv_cnt]->server_name == NULL) { free (opt); free (val); status = ENOMEM; goto cleanup; } srv_cnt++; } else { /* ignore hash argument. Might have been passed from create */ status = EINVAL; if (opt && !strcmp(opt, "temporary")) { /* * temporary is passed in when kdb5_util load without -update is done. * This is unsupported by the LDAP plugin. */ krb5_set_error_message(context, status, _("creation of LDAP entries aborted, " "plugin requires -update argument")); } else { krb5_set_error_message(context, status, _("unknown option \'%s\'"), opt?opt:val); } free(opt); free(val); goto cleanup; } free(opt); free(val); t_ptr++; } dal_handle = context->dal_handle; dal_handle->db_context = (kdb5_dal_handle *) ldap_context; status = krb5_ldap_read_server_params(context, conf_section, KRB5_KDB_SRV_TYPE_ADMIN); if (status) { dal_handle->db_context = NULL; prepend_err_str (context, "Error reading LDAP server params: ", status, status); goto cleanup; } status = krb5_ldap_db_init(context, ldap_context); if (status) { goto cleanup; } /* read the kerberos container */ if ((status = krb5_ldap_read_krbcontainer_params(context, &(ldap_context->krbcontainer))) == KRB5_KDB_NOENTRY) { /* Read the kerberos container location from configuration file */ if (ldap_context->conf_section) { if ((status = profile_get_string(context->profile, KDB_MODULE_SECTION, ldap_context->conf_section, KRB5_CONF_LDAP_KERBEROS_CONTAINER_DN, NULL, &kparams.DN)) != 0) { goto cleanup; } } if (kparams.DN == NULL) { if ((status = profile_get_string(context->profile, KDB_MODULE_DEF_SECTION, KRB5_CONF_LDAP_KERBEROS_CONTAINER_DN, NULL, NULL, &kparams.DN)) != 0) { goto cleanup; } } /* create the kerberos container */ status = krb5_ldap_create_krbcontainer(context, ((kparams.DN != NULL) ? &kparams : NULL)); if (status) goto cleanup; krbcontainer_obj_created = TRUE; status = krb5_ldap_read_krbcontainer_params(context, &(ldap_context->krbcontainer)); if (status) goto cleanup; } else if (status) { goto cleanup; } rparams = (krb5_ldap_realm_params *) malloc(sizeof(krb5_ldap_realm_params)); if (rparams == NULL) { status = ENOMEM; goto cleanup; } memset(rparams, 0, sizeof(*rparams)); rparams->realm_name = strdup(context->default_realm); if (rparams->realm_name == NULL) { status = ENOMEM; goto cleanup; } if ((status = krb5_ldap_create_realm(context, rparams, mask))) goto cleanup; /* We just created the Realm container. Here starts our transaction tracking */ realm_obj_created = TRUE; /* verify realm object */ if ((status = krb5_ldap_read_realm_params(context, rparams->realm_name, &(ldap_context->lrparams), &mask))) goto cleanup; cleanup: /* If the krbcontainer/realm creation is not complete, do the roll-back here */ if ((krbcontainer_obj_created) && (!realm_obj_created)) { int rc; rc = krb5_ldap_delete_krbcontainer(context, ((kparams.DN != NULL) ? &kparams : NULL)); krb5_set_error_message(context, rc, _("could not complete roll-back, error " "deleting Kerberos Container")); } /* should call krb5_ldap_free_krbcontainer_params() but can't */ if (kparams.DN != NULL) krb5_xfree(kparams.DN); if (rparams) krb5_ldap_free_realm_params(rparams); return(status); }
/* Get a TGT for use at the remote host */ krb5_error_code KRB5_CALLCONV krb5_fwd_tgt_creds(krb5_context context, krb5_auth_context auth_context, char *rhost, krb5_principal client, krb5_principal server, krb5_ccache cc, int forwardable, krb5_data *outbuf) /* Should forwarded TGT also be forwardable? */ { krb5_replay_data replaydata; krb5_data * scratch = 0; krb5_address **addrs = NULL; krb5_error_code retval; krb5_creds creds, tgt; krb5_creds *pcreds; krb5_flags kdcoptions; int close_cc = 0; int free_rhost = 0; krb5_enctype enctype = 0; krb5_keyblock *session_key; krb5_boolean old_use_conf_ktypes = context->use_conf_ktypes; memset((char *)&creds, 0, sizeof(creds)); memset((char *)&tgt, 0, sizeof(creds)); if (cc == 0) { if ((retval = krb5int_cc_default(context, &cc))) goto errout; close_cc = 1; } retval = krb5_auth_con_getkey (context, auth_context, &session_key); if (retval) goto errout; if (session_key) { enctype = session_key->enctype; krb5_free_keyblock (context, session_key); session_key = NULL; } else if (server) { /* must server be non-NULL when rhost is given? */ /* Try getting credentials to see what the remote side supports. Not bulletproof, just a heuristic. */ krb5_creds in, *out = 0; memset (&in, 0, sizeof(in)); retval = krb5_copy_principal (context, server, &in.server); if (retval) goto punt; retval = krb5_copy_principal (context, client, &in.client); if (retval) goto punt; retval = krb5_get_credentials (context, 0, cc, &in, &out); if (retval) goto punt; /* Got the credentials. Okay, now record the enctype and throw them away. */ enctype = out->keyblock.enctype; krb5_free_creds (context, out); punt: krb5_free_cred_contents (context, &in); } if ((retval = krb5_copy_principal(context, client, &creds.client))) goto errout; if ((retval = krb5_build_principal_ext(context, &creds.server, client->realm.length, client->realm.data, KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME, client->realm.length, client->realm.data, 0))) goto errout; /* fetch tgt directly from cache */ context->use_conf_ktypes = 1; retval = krb5_cc_retrieve_cred (context, cc, KRB5_TC_SUPPORTED_KTYPES, &creds, &tgt); context->use_conf_ktypes = old_use_conf_ktypes; if (retval) goto errout; /* tgt->client must be equal to creds.client */ if (!krb5_principal_compare(context, tgt.client, creds.client)) { /* Solaris Kerberos */ char *r_name = NULL; char *t_name = NULL; krb5_error_code r_err, t_err; t_err = krb5_unparse_name(context, tgt.client, &t_name); r_err = krb5_unparse_name(context, creds.client, &r_name); krb5_set_error_message(context, KRB5_PRINC_NOMATCH, dgettext(TEXT_DOMAIN, "Requested principal and ticket don't match: Requested principal is '%s' and TGT principal is '%s'"), r_err ? "unknown" : r_name, t_err ? "unknown" : t_name); if (r_name) krb5_free_unparsed_name(context, r_name); if (t_name) krb5_free_unparsed_name(context, t_name); retval = KRB5_PRINC_NOMATCH; goto errout; } if (!tgt.ticket.length) { retval = KRB5_NO_TKT_SUPPLIED; goto errout; } if (tgt.addresses && *tgt.addresses) { if (rhost == NULL) { if (krb5_princ_type(context, server) != KRB5_NT_SRV_HST) { retval = KRB5_FWD_BAD_PRINCIPAL; goto errout; } if (krb5_princ_size(context, server) < 2){ retval = KRB5_CC_BADNAME; goto errout; } rhost = malloc(server->data[1].length+1); if (!rhost) { retval = ENOMEM; goto errout; } free_rhost = 1; /* Solaris Kerberos */ (void) memcpy(rhost, server->data[1].data, server->data[1].length); rhost[server->data[1].length] = '\0'; } retval = krb5_os_hostaddr(context, rhost, &addrs); if (retval) goto errout; } creds.keyblock.enctype = enctype; creds.times = tgt.times; creds.times.starttime = 0; kdcoptions = flags2options(tgt.ticket_flags)|KDC_OPT_FORWARDED; if (!forwardable) /* Reset KDC_OPT_FORWARDABLE */ kdcoptions &= ~(KDC_OPT_FORWARDABLE); if ((retval = krb5_get_cred_via_tkt(context, &tgt, kdcoptions, addrs, &creds, &pcreds))) { if (enctype) { creds.keyblock.enctype = 0; if ((retval = krb5_get_cred_via_tkt(context, &tgt, kdcoptions, addrs, &creds, &pcreds))) goto errout; } else goto errout; } retval = krb5_mk_1cred(context, auth_context, pcreds, &scratch, &replaydata); krb5_free_creds(context, pcreds); /* * Solaris Kerberos: changed this logic from the MIT 1.2.1 version to be * more robust. */ if (scratch) { if (retval) krb5_free_data(context, scratch); else { *outbuf = *scratch; krb5_xfree(scratch); } } errout: if (addrs) krb5_free_addresses(context, addrs); /* Solaris Kerberos */ if (close_cc) (void) krb5_cc_close(context, cc); if (free_rhost) free(rhost); krb5_free_cred_contents(context, &creds); krb5_free_cred_contents(context, &tgt); return retval; }
int do_krb5_comm(krb5_context context, krb5_keytab keytab, krb5_principal server, char *cmddir) { struct sockaddr_in c_saddr, s_saddr; socklen_t namelen; int sock = 0; int len; char buff[BUFFSIZE]; char *cname = NULL; krb5_error_code retval; krb5_data kdata, message; krb5_auth_context auth_context = NULL; krb5_ticket *ticket; krb5_address ckaddr, skaddr; krb5_rcache rcache; krb5_data rcache_name; long srand, rrand; int fd[2]; char rcname_piece[RC_PIECE_MAXLEN]; namelen = sizeof(c_saddr); if (getpeername(sock, (struct sockaddr *)&c_saddr, &namelen) < 0) { syslog(LOG_ERR, "getpeername: %m"); return 1; } namelen = sizeof(s_saddr); if (getsockname(sock, (struct sockaddr *)&s_saddr, &namelen) < 0) { syslog(LOG_ERR, "getsockname: %m"); return 1; } /* INIT MSG = random number */ srand = random(); /* Send it */ if (send(sock, &srand, sizeof(srand), 0) < 0) { syslog(LOG_ERR, "%m while sending init message"); return 1; } if (recv(sock, &rrand, sizeof(rrand), 0) < 0) { syslog(LOG_ERR, "%m while receiving init reply"); return 1; } /* Reply should contain the same message (number) */ if (srand != rrand) { syslog(LOG_ERR, "Bad init reply"); return 1; } /* Do authentication */ if (retval = krb5_recvauth(context, &auth_context, (krb5_pointer)&sock, AFSADM_VERSION, server, 0, keytab, &ticket)) { syslog(LOG_ERR, "recvauth failed: %s", error_message(retval)); exit(1); } /* Get client name */ if (retval = krb5_unparse_name(context, ticket->enc_part2->client, &cname)) { syslog(LOG_ERR, "unparse failed: %s", error_message(retval)); return 1; } if (ticket) krb5_free_ticket(context, ticket); if (debug) syslog(LOG_DEBUG, "Principal %s", cname); /*******************************************************************/ ckaddr.addrtype = ADDRTYPE_IPPORT; ckaddr.length = sizeof(c_saddr.sin_port); ckaddr.contents = (krb5_octet *)&c_saddr.sin_port; skaddr.addrtype = ADDRTYPE_IPPORT; skaddr.length = sizeof(s_saddr.sin_port); skaddr.contents = (krb5_octet *)&s_saddr.sin_port; if ((retval = krb5_auth_con_setports(context, auth_context, &skaddr, &ckaddr))) { syslog(LOG_ERR, "%s while setting ports", error_message(retval)); return 1; } /* Set foreign_addr for rd_priv() */ ckaddr.addrtype = ADDRTYPE_INET; ckaddr.length = sizeof(c_saddr.sin_addr); ckaddr.contents = (krb5_octet *)&c_saddr.sin_addr; /* Set local_addr */ skaddr.addrtype = ADDRTYPE_INET; skaddr.length = sizeof(s_saddr.sin_addr); skaddr.contents = (krb5_octet *)&s_saddr.sin_addr; if ((retval = krb5_auth_con_setaddrs(context, auth_context, &skaddr, &ckaddr))) { syslog(LOG_ERR, "%s while setting addrs", error_message(retval)); return 1; } /* Receive a request */ if ((len = recv(sock, (char *)buff, sizeof(buff), 0)) < 0) { syslog(LOG_ERR, "%m while receiving datagram"); return 1; } kdata.length = len; kdata.data = buff; if (debug) syslog(LOG_DEBUG, "Received %d bytes", len); /* Decrypt it */ if ((retval = krb5_rd_priv(context, auth_context, &kdata, &message, NULL))) { syslog(LOG_ERR, "%s while verifying PRIV message", error_message(retval)); return 1; } if (message.length > 0) { #ifdef __osf__ sprintf(rcname_piece, "afsadmd_%d", getpid()); #else snprintf(rcname_piece, RC_PIECE_MAXLEN, "afsadmd_%d", getpid()); #endif rcache_name.data = rcname_piece; rcache_name.length = strlen(rcache_name.data); if ((retval = krb5_get_server_rcache(context, &rcache_name, &rcache))) { syslog(LOG_ERR, "%s while getting server rcache", error_message(retval)); return 1; } /* set auth_context rcache */ if (retval = krb5_auth_con_setrcache(context, auth_context, rcache)) { syslog(LOG_ERR, "%s while setting rcache", error_message(retval)); return 1; } /********************************************************************* * Call the desired command, read stdout/stderr, send it *********************************************************************/ /* create fork */ if (pipe(fd) == -1) printf("Failed create fork with pipe().\n"); if (fork() == 0) { close(fd[0]); close(1); close(2); dup2(fd[1], 1); dup2(fd[1], 2); /* Call required command */ do_command(context, keytab, server, cname, message.data, cmddir ); krb5_xfree(message.data); exit(0); } else { /* Read stdout/stderr from pipe, store it to the buffer, encrypt it a send to the client */ krb5_data message, kdata; char buff[PIPEBUFF]; int n = 0; int len = 0; int sent = 0; int counter = 0; int end = 0; short netlen; time_t starttime, oldtime, newtime; FILE *pipedes; close(fd[1]); pipedes = fdopen(fd[0], "r"); starttime = oldtime = time(NULL); for (n = 0; end == 0; ) { /* Read line from pipe */ if (fgets(buff + n, PIPEBUFF - n, pipedes) == NULL) end++; else n = strlen(buff); /* Get time */ newtime = time(NULL); /* Send buffer when * a) buffer is full * b) buffer contains data and * 1) end-of-file encountered (end flag) * 2) buffer sent before 1s */ if ((n == PIPEBUFF) || (((newtime > oldtime) || end ) && (n != 0))) { /* Prepare data for sending */ message.data = buff; message.length = n; kdata.data = NULL; /* Make the encrypted message */ if ((retval = krb5_mk_priv(context, auth_context, &message, &kdata, NULL))) { syslog(LOG_ERR, "%s while making KRB_PRIV message", error_message(retval)); return 1; } /* Convert byte order */ netlen = htons((short)kdata.length); /* Send len of encrypted data */ if ((len = send(sock, (char *)&netlen, sizeof(netlen), 0)) != sizeof(netlen)) { krb5_xfree(kdata.data); syslog(LOG_ERR, "%m while sending len of PRIV message"); return 1; } /* Send it */ if ((len = send(sock, (char *)kdata.data, kdata.length, 0)) != kdata.length) { syslog(LOG_ERR, "%m while sending PRIV message"); krb5_xfree(kdata.data); return 1; } /* Statistics */ sent += len; counter++; /* Timestanmp */ oldtime = newtime; n = 0; krb5_xfree(kdata.data); } } newtime = time(NULL); if (debug) syslog(LOG_DEBUG, "Sent %d bytes in %ds [%d fragment(s)]", sent, (int)(newtime - starttime), counter); } } //FIXME: There is no way to close or destroy rcache declared in krb5 headers //krb5_rc_destroy(context, rcache); /* set auth_context rcache */ if (retval = krb5_auth_con_setrcache(context, auth_context, rcache)) { syslog(LOG_ERR, "%s while setting rcache to NULL", error_message(retval)); return 1; } free(cname); krb5_auth_con_free(context, auth_context); return 0; }
krb5_error_code KRB5_CALLCONV krb5_425_conv_principal(krb5_context context, const char *name, const char *instance, const char *realm, krb5_principal *princ) { const struct krb_convert *p; char buf[256]; /* V4 instances are limited to 40 characters */ krb5_error_code retval; char *domain, *cp; char **full_name = 0; const char *names[5], *names2[2]; void* iterator = NULL; char** v4realms = NULL; char* realm_name = NULL; char* dummy_value = NULL; /* First, convert the realm, since the v4 realm is not necessarily the same as the v5 realm To do that, iterate over all the realms in the config file, looking for a matching v4_realm line */ names2 [0] = "realms"; names2 [1] = NULL; retval = profile_iterator_create (context -> profile, names2, PROFILE_ITER_LIST_SECTION | PROFILE_ITER_SECTIONS_ONLY, &iterator); while (retval == 0) { retval = profile_iterator (&iterator, &realm_name, &dummy_value); if ((retval == 0) && (realm_name != NULL)) { names [0] = "realms"; names [1] = realm_name; names [2] = "v4_realm"; names [3] = NULL; retval = profile_get_values (context -> profile, names, &v4realms); if ((retval == 0) && (v4realms != NULL) && (v4realms [0] != NULL) && (strcmp (v4realms [0], realm) == 0)) { realm = realm_name; break; } else if (retval == PROF_NO_RELATION) { /* If it's not found, just keep going */ retval = 0; } } else if ((retval == 0) && (realm_name == NULL)) { break; } if (v4realms != NULL) { profile_free_list(v4realms); v4realms = NULL; } if (realm_name != NULL) { profile_release_string (realm_name); realm_name = NULL; } if (dummy_value != NULL) { profile_release_string (dummy_value); dummy_value = NULL; } } if (instance) { if (instance[0] == '\0') { instance = 0; goto not_service; } p = sconv_list; while (1) { if (!p->v4_str) goto not_service; if (!strcmp(p->v4_str, name)) break; p++; } name = p->v5_str; if ((p->flags & DO_REALM_CONVERSION) && !strchr(instance, '.')) { names[0] = "realms"; names[1] = realm; names[2] = "v4_instance_convert"; names[3] = instance; names[4] = 0; retval = profile_get_values(context->profile, names, &full_name); if (retval == 0 && full_name && full_name[0]) { instance = full_name[0]; } else { strncpy(buf, instance, sizeof(buf)); buf[sizeof(buf) - 1] = '\0'; retval = krb5_get_realm_domain(context, realm, &domain); if (retval) return retval; if (domain) { for (cp = domain; *cp; cp++) if (isupper((unsigned char) (*cp))) *cp = tolower((unsigned char) *cp); strncat(buf, ".", sizeof(buf) - 1 - strlen(buf)); strncat(buf, domain, sizeof(buf) - 1 - strlen(buf)); krb5_xfree(domain); } instance = buf; } } } not_service: retval = krb5_build_principal(context, princ, strlen(realm), realm, name, instance, NULL); if (iterator) profile_iterator_free (&iterator); if (full_name) profile_free_list(full_name); if (v4realms) profile_free_list(v4realms); if (realm_name) profile_release_string (realm_name); if (dummy_value) profile_release_string (dummy_value); return retval; }
krb5_error_code krb5_db_fetch_mkey(krb5_context context, krb5_principal mname, krb5_enctype etype, krb5_boolean fromkeyboard, krb5_boolean twice, char *db_args, krb5_data * salt, krb5_keyblock * key) { krb5_error_code retval; char password[BUFSIZ]; krb5_data pwd; unsigned int size = sizeof(password); int kvno; krb5_keyblock tmp_key; memset(&tmp_key, 0, sizeof(tmp_key)); if (fromkeyboard) { krb5_data scratch; if ((retval = krb5_read_password(context, krb5_mkey_pwd_prompt1, twice ? krb5_mkey_pwd_prompt2 : 0, password, &size))) { goto clean_n_exit; } pwd.data = password; pwd.length = size; if (!salt) { retval = krb5_principal2salt(context, mname, &scratch); if (retval) goto clean_n_exit; } retval = krb5_c_string_to_key(context, etype, &pwd, salt ? salt : &scratch, key); if (!salt) krb5_xfree(scratch.data); memset(password, 0, sizeof(password)); /* erase it */ } else { kdb5_dal_handle *dal_handle; if (context->db_context == NULL) { retval = kdb_setup_lib_handle(context); if (retval) { goto clean_n_exit; } } dal_handle = (kdb5_dal_handle *) context->db_context; retval = kdb_lock_lib_lock(dal_handle->lib_handle, FALSE); if (retval) { goto clean_n_exit; } tmp_key.enctype = key->enctype; retval = dal_handle->lib_handle->vftabl.fetch_master_key(context, mname, &tmp_key, &kvno, db_args); get_errmsg(context, retval); kdb_unlock_lib_lock(dal_handle->lib_handle, FALSE); if (retval) { goto clean_n_exit; } key->contents = malloc(tmp_key.length); if (key->contents == NULL) { retval = ENOMEM; goto clean_n_exit; } key->magic = tmp_key.magic; key->enctype = tmp_key.enctype; key->length = tmp_key.length; memcpy(key->contents, tmp_key.contents, tmp_key.length); } clean_n_exit: if (tmp_key.contents) { memset(tmp_key.contents, 0, tmp_key.length); krb5_db_free(context, tmp_key.contents); } return retval; }
krb5_error_code KRB5_CALLCONV krb5_sendauth(krb5_context context, krb5_auth_context *auth_context, krb5_pointer fd, char *appl_version, krb5_principal client, krb5_principal server, krb5_flags ap_req_options, krb5_data *in_data, krb5_creds *in_creds, krb5_ccache ccache, krb5_error **error, krb5_ap_rep_enc_part **rep_result, krb5_creds **out_creds) { krb5_octet result; krb5_creds creds; krb5_creds * credsp = NULL; krb5_creds * credspout = NULL; krb5_error_code retval = 0; krb5_data inbuf, outbuf; int len; krb5_ccache use_ccache = 0; if (error) *error = 0; /* * First, send over the length of the sendauth version string; * then, we send over the sendauth version. Next, we send * over the length of the application version strings followed * by the string itself. */ outbuf.length = strlen(sendauth_version) + 1; outbuf.data = (char *) sendauth_version; if ((retval = krb5_write_message(context, fd, &outbuf))) return(retval); outbuf.length = strlen(appl_version) + 1; outbuf.data = appl_version; if ((retval = krb5_write_message(context, fd, &outbuf))) return(retval); /* * Now, read back a byte: 0 means no error, 1 means bad sendauth * version, 2 means bad application version */ len = krb5_net_read(context, *((int *) fd), (char *)&result, 1); if (len != 1) return((len < 0) ? errno : ECONNABORTED); if (result == 1) return(KRB5_SENDAUTH_BADAUTHVERS); else if (result == 2) return(KRB5_SENDAUTH_BADAPPLVERS); else if (result != 0) return(KRB5_SENDAUTH_BADRESPONSE); /* * We're finished with the initial negotiations; let's get and * send over the authentication header. (The AP_REQ message) */ /* * If no credentials were provided, try getting it from the * credentials cache. */ memset((char *)&creds, 0, sizeof(creds)); /* * See if we need to access the credentials cache */ if (!in_creds || !in_creds->ticket.length) { if (ccache) use_ccache = ccache; /* Solaris Kerberos */ else if ((retval = krb5int_cc_default(context, &use_ccache)) != 0) goto error_return; } if (!in_creds) { if ((retval = krb5_copy_principal(context, server, &creds.server))) goto error_return; if (client) retval = krb5_copy_principal(context, client, &creds.client); else retval = krb5_cc_get_principal(context, use_ccache, &creds.client); if (retval) { krb5_free_principal(context, creds.server); goto error_return; } /* creds.times.endtime = 0; -- memset 0 takes care of this zero means "as long as possible" */ /* creds.keyblock.enctype = 0; -- as well as this. zero means no session enctype preference */ in_creds = &creds; } if (!in_creds->ticket.length) { /* Solaris Kerberos */ if ((retval = krb5_get_credentials(context, 0, use_ccache, in_creds, &credsp)) != 0) goto error_return; credspout = credsp; } else { credsp = in_creds; } if (ap_req_options & AP_OPTS_USE_SUBKEY) { /* Provide some more fodder for random number code. This isn't strong cryptographically; the point here is not to guarantee randomness, but to make it less likely that multiple sessions could pick the same subkey. */ char rnd_data[1024]; GETPEERNAME_ARG3_TYPE len2; krb5_data d; d.length = sizeof (rnd_data); d.data = rnd_data; len2 = sizeof (rnd_data); if (getpeername (*(int*)fd, (GETPEERNAME_ARG2_TYPE *) rnd_data, &len2) == 0) { d.length = len2; /* Solaris Kerberos */ (void) krb5_c_random_seed (context, &d); } len2 = sizeof (rnd_data); if (getsockname (*(int*)fd, (GETSOCKNAME_ARG2_TYPE *) rnd_data, &len2) == 0) { d.length = len2; /* Solaris Kerberos */ (void) krb5_c_random_seed (context, &d); } } /* Solaris Kerberos */ if ((retval = krb5_mk_req_extended(context, auth_context, ap_req_options, in_data, credsp, &outbuf)) != 0) goto error_return; /* * First write the length of the AP_REQ message, then write * the message itself. */ retval = krb5_write_message(context, fd, &outbuf); free(outbuf.data); if (retval) goto error_return; /* * Now, read back a message. If it was a null message (the * length was zero) then there was no error. If not, we the * authentication was rejected, and we need to return the * error structure. */ /* Solaris Kerberos */ if ((retval = krb5_read_message(context, fd, &inbuf)) != 0) goto error_return; if (inbuf.length) { if (error) { /* Solaris Kerberos */ if ((retval = krb5_rd_error(context, &inbuf, error)) != 0) { krb5_xfree(inbuf.data); goto error_return; } } retval = KRB5_SENDAUTH_REJECTED; krb5_xfree(inbuf.data); goto error_return; } /* * If we asked for mutual authentication, we should now get a * length field, followed by a AP_REP message */ if ((ap_req_options & AP_OPTS_MUTUAL_REQUIRED)) { krb5_ap_rep_enc_part *repl = 0; /* Solaris Kerberos */ if ((retval = krb5_read_message(context, fd, &inbuf)) != 0) goto error_return; /* Solaris Kerberos */ if ((retval = krb5_rd_rep(context, *auth_context, &inbuf, &repl)) != 0) { if (repl) krb5_free_ap_rep_enc_part(context, repl); krb5_xfree(inbuf.data); goto error_return; } krb5_xfree(inbuf.data); /* * If the user wants to look at the AP_REP message, * copy it for them. */ if (rep_result) *rep_result = repl; else krb5_free_ap_rep_enc_part(context, repl); } retval = 0; /* Normal return */ if (out_creds) { *out_creds = credsp; credspout = NULL; } error_return: krb5_free_cred_contents(context, &creds); if (credspout != NULL) krb5_free_creds(context, credspout); /* Solaris Kerberos */ if (!ccache && use_ccache) (void) krb5_cc_close(context, use_ccache); return(retval); }
static int list_caches(krb5_context context) { krb5_cc_cache_cursor cursor; const char *cdef_name; char *def_name; krb5_error_code ret; krb5_ccache id; rtbl_t ct; cdef_name = krb5_cc_default_name(context); if (cdef_name == NULL) krb5_errx(context, 1, "krb5_cc_default_name"); def_name = strdup(cdef_name); ret = krb5_cc_cache_get_first (context, NULL, &cursor); if (ret == KRB5_CC_NOSUPP) return 0; else if (ret) krb5_err (context, 1, ret, "krb5_cc_cache_get_first"); ct = rtbl_create(); rtbl_add_column(ct, COL_NAME, 0); rtbl_add_column(ct, COL_CACHENAME, 0); rtbl_add_column(ct, COL_EXPIRES, 0); rtbl_add_column(ct, COL_DEFCACHE, 0); rtbl_set_prefix(ct, " "); rtbl_set_column_prefix(ct, COL_NAME, ""); while (krb5_cc_cache_next (context, cursor, &id) == 0) { krb5_principal principal = NULL; int expired = 0; char *name; time_t t; ret = krb5_cc_get_principal(context, id, &principal); if (ret) continue; expired = check_for_tgt (context, id, principal, &t); ret = krb5_cc_get_friendly_name(context, id, &name); if (ret == 0) { const char *str; char *fname; rtbl_add_column_entry(ct, COL_NAME, name); rtbl_add_column_entry(ct, COL_CACHENAME, krb5_cc_get_name(context, id)); if (expired) str = N_(">>> Expired <<<", ""); else str = printable_time(t); rtbl_add_column_entry(ct, COL_EXPIRES, str); free(name); ret = krb5_cc_get_full_name(context, id, &fname); if (ret) krb5_err (context, 1, ret, "krb5_cc_get_full_name"); if (strcmp(fname, def_name) == 0) rtbl_add_column_entry(ct, COL_DEFCACHE, "*"); else rtbl_add_column_entry(ct, COL_DEFCACHE, ""); krb5_xfree(fname); } krb5_cc_close(context, id); krb5_free_principal(context, principal); } krb5_cc_cache_end_seq_get(context, cursor); free(def_name); rtbl_format(ct, stdout); rtbl_destroy(ct); return 0; }