krb5_error_code KRB5_LIB_FUNCTION krb5_kt_get_full_name(krb5_context context, krb5_keytab keytab, char **str) { char type[KRB5_KT_PREFIX_MAX_LEN]; char name[MAXPATHLEN]; krb5_error_code ret; *str = NULL; ret = krb5_kt_get_type(context, keytab, type, sizeof(type)); if (ret) return ret; ret = krb5_kt_get_name(context, keytab, name, sizeof(name)); if (ret) return ret; if (asprintf(str, "%s:%s", type, name) == -1) { krb5_set_error_string(context, "malloc - out of memory"); *str = NULL; return ENOMEM; } return 0; }
static krb5_error_code mcc_resolve(krb5_context context, krb5_ccache *id, const char *res) { krb5_mcache *m; HEIMDAL_MUTEX_lock(&mcc_mutex); for (m = mcc_head; m != NULL; m = m->next) if (strcmp(m->name, res) == 0) break; HEIMDAL_MUTEX_unlock(&mcc_mutex); if (m != NULL) { m->refcnt++; (*id)->data.data = m; (*id)->data.length = sizeof(*m); return 0; } m = mcc_alloc(res); if (m == NULL) { krb5_set_error_string (context, "malloc: out of memory"); return KRB5_CC_NOMEM; } (*id)->data.data = m; (*id)->data.length = sizeof(*m); return 0; }
/** * Wrapper around sqlite3_prepare_v2. * * @param context The current krb5 context * @param statement Where to store the pointer to the statement * after preparing it * @param str SQL code for the statement * * @return 0 if OK, an error code if not */ static krb5_error_code hdb_sqlite_prepare_stmt(krb5_context context, sqlite3 *db, sqlite3_stmt **statement, const char *str) { int ret, tries = 0; ret = sqlite3_prepare_v2(db, str, -1, statement, NULL); while((tries++ < MAX_RETRIES) && ((ret == SQLITE_BUSY) || (ret == SQLITE_IOERR_BLOCKED) || (ret == SQLITE_LOCKED))) { krb5_warnx(context, "hdb-sqlite: prepare busy"); sleep(1); ret = sqlite3_prepare_v2(db, str, -1, statement, NULL); } if (ret != SQLITE_OK) { krb5_set_error_string(context, "Failed to prepare stmt %s: %s", str, sqlite3_errmsg(db)); return EINVAL; } return 0; }
static krb5_error_code akf_start_seq_get(krb5_context context, krb5_keytab id, krb5_kt_cursor *c) { int32_t ret; struct akf_data *d = id->data; c->fd = open (d->filename, O_RDONLY|O_BINARY, 0600); if (c->fd < 0) { ret = errno; krb5_set_error_string(context, "open(%s): %s", d->filename, strerror(ret)); return ret; } c->sp = krb5_storage_from_fd(c->fd); ret = krb5_ret_int32(c->sp, &d->num_entries); if(ret) { krb5_storage_free(c->sp); close(c->fd); krb5_clear_error_string (context); if(ret == KRB5_KT_END) return KRB5_KT_NOTFOUND; return ret; } return 0; }
krb5_error_code KRB5_LIB_FUNCTION krb5_expand_hostname (krb5_context context, const char *orig_hostname, char **new_hostname) { struct addrinfo *ai, *a, hints; int error; if (!context->dns_canonicalize_hostname) return copy_hostname (context, orig_hostname, new_hostname); memset (&hints, 0, sizeof(hints)); hints.ai_flags = AI_CANONNAME; error = getaddrinfo (orig_hostname, NULL, &hints, &ai); if (error) return copy_hostname (context, orig_hostname, new_hostname); for (a = ai; a != NULL; a = a->ai_next) { if (a->ai_canonname != NULL) { *new_hostname = strdup (a->ai_canonname); freeaddrinfo (ai); if (*new_hostname == NULL) { krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } else { return 0; } } } freeaddrinfo (ai); return copy_hostname (context, orig_hostname, new_hostname); }
krb5_error_code KRB5_LIB_FUNCTION krb5_check_transited_realms(krb5_context context, const char *const *realms, int num_realms, int *bad_realm) { int i; int ret = 0; char **bad_realms = krb5_config_get_strings(context, NULL, "libdefaults", "transited_realms_reject", NULL); if(bad_realms == NULL) return 0; for(i = 0; i < num_realms; i++) { char **p; for(p = bad_realms; *p; p++) if(strcmp(*p, realms[i]) == 0) { krb5_set_error_string (context, "no transit through realm %s", *p); ret = KRB5KRB_AP_ERR_ILL_CR_TKT; if(bad_realm) *bad_realm = i; break; } } krb5_config_free_strings(bad_realms); return ret; }
krb5_error_code hdb_print_entry(krb5_context context, HDB *db, hdb_entry *entry, void *data) { krb5_error_code ret; krb5_storage *sp; FILE *f = data; fflush(f); sp = krb5_storage_from_fd(fileno(f)); if(sp == NULL) { krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } ret = entry2string_int(context, sp, entry); if(ret) { krb5_storage_free(sp); return ret; } krb5_storage_write(sp, "\n", 1); krb5_storage_free(sp); return 0; }
static krb5_error_code calculate_reply_hash(krb5_context context, krb5_keyblock *key, Kx509Response *rep) { HMAC_CTX ctx; HMAC_CTX_init(&ctx); HMAC_Init_ex(&ctx, key->keyvalue.data, key->keyvalue.length, EVP_sha1(), NULL); rep->hash->length = HMAC_size(&ctx); rep->hash->data = malloc(rep->hash->length); if (rep->hash->data == NULL) { HMAC_CTX_cleanup(&ctx); krb5_set_error_string(context, "out of memory"); return ENOMEM; } HMAC_Update(&ctx, version_2_0, sizeof(version_2_0)); if (rep->error_code) { int32_t t = *rep->error_code; do { unsigned char p = (t & 0xff); HMAC_Update(&ctx, &p, 1); t >>= 8; } while (t); }
/* * Removes a principal, including aliases and associated entry. */ static krb5_error_code hdb_sqlite_remove(krb5_context context, HDB *db, krb5_const_principal principal) { krb5_error_code ret; char *principal_string; hdb_sqlite_db *hsdb = (hdb_sqlite_db*)(db->hdb_db); ret = krb5_unparse_name(context, principal, &principal_string); if (ret) { free(principal_string); return ret; } sqlite3_stmt *remove = hsdb->remove; sqlite3_bind_text(remove, 1, principal_string, -1, SQLITE_STATIC); ret = hdb_sqlite_step(context, hsdb->db, remove); if (ret != SQLITE_DONE) { krb5_set_error_string(context, "sqlite remove failed: %d", ret); } else ret = 0; sqlite3_clear_bindings(remove); sqlite3_reset(remove); return ret; }
/** * A wrapper around sqlite3_exec. * * @param context The current krb5 context * @param database An open sqlite3 database handle * @param statement SQL code to execute * @param error_code What to return if the statement fails * * @return 0 if OK, else error_code */ static krb5_error_code hdb_sqlite_exec_stmt(krb5_context context, sqlite3 *database, const char *statement, krb5_error_code error_code) { int ret; ret = sqlite3_exec(database, statement, NULL, NULL, NULL); while(((ret == SQLITE_BUSY) || (ret == SQLITE_IOERR_BLOCKED) || (ret == SQLITE_LOCKED))) { krb5_warnx(context, "hdb-sqlite: exec busy: %d", (int)getpid()); sleep(1); ret = sqlite3_exec(database, statement, NULL, NULL, NULL); } if (ret != SQLITE_OK && error_code) { krb5_set_error_string(context, "Execute %s: %s", statement, sqlite3_errmsg(database)); return error_code; } return 0; }
krb5_error_code KRB5_LIB_FUNCTION krb5_get_init_creds_opt_get_error(krb5_context context, krb5_get_init_creds_opt *opt, KRB_ERROR **error) { krb5_error_code ret; *error = NULL; ret = require_ext_opt(context, opt, "init_creds_opt_get_error"); if (ret) return ret; if (opt->opt_private->error == NULL) return 0; *error = malloc(sizeof(**error)); if (*error == NULL) { krb5_set_error_string(context, "malloc - out memory"); return ENOMEM; } ret = copy_KRB_ERROR(*error, opt->opt_private->error); if (ret) krb5_clear_error_string(context); return 0; }
krb5_error_code hdb_entry2string (krb5_context context, hdb_entry *ent, char **str) { krb5_error_code ret; krb5_data data; krb5_storage *sp; sp = krb5_storage_emem(); if(sp == NULL) { krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } ret = entry2string_int(context, sp, ent); if(ret) { krb5_storage_free(sp); return ret; } krb5_storage_write(sp, "\0", 1); krb5_storage_to_data(sp, &data); krb5_storage_free(sp); *str = data.data; return 0; }
krb5_error_code KRB5_LIB_FUNCTION krb5_copy_ticket(krb5_context context, const krb5_ticket *from, krb5_ticket **to) { krb5_error_code ret; krb5_ticket *tmp; *to = NULL; tmp = malloc(sizeof(*tmp)); if(tmp == NULL) { krb5_set_error_string (context, "malloc: out of memory"); return ENOMEM; } if((ret = copy_EncTicketPart(&from->ticket, &tmp->ticket))){ free(tmp); return ret; } ret = krb5_copy_principal(context, from->client, &tmp->client); if(ret){ free_EncTicketPart(&tmp->ticket); free(tmp); return ret; } ret = krb5_copy_principal(context, from->server, &tmp->server); if(ret){ krb5_free_principal(context, tmp->client); free_EncTicketPart(&tmp->ticket); free(tmp); return ret; } *to = tmp; return 0; }
static krb5_error_code any_remove_entry(krb5_context context, krb5_keytab id, krb5_keytab_entry *entry) { struct any_data *a = id->data; krb5_error_code ret; int found = 0; while(a != NULL) { ret = krb5_kt_remove_entry(context, a->kt, entry); if(ret == 0) found++; else { if(ret != KRB5_KT_NOWRITE && ret != KRB5_KT_NOTFOUND) { krb5_set_error_string(context, "failed to remove entry from %s", a->name); return ret; } } a = a->next; } if(!found) return KRB5_KT_NOTFOUND; return 0; }
static void plugin_get_hosts(krb5_context context, struct krb5_krbhst_data *kd, enum locate_service_type type) { struct krb5_plugin *list = NULL, *e; krb5_error_code ret; ret = _krb5_plugin_find(context, PLUGIN_TYPE_DATA, "resolve", &list); if(ret != 0 || list == NULL) return; kd->flags |= KD_CONFIG_EXISTS; for (e = list; e != NULL; e = _krb5_plugin_get_next(e)) { krb5plugin_service_locate_ftable *service; void *ctx; service = _krb5_plugin_get_symbol(e); if (service->minor_version != 0) continue; (*service->init)(context, &ctx); ret = (*service->lookup)(ctx, type, kd->realm, 0, 0, add_locate, kd); (*service->fini)(ctx); if (ret) { krb5_set_error_string(context, "Plugin failed to lookup"); break; } } _krb5_plugin_free(list); }
krb5_error_code KRB5_LIB_FUNCTION krb5_get_kdc_cred(krb5_context context, krb5_ccache id, krb5_kdc_flags flags, krb5_addresses *addresses, Ticket *second_ticket, krb5_creds *in_creds, krb5_creds **out_creds ) { krb5_error_code ret; krb5_creds *krbtgt; *out_creds = calloc(1, sizeof(**out_creds)); if(*out_creds == NULL) { krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } ret = _krb5_get_krbtgt (context, id, in_creds->server->realm, &krbtgt); if(ret) { free(*out_creds); return ret; } ret = get_cred_kdc(context, id, flags, addresses, in_creds, krbtgt, *out_creds); krb5_free_creds (context, krbtgt); if(ret) free(*out_creds); return ret; }
static krb5_error_code mcc_store_cred(krb5_context context, krb5_ccache id, krb5_creds *creds) { krb5_mcache *m = MCACHE(id); krb5_error_code ret; struct link *l; if (MISDEAD(m)) return ENOENT; l = malloc (sizeof(*l)); if (l == NULL) { krb5_set_error_string (context, "malloc: out of memory"); return KRB5_CC_NOMEM; } l->next = m->creds; m->creds = l; memset (&l->cred, 0, sizeof(l->cred)); ret = krb5_copy_creds_contents (context, creds, &l->cred); if (ret) { m->creds = l->next; free (l); return ret; } return 0; }
krb5_error_code KRB5_LIB_FUNCTION krb5_rc_store(krb5_context context, krb5_rcache id, krb5_donot_replay *rep) { struct rc_entry ent, tmp; time_t t; FILE *f; int ret; ent.stamp = time(NULL); checksum_authenticator(rep, ent.data); f = fopen(id->name, "r"); if(f == NULL) { ret = errno; krb5_set_error_string (context, "open(%s): %s", id->name, strerror(ret)); return ret; } fread(&tmp, sizeof(ent), 1, f); t = ent.stamp - tmp.stamp; while(fread(&tmp, sizeof(ent), 1, f)){ if(tmp.stamp < t) continue; if(memcmp(tmp.data, ent.data, sizeof(ent.data)) == 0){ fclose(f); krb5_clear_error_string (context); return KRB5_RC_REPLAY; } } if(ferror(f)){ ret = errno; fclose(f); krb5_set_error_string (context, "%s: %s", id->name, strerror(ret)); return ret; } fclose(f); f = fopen(id->name, "a"); if(f == NULL) { krb5_set_error_string (context, "open(%s): %s", id->name, strerror(errno)); return KRB5_RC_IO_UNKNOWN; } fwrite(&ent, 1, sizeof(ent), f); fclose(f); return 0; }
krb5_error_code KRB5_LIB_FUNCTION _krb5_krb_create_auth_reply(krb5_context context, const char *pname, const char *pinst, const char *prealm, int32_t time_ws, int n, uint32_t x_date, unsigned char kvno, const krb5_data *cipher, krb5_data *data) { krb5_error_code ret; krb5_storage *sp; krb5_data_zero(data); sp = krb5_storage_emem(); if (sp == NULL) { krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE); RCHECK(ret, krb5_store_int8(sp, KRB_PROT_VERSION), error); RCHECK(ret, krb5_store_int8(sp, AUTH_MSG_KDC_REPLY), error); RCHECK(ret, put_nir(sp, pname, pinst, prealm), error); RCHECK(ret, krb5_store_int32(sp, time_ws), error); RCHECK(ret, krb5_store_int8(sp, n), error); RCHECK(ret, krb5_store_int32(sp, x_date), error); RCHECK(ret, krb5_store_int8(sp, kvno), error); RCHECK(ret, krb5_store_int16(sp, cipher->length), error); ret = krb5_storage_write(sp, cipher->data, cipher->length); if (ret != cipher->length) { ret = EINVAL; goto error; } ret = krb5_storage_to_data(sp, data); error: krb5_storage_free(sp); if (ret) krb5_set_error_string(context, "Failed to encode kerberos 4 ticket"); return ret; }
krb5_error_code KRB5_LIB_FUNCTION krb5_kt_resolve(krb5_context context, const char *name, krb5_keytab *id) { krb5_keytab k; int i; const char *type, *residual; size_t type_len; krb5_error_code ret; residual = strchr(name, ':'); if(residual == NULL) { type = "FILE"; type_len = strlen(type); residual = name; } else { type = name; type_len = residual - name; residual++; } for(i = 0; i < context->num_kt_types; i++) { if(strncasecmp(type, context->kt_types[i].prefix, type_len) == 0) break; } if(i == context->num_kt_types) { krb5_set_error_string(context, "unknown keytab type %.*s", (int)type_len, type); return KRB5_KT_UNKNOWN_TYPE; } k = malloc (sizeof(*k)); if (k == NULL) { krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } memcpy(k, &context->kt_types[i], sizeof(*k)); k->data = NULL; ret = (*k->resolve)(context, residual, k); if(ret) { free(k); k = NULL; } *id = k; return ret; }
/** * Retrieves an entry by searching for the given * principal in the Principal database table, both * for canonical principals and aliases. * * @param context The current krb5_context * @param db Heimdal database handle * @param principal The principal whose entry to search for * @param flags Currently only for HDB_F_DECRYPT * * @return 0 if everything worked, an error code if not */ static krb5_error_code hdb_sqlite_fetch(krb5_context context, HDB *db, krb5_const_principal principal, unsigned flags, hdb_entry_ex *entry) { int sqlite_error; krb5_error_code ret; char *principal_string; hdb_sqlite_db *hsdb = (hdb_sqlite_db*)(db->hdb_db); sqlite3_stmt *fetch = hsdb->fetch; krb5_data value; ret = krb5_unparse_name(context, principal, &principal_string); if (ret) { free(principal_string); return ret; } sqlite3_bind_text(fetch, 1, principal_string, -1, SQLITE_STATIC); sqlite_error = hdb_sqlite_step(context, hsdb->db, fetch); if (sqlite_error != SQLITE_ROW) { if(sqlite_error == SQLITE_DONE) { ret = HDB_ERR_NOENTRY; goto out; } else { krb5_set_error_string(context, "sqlite fetch failed: %d", sqlite_error); ret = EINVAL; goto out; } } if (db->hdb_master_key_set && (flags & HDB_F_DECRYPT)) { ret = hdb_unseal_keys(context, db, &entry->entry); if(ret) { hdb_free_entry(context, entry); goto out; } } value.length = sqlite3_column_bytes(fetch, 0); value.data = (void *) sqlite3_column_blob(fetch, 0); ret = hdb_value2entry(context, &value, &entry->entry); if(ret) goto out; ret = 0; out: sqlite3_clear_bindings(fetch); sqlite3_reset(fetch); free(principal_string); return ret; }
static int expand_realms(krb5_context context, struct tr_realm *realms, const char *client_realm) { struct tr_realm *r; const char *prev_realm = NULL; for(r = realms; r; r = r->next){ if(r->trailing_dot){ char *tmp; size_t len; if(prev_realm == NULL) prev_realm = client_realm; len = strlen(r->realm) + strlen(prev_realm) + 1; tmp = realloc(r->realm, len); if(tmp == NULL){ free_realms(realms); krb5_set_error_string (context, "malloc: out of memory"); return ENOMEM; } r->realm = tmp; strlcat(r->realm, prev_realm, len); }else if(r->leading_slash && !r->leading_space && prev_realm){ /* yet another exception: if you use x500-names, the leading realm doesn't have to be "quoted" with a space */ char *tmp; size_t len = strlen(r->realm) + strlen(prev_realm) + 1; tmp = malloc(len); if(tmp == NULL){ free_realms(realms); krb5_set_error_string (context, "malloc: out of memory"); return ENOMEM; } strlcpy(tmp, prev_realm, len); strlcat(tmp, r->realm, len); free(r->realm); r->realm = tmp; } prev_realm = r->realm; } return 0; }
krb5_error_code KRB5_LIB_FUNCTION krb5_rc_resolve_type(krb5_context context, krb5_rcache *id, const char *type) { *id = NULL; if(strcmp(type, "FILE")) { krb5_set_error_string (context, "replay cache type %s not supported", type); return KRB5_RC_TYPE_NOTFOUND; } *id = calloc(1, sizeof(**id)); if(*id == NULL) { krb5_set_error_string (context, "malloc: out of memory"); return KRB5_RC_MALLOC; } return 0; }
static krb5_error_code string_to_list (krb5_context context, const char *s, krb5_realm **list) { *list = malloc (2 * sizeof(**list)); if (*list == NULL) { krb5_set_error_string (context, "malloc: out of memory"); return ENOMEM; } (*list)[0] = strdup (s); if ((*list)[0] == NULL) { free (*list); krb5_set_error_string (context, "malloc: out of memory"); return ENOMEM; } (*list)[1] = NULL; return 0; }
krb5_error_code KRB5_LIB_FUNCTION krb5_copy_principal(krb5_context context, krb5_const_principal inprinc, krb5_principal *outprinc) { krb5_principal p = malloc(sizeof(*p)); if (p == NULL) { krb5_set_error_string (context, "malloc: out of memory"); return ENOMEM; } if(copy_Principal(inprinc, p)) { free(p); krb5_set_error_string (context, "malloc: out of memory"); return ENOMEM; } *outprinc = p; return 0; }
krb5_error_code KRB5_LIB_FUNCTION _krb5_krb_cr_err_reply(krb5_context context, const char *name, const char *inst, const char *realm, uint32_t time_ws, uint32_t e, const char *e_string, krb5_data *data) { krb5_error_code ret; krb5_storage *sp; krb5_data_zero(data); if (name == NULL) name = ""; if (inst == NULL) inst = ""; if (realm == NULL) realm = ""; if (e_string == NULL) e_string = ""; sp = krb5_storage_emem(); if (sp == NULL) { krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_BE); RCHECK(ret, krb5_store_int8(sp, KRB_PROT_VERSION), error); RCHECK(ret, krb5_store_int8(sp, AUTH_MSG_ERR_REPLY), error); RCHECK(ret, put_nir(sp, name, inst, realm), error); RCHECK(ret, krb5_store_int32(sp, time_ws), error); RCHECK(ret, krb5_store_int32(sp, e), error); RCHECK(ret, krb5_store_stringz(sp, e_string), error); ret = krb5_storage_to_data(sp, data); error: krb5_storage_free(sp); if (ret) krb5_set_error_string(context, "Failed to encode kerberos 4 error"); return 0; }
krb5_error_code KRB5_LIB_FUNCTION krb5_get_creds_opt_alloc(krb5_context context, krb5_get_creds_opt *opt) { *opt = calloc(1, sizeof(**opt)); if (*opt == NULL) { krb5_set_error_string(context, "malloc: out of memory"); return ENOMEM; } return 0; }
krb5_error_code KRB5_LIB_FUNCTION _krb5_rd_req_out_ctx_alloc(krb5_context context, krb5_rd_req_out_ctx *ctx) { *ctx = calloc(1, sizeof(**ctx)); if (*ctx == NULL) { krb5_set_error_string(context, "out of memory"); return ENOMEM; } return 0; }
krb5_error_code KRB5_LIB_FUNCTION krb5_initlog(krb5_context context, const char *program, krb5_log_facility **fac) { krb5_log_facility *f = calloc(1, sizeof(*f)); if(f == NULL) { krb5_set_error_string (context, "malloc: out of memory"); return ENOMEM; } f->program = strdup(program); if(f->program == NULL){ free(f); krb5_set_error_string (context, "malloc: out of memory"); return ENOMEM; } *fac = f; return 0; }
static krb5_error_code mcc_default_name(krb5_context context, char **str) { *str = strdup("MEMORY:"); if (*str == NULL) { krb5_set_error_string(context, "out of memory"); return ENOMEM; } return 0; }