static krb5_error_code add_db(krb5_context context, struct krb5_kdc_configuration *c, const char *conf, const char *master_key) { krb5_error_code ret; void *ptr; ptr = realloc(c->db, (c->num_db + 1) * sizeof(*c->db)); if (ptr == NULL) { krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } c->db = ptr; ret = hdb_create(context, &c->db[c->num_db], conf); if(ret) return ret; c->num_db++; if (master_key) { ret = hdb_set_master_keyfile(context, c->db[c->num_db - 1], master_key); if (ret) return ret; } return 0; }
static kadm5_ret_t kadm5_s_init_with_context(krb5_context context, const char *client_name, const char *service_name, kadm5_config_params *realm_params, unsigned long struct_version, unsigned long api_version, void **server_handle) { kadm5_ret_t ret; kadm5_server_context *ctx; ret = _kadm5_s_init_context(&ctx, realm_params, context); if(ret) return ret; assert(ctx->config.dbname != NULL); assert(ctx->config.stash_file != NULL); assert(ctx->config.acl_file != NULL); assert(ctx->log_context.log_file != NULL); #ifndef NO_UNIX_SOCKETS assert(ctx->log_context.socket_name.sun_path[0] != '\0'); #else assert(ctx->log_context.socket_info != NULL); #endif ret = hdb_create(ctx->context, &ctx->db, ctx->config.dbname); if(ret) return ret; ret = hdb_set_master_keyfile (ctx->context, ctx->db, ctx->config.stash_file); if(ret) return ret; ctx->log_context.log_fd = -1; #ifndef NO_UNIX_SOCKETS ctx->log_context.socket_fd = socket (AF_UNIX, SOCK_DGRAM, 0); #else ctx->log_context.socket_fd = socket (ctx->log_context.socket_info->ai_family, ctx->log_context.socket_info->ai_socktype, ctx->log_context.socket_info->ai_protocol); #endif ret = krb5_parse_name(ctx->context, client_name, &ctx->caller); if(ret) return ret; ret = _kadm5_acl_init(ctx); if(ret) return ret; *server_handle = ctx; return 0; }
static krb5_error_code KRB5_CALLCONV hdb_start_seq_get(krb5_context context, krb5_keytab id, krb5_kt_cursor *cursor) { krb5_error_code ret; struct hdb_cursor *c; struct hdb_data *d = id->data; const char *dbname = d->dbname; const char *mkey = d->mkey; HDB *db; if (dbname == NULL) { /* * We don't support enumerating without being told what * backend to enumerate on */ ret = KRB5_KT_NOTFOUND; return ret; } ret = hdb_create (context, &db, dbname); if (ret) return ret; ret = hdb_set_master_keyfile (context, db, mkey); if (ret) { (*db->hdb_destroy)(context, db); return ret; } ret = (*db->hdb_open)(context, db, O_RDONLY, 0); if (ret) { (*db->hdb_destroy)(context, db); return ret; } cursor->data = c = malloc (sizeof(*c)); if(c == NULL){ (*db->hdb_close)(context, db); (*db->hdb_destroy)(context, db); krb5_set_error_message(context, ENOMEM, "malloc: out of memory"); return ENOMEM; } c->db = db; c->first = TRUE; c->next = TRUE; c->key_idx = 0; cursor->data = c; return ret; }
static krb5_error_code KRB5_CALLCONV hdb_get_entry(krb5_context context, krb5_keytab id, krb5_const_principal principal, krb5_kvno kvno, krb5_enctype enctype, krb5_keytab_entry *entry) { hdb_entry_ex ent; krb5_error_code ret; struct hdb_data *d = id->data; const char *dbname = d->dbname; const char *mkey = d->mkey; char *fdbname = NULL, *fmkey = NULL; HDB *db; int i; memset(&ent, 0, sizeof(ent)); if (dbname == NULL) { ret = find_db(context, &fdbname, &fmkey, principal); if (ret) return ret; dbname = fdbname; mkey = fmkey; } ret = hdb_create (context, &db, dbname); if (ret) goto out2; ret = hdb_set_master_keyfile (context, db, mkey); if (ret) { (*db->hdb_destroy)(context, db); goto out2; } ret = (*db->hdb_open)(context, db, O_RDONLY, 0); if (ret) { (*db->hdb_destroy)(context, db); goto out2; } ret = (*db->hdb_fetch_kvno)(context, db, principal, HDB_F_DECRYPT|HDB_F_KVNO_SPECIFIED| HDB_F_GET_CLIENT|HDB_F_GET_SERVER|HDB_F_GET_KRBTGT, kvno, &ent); if(ret == HDB_ERR_NOENTRY) { ret = KRB5_KT_NOTFOUND; goto out; }else if(ret) goto out; if(kvno && ent.entry.kvno != kvno) { hdb_free_entry(context, &ent); ret = KRB5_KT_NOTFOUND; goto out; } if(enctype == 0) if(ent.entry.keys.len > 0) enctype = ent.entry.keys.val[0].key.keytype; ret = KRB5_KT_NOTFOUND; for(i = 0; i < ent.entry.keys.len; i++) { if(ent.entry.keys.val[i].key.keytype == enctype) { krb5_copy_principal(context, principal, &entry->principal); entry->vno = ent.entry.kvno; krb5_copy_keyblock_contents(context, &ent.entry.keys.val[i].key, &entry->keyblock); ret = 0; break; } } hdb_free_entry(context, &ent); out: (*db->hdb_close)(context, db); (*db->hdb_destroy)(context, db); out2: free(fdbname); free(fmkey); return ret; }
int main(int argc, char **argv) { krb5_error_code ret; ret = krb5_init_context(&context); if (ret == KRB5_CONFIG_BADFORMAT) errx (1, "krb5_init_context failed to parse configuration file"); else if (ret) errx (1, "krb5_init_context failed: %d", ret); configure(argc, argv); if(databases == NULL) { db = malloc(sizeof(*db)); num_db = 1; ret = hdb_create(context, &db[0], NULL); if(ret) krb5_err(context, 1, ret, "hdb_create %s", HDB_DEFAULT_DB); ret = hdb_set_master_keyfile(context, db[0], NULL); if (ret) krb5_err(context, 1, ret, "hdb_set_master_keyfile"); } else { struct dbinfo *d; int i; /* count databases */ for(d = databases, i = 0; d; d = d->next, i++); db = malloc(i * sizeof(*db)); for(d = databases, num_db = 0; d; d = d->next, num_db++) { ret = hdb_create(context, &db[num_db], d->dbname); if(ret) krb5_err(context, 1, ret, "hdb_create %s", d->dbname); ret = hdb_set_master_keyfile(context, db[num_db], d->mkey_file); if (ret) krb5_err(context, 1, ret, "hdb_set_master_keyfile"); } } #ifdef HAVE_SIGACTION { struct sigaction sa; sa.sa_flags = 0; sa.sa_handler = sigterm; sigemptyset(&sa.sa_mask); sigaction(SIGINT, &sa, NULL); sigaction(SIGTERM, &sa, NULL); sigaction(SIGXCPU, &sa, NULL); sa.sa_handler = SIG_IGN; sigaction(SIGPIPE, &sa, NULL); } #else signal(SIGINT, sigterm); signal(SIGTERM, sigterm); signal(SIGXCPU, sigterm); signal(SIGPIPE, SIG_IGN); #endif if (detach_from_console) daemon(0, 0); pidfile(NULL); loop(); krb5_free_context(context); return 0; }
static krb5_error_code receive_everything (krb5_context context, int fd, kadm5_server_context *server_context, krb5_auth_context auth_context) { int ret; krb5_data data; int32_t vno = 0; int32_t opcode; krb5_storage *sp; char *dbname; HDB *mydb; krb5_warnx(context, "receive complete database"); asprintf(&dbname, "%s-NEW", server_context->db->hdb_name); ret = hdb_create(context, &mydb, dbname); if(ret) krb5_err(context,1, ret, "hdb_create"); free(dbname); ret = hdb_set_master_keyfile (context, mydb, server_context->config.stash_file); if(ret) krb5_err(context,1, ret, "hdb_set_master_keyfile"); /* I really want to use O_EXCL here, but given that I can't easily clean up on error, I won't */ ret = mydb->hdb_open(context, mydb, O_RDWR | O_CREAT | O_TRUNC, 0600); if (ret) krb5_err (context, 1, ret, "db->open"); sp = NULL; do { ret = krb5_read_priv_message(context, auth_context, &fd, &data); if (ret) { krb5_warn (context, ret, "krb5_read_priv_message"); goto cleanup; } sp = krb5_storage_from_data (&data); if (sp == NULL) krb5_errx (context, 1, "krb5_storage_from_data"); krb5_ret_int32 (sp, &opcode); if (opcode == ONE_PRINC) { krb5_data fake_data; hdb_entry_ex entry; krb5_storage_free(sp); fake_data.data = (char *)data.data + 4; fake_data.length = data.length - 4; memset(&entry, 0, sizeof(entry)); ret = hdb_value2entry (context, &fake_data, &entry.entry); if (ret) krb5_err (context, 1, ret, "hdb_value2entry"); ret = mydb->hdb_store(server_context->context, mydb, 0, &entry); if (ret) krb5_err (context, 1, ret, "hdb_store"); hdb_free_entry (context, &entry); krb5_data_free (&data); } else if (opcode == NOW_YOU_HAVE) ; else krb5_errx (context, 1, "strange opcode %d", opcode); } while (opcode == ONE_PRINC); if (opcode != NOW_YOU_HAVE) krb5_errx (context, 1, "receive_everything: strange %d", opcode); krb5_ret_int32 (sp, &vno); krb5_storage_free(sp); ret = kadm5_log_reinit (server_context); if (ret) krb5_err(context, 1, ret, "kadm5_log_reinit"); ret = kadm5_log_set_version (server_context, vno - 1); if (ret) krb5_err (context, 1, ret, "kadm5_log_set_version"); ret = kadm5_log_nop (server_context); if (ret) krb5_err (context, 1, ret, "kadm5_log_nop"); ret = mydb->hdb_rename (context, mydb, server_context->db->hdb_name); if (ret) krb5_err (context, 1, ret, "db->rename"); cleanup: krb5_data_free (&data); ret = mydb->hdb_close (context, mydb); if (ret) krb5_err (context, 1, ret, "db->close"); ret = mydb->hdb_destroy (context, mydb); if (ret) krb5_err (context, 1, ret, "db->destroy"); krb5_warnx(context, "receive complete database, version %ld", (long)vno); return ret; }
static kadm5_ret_t kadm5_s_init_with_context(krb5_context context, const char *client_name, const char *service_name, kadm5_config_params *realm_params, unsigned long struct_version, unsigned long api_version, void **server_handle) { kadm5_ret_t ret; kadm5_server_context *ctx; char *dbname; char *stash_file; *server_handle = NULL; ret = _kadm5_s_init_context(&ctx, realm_params, context); if (ret) return ret; if (realm_params->mask & KADM5_CONFIG_DBNAME) dbname = realm_params->dbname; else dbname = ctx->config.dbname; if (realm_params->mask & KADM5_CONFIG_STASH_FILE) stash_file = realm_params->stash_file; else stash_file = ctx->config.stash_file; assert(dbname != NULL); assert(stash_file != NULL); assert(ctx->config.acl_file != NULL); assert(ctx->log_context.log_file != NULL); #ifndef NO_UNIX_SOCKETS assert(ctx->log_context.socket_name.sun_path[0] != '\0'); #else assert(ctx->log_context.socket_info != NULL); #endif ret = hdb_create(ctx->context, &ctx->db, dbname); if (ret == 0) ret = hdb_set_master_keyfile(ctx->context, ctx->db, stash_file); if (ret) { kadm5_s_destroy(ctx); return ret; } ctx->log_context.log_fd = -1; #ifndef NO_UNIX_SOCKETS ctx->log_context.socket_fd = socket(AF_UNIX, SOCK_DGRAM, 0); #else ctx->log_context.socket_fd = socket(ctx->log_context.socket_info->ai_family, ctx->log_context.socket_info->ai_socktype, ctx->log_context.socket_info->ai_protocol); #endif if (ctx->log_context.socket_fd != rk_INVALID_SOCKET) socket_set_nonblocking(ctx->log_context.socket_fd, 1); ret = krb5_parse_name(ctx->context, client_name, &ctx->caller); if (ret == 0) ret = _kadm5_acl_init(ctx); if (ret) kadm5_s_destroy(ctx); else *server_handle = ctx; return ret; }