2 Copyright (C) 1989 by the Massachusetts Institute of Technology
4 Export of this software from the United States of America is assumed
5 to require a specific license from the United States Government.
6 It is the responsibility of any person or organization contemplating
7 export to obtain such a license before exporting.
9 WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
10 distribute this software and its documentation for any purpose and
11 without fee is hereby granted, provided that the above copyright
12 notice appear in all copies and that both that copyright notice and
13 this permission notice appear in supporting documentation, and that
14 the name of M.I.T. not be used in advertising or publicity pertaining
15 to distribution of the software without specific, written prior
16 permission. M.I.T. makes no representations about the suitability of
17 this software for any purpose. It is provided "as is" without express
23 * Kerberos administration server-side database manipulation routines
28 * the actual database manipulation code
31 #include "kadm_locl.h"
33 RCSID("$Id: kadm_funcs.c,v 1.18 1999/09/16 20:41:40 assar Exp $");
36 check_access(char *pname, char *pinst, char *prealm, enum acl_types acltype)
38 char checkname[MAX_K_NAME_SZ];
39 char filename[MaxPathLen];
41 snprintf(checkname, sizeof(checkname), "%s.%s@%s", pname, pinst, prealm);
45 snprintf(filename, sizeof(filename), "%s%s", acldir, ADD_ACL_FILE);
48 snprintf(filename, sizeof(filename), "%s%s", acldir, GET_ACL_FILE);
51 snprintf(filename, sizeof(filename), "%s%s", acldir, MOD_ACL_FILE);
54 snprintf(filename, sizeof(filename), "%s%s", acldir, DEL_ACL_FILE);
57 krb_log("WARNING in check_access: default case in switch");
60 return(acl_check(filename, checkname));
66 if (!strcmp(str, WILDCARD_STR))
72 fail(int code, char *oper, char *princ)
74 krb_log("ERROR: %s: %s (%s)", oper, princ, error_message(code));
78 #define failadd(code) { fail(code, "ADD", victim); return code; }
79 #define faildelete(code) { fail(code, "DELETE", victim); return code; }
80 #define failget(code) { fail(code, "GET", victim); return code; }
81 #define failmod(code) { fail(code, "MOD", victim); return code; }
82 #define failchange(code) { fail(code, "CHANGE", admin); return code; }
85 kadm_add_entry (char *rname, char *rinstance, char *rrealm,
86 Kadm_vals *valsin, Kadm_vals *valsout)
88 long numfound; /* check how many we get written */
89 int more; /* pointer to more grabbed records */
90 Principal data_i, data_o; /* temporary principal */
93 Principal default_princ;
95 char admin[MAX_K_NAME_SZ], victim[MAX_K_NAME_SZ];
98 krb_unparse_name_long(rname, rinstance, rrealm),
101 krb_unparse_name_long(valsin->name,
106 krb_log("ADD: %s by %s", victim, admin);
108 if (!check_access(rname, rinstance, rrealm, ADDACL)) {
109 krb_log("WARNING: ADD: %s permission denied", admin);
113 /* Need to check here for "legal" name and instance */
114 if (wildcard(valsin->name) || wildcard(valsin->instance)) {
115 failadd(KADM_ILL_WILDCARD);
118 numfound = kerb_get_principal(KERB_DEFAULT_NAME, KERB_DEFAULT_INST,
119 &default_princ, 1, &more);
120 if (numfound == -1) {
121 failadd(KADM_DB_INUSE);
122 } else if (numfound != 1) {
123 failadd(KADM_UK_RERROR);
126 kadm_vals_to_prin(valsin->fields, &data_i, valsin);
127 strlcpy(data_i.name, valsin->name, ANAME_SZ);
128 strlcpy(data_i.instance, valsin->instance, INST_SZ);
130 if (!IS_FIELD(KADM_EXPDATE,valsin->fields))
131 data_i.exp_date = default_princ.exp_date;
132 if (!IS_FIELD(KADM_ATTR,valsin->fields))
133 data_i.attributes = default_princ.attributes;
134 if (!IS_FIELD(KADM_MAXLIFE,valsin->fields))
135 data_i.max_life = default_princ.max_life;
137 memset(&default_princ, 0, sizeof(default_princ));
139 /* convert to host order */
140 data_i.key_low = ntohl(data_i.key_low);
141 data_i.key_high = ntohl(data_i.key_high);
144 copy_to_key(&data_i.key_low, &data_i.key_high, newpw);
146 /* encrypt new key in master key */
147 kdb_encrypt_key (&newpw, &newpw, &server_parm.master_key,
148 server_parm.master_key_schedule, DES_ENCRYPT);
149 copy_from_key(newpw, &data_i.key_low, &data_i.key_high);
150 memset(newpw, 0, sizeof(newpw));
153 numfound = kerb_get_principal(valsin->name, valsin->instance,
155 if (numfound == -1) {
156 failadd(KADM_DB_INUSE);
157 } else if (numfound) {
160 data_i.key_version++;
161 data_i.kdc_key_ver = server_parm.master_key_version;
162 strlcpy(data_i.mod_name, rname, sizeof(data_i.mod_name));
163 strlcpy(data_i.mod_instance, rinstance,
164 sizeof(data_i.mod_instance));
166 numfound = kerb_put_principal(&data_i, 1);
167 if (numfound == -1) {
168 failadd(KADM_DB_INUSE);
169 } else if (numfound) {
170 failadd(KADM_UK_SERROR);
172 numfound = kerb_get_principal(valsin->name, valsin->instance,
174 if ((numfound!=1) || (more!=0)) {
175 failadd(KADM_UK_RERROR);
177 memset(flags, 0, sizeof(flags));
178 SET_FIELD(KADM_NAME,flags);
179 SET_FIELD(KADM_INST,flags);
180 SET_FIELD(KADM_EXPDATE,flags);
181 SET_FIELD(KADM_ATTR,flags);
182 SET_FIELD(KADM_MAXLIFE,flags);
183 kadm_prin_to_vals(flags, valsout, &data_o);
184 krb_log("ADD: %s added", victim);
185 return KADM_DATA; /* Set all the appropriate fields */
191 kadm_delete_entry (char *rname, char *rinstance, char *rrealm,
196 char admin[MAX_K_NAME_SZ], victim[MAX_K_NAME_SZ];
199 krb_unparse_name_long(rname, rinstance, rrealm),
202 krb_unparse_name_long(valsin->name,
207 krb_log("DELETE: %s by %s", victim, admin);
209 if (!check_access(rname, rinstance, rrealm, DELACL)) {
210 krb_log("WARNING: DELETE: %s permission denied", admin);
214 /* Need to check here for "legal" name and instance */
215 if (wildcard(valsin->name) || wildcard(valsin->instance)) {
216 faildelete(KADM_ILL_WILDCARD);
219 #define EQ(V,N,I) (strcmp((V)->name, (N)) == 0 && strcmp((V)->instance, (I)) == 0)
221 if(EQ(valsin, PWSERV_NAME, KRB_MASTER) ||
222 EQ(valsin, "K", "M") ||
223 EQ(valsin, "default", "") ||
224 EQ(valsin, KRB_TICKET_GRANTING_TICKET, server_parm.krbrlm)){
225 krb_log("WARNING: DELETE: %s is immutable", victim);
226 return KADM_IMMUTABLE; /* XXX */
229 ret = kerb_delete_principal(valsin->name, valsin->instance);
231 return KADM_DB_INUSE; /* XXX */
232 krb_log("DELETE: %s removed.", victim);
238 kadm_get_entry (char *rname, char *rinstance, char *rrealm,
239 Kadm_vals *valsin, u_char *flags, Kadm_vals *valsout)
241 long numfound; /* check how many were returned */
242 int more; /* To point to more name.instances */
243 Principal data_o; /* Data object to hold Principal */
245 char admin[MAX_K_NAME_SZ], victim[MAX_K_NAME_SZ];
248 krb_unparse_name_long(rname, rinstance, rrealm),
251 krb_unparse_name_long(valsin->name,
256 krb_log("GET: %s by %s", victim, admin);
258 if (!check_access(rname, rinstance, rrealm, GETACL)) {
259 krb_log("WARNING: GET: %s permission denied", admin);
263 if (wildcard(valsin->name) || wildcard(valsin->instance)) {
264 failget(KADM_ILL_WILDCARD);
267 /* Look up the record in the database */
268 numfound = kerb_get_principal(valsin->name, valsin->instance,
270 if (numfound == -1) {
271 failget(KADM_DB_INUSE);
272 } else if (numfound) { /* We got the record, let's return it */
273 kadm_prin_to_vals(flags, valsout, &data_o);
274 krb_log("GET: %s retrieved", victim);
275 return KADM_DATA; /* Set all the appropriate fields */
277 failget(KADM_NOENTRY); /* Else whimper and moan */
282 kadm_mod_entry (char *rname, char *rinstance, char *rrealm,
283 Kadm_vals *valsin, Kadm_vals *valsin2, Kadm_vals *valsout)
287 Principal data_o, temp_key;
291 char admin[MAX_K_NAME_SZ], victim[MAX_K_NAME_SZ];
294 krb_unparse_name_long(rname, rinstance, rrealm),
297 krb_unparse_name_long(valsin->name,
302 krb_log("MOD: %s by %s", victim, admin);
304 if (wildcard(valsin->name) || wildcard(valsin->instance)) {
305 failmod(KADM_ILL_WILDCARD);
308 if (!check_access(rname, rinstance, rrealm, MODACL)) {
309 krb_log("WARNING: MOD: %s permission denied", admin);
313 numfound = kerb_get_principal(valsin->name, valsin->instance,
315 if (numfound == -1) {
316 failmod(KADM_DB_INUSE);
317 } else if (numfound) {
318 kadm_vals_to_prin(valsin2->fields, &temp_key, valsin2);
319 strlcpy(data_o.name, valsin->name, ANAME_SZ);
320 strlcpy(data_o.instance, valsin->instance, INST_SZ);
321 if (IS_FIELD(KADM_EXPDATE,valsin2->fields))
322 data_o.exp_date = temp_key.exp_date;
323 if (IS_FIELD(KADM_ATTR,valsin2->fields))
324 data_o.attributes = temp_key.attributes;
325 if (IS_FIELD(KADM_MAXLIFE,valsin2->fields))
326 data_o.max_life = temp_key.max_life;
327 if (IS_FIELD(KADM_DESKEY,valsin2->fields)) {
328 data_o.key_version++;
329 data_o.kdc_key_ver = server_parm.master_key_version;
332 /* convert to host order */
333 temp_key.key_low = ntohl(temp_key.key_low);
334 temp_key.key_high = ntohl(temp_key.key_high);
337 copy_to_key(&temp_key.key_low, &temp_key.key_high, newpw);
339 /* encrypt new key in master key */
340 kdb_encrypt_key (&newpw, &newpw, &server_parm.master_key,
341 server_parm.master_key_schedule, DES_ENCRYPT);
342 copy_from_key(newpw, &data_o.key_low, &data_o.key_high);
343 memset(newpw, 0, sizeof(newpw));
345 memset(&temp_key, 0, sizeof(temp_key));
347 strlcpy(data_o.mod_name, rname, sizeof(data_o.mod_name));
348 strlcpy(data_o.mod_instance, rinstance,
349 sizeof(data_o.mod_instance));
350 more = kerb_put_principal(&data_o, 1);
352 memset(&data_o, 0, sizeof(data_o));
355 failmod(KADM_DB_INUSE);
357 failmod(KADM_UK_SERROR);
359 numfound = kerb_get_principal(valsin->name, valsin->instance,
361 if ((more!=0)||(numfound!=1)) {
362 failmod(KADM_UK_RERROR);
364 memset(fields, 0, sizeof(fields));
365 SET_FIELD(KADM_NAME,fields);
366 SET_FIELD(KADM_INST,fields);
367 SET_FIELD(KADM_EXPDATE,fields);
368 SET_FIELD(KADM_ATTR,fields);
369 SET_FIELD(KADM_MAXLIFE,fields);
370 kadm_prin_to_vals(fields, valsout, &data_o);
371 krb_log("MOD: %s modified", victim);
372 return KADM_DATA; /* Set all the appropriate fields */
376 failmod(KADM_NOENTRY);
381 kadm_change (char *rname, char *rinstance, char *rrealm, unsigned char *newpw)
388 char admin[MAX_K_NAME_SZ];
391 krb_unparse_name_long(rname, rinstance, rrealm),
394 krb_log("CHANGE: %s", admin);
396 if (strcmp(server_parm.krbrlm, rrealm)) {
397 krb_log("ERROR: CHANGE: request from wrong realm %s", rrealm);
398 return(KADM_WRONG_REALM);
401 if (wildcard(rname) || wildcard(rinstance)) {
402 failchange(KADM_ILL_WILDCARD);
405 memcpy(local_pw, newpw, sizeof(local_pw));
407 /* encrypt new key in master key */
408 kdb_encrypt_key (&local_pw, &local_pw, &server_parm.master_key,
409 server_parm.master_key_schedule, DES_ENCRYPT);
411 numfound = kerb_get_principal(rname, rinstance,
413 if (numfound == -1) {
414 failchange(KADM_DB_INUSE);
415 } else if (numfound) {
416 copy_from_key(local_pw, &data_o.key_low, &data_o.key_high);
417 data_o.key_version++;
418 data_o.kdc_key_ver = server_parm.master_key_version;
419 strlcpy(data_o.mod_name, rname, sizeof(data_o.mod_name));
420 strlcpy(data_o.mod_instance, rinstance,
421 sizeof(data_o.mod_instance));
422 more = kerb_put_principal(&data_o, 1);
423 memset(local_pw, 0, sizeof(local_pw));
424 memset(&data_o, 0, sizeof(data_o));
426 failchange(KADM_DB_INUSE);
428 failchange(KADM_UK_SERROR);
430 krb_log("CHANGE: %s's password changed", admin);
435 failchange(KADM_NOENTRY);