This commit was manufactured by cvs2svn to create tag
[heimdal.git] / kadmin / util.c
blobedcd1de413fa2e9d06eb0bae1eb1b862a2b3c940
1 /*
2 * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
4 * All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Kungliga Tekniska
20 * Högskolan and its contributors.
22 * 4. Neither the name of the Institute nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
39 #include "kadmin_locl.h"
40 #include <parse_units.h>
42 RCSID("$Id$");
44 struct units kdb_attrs[] = {
45 { "new-princ", KRB5_KDB_NEW_PRINC },
46 { "support-desmd5", KRB5_KDB_SUPPORT_DESMD5 },
47 { "pwchange-service", KRB5_KDB_PWCHANGE_SERVICE },
48 { "disallow-svr", KRB5_KDB_DISALLOW_SVR },
49 { "requires-pw-change", KRB5_KDB_REQUIRES_PWCHANGE },
50 { "requires-hw-auth", KRB5_KDB_REQUIRES_HW_AUTH },
51 { "requires-pre-auth", KRB5_KDB_REQUIRES_PRE_AUTH },
52 { "disallow-all-tix", KRB5_KDB_DISALLOW_ALL_TIX },
53 { "disallow-dup-skey", KRB5_KDB_DISALLOW_DUP_SKEY },
54 { "disallow-proxiable", KRB5_KDB_DISALLOW_PROXIABLE },
55 { "disallow-renewable", KRB5_KDB_DISALLOW_RENEWABLE },
56 { "disallow-tgt-based", KRB5_KDB_DISALLOW_TGT_BASED },
57 { "disallow-forwardable", KRB5_KDB_DISALLOW_FORWARDABLE },
58 { "disallow-postdated", KRB5_KDB_DISALLOW_POSTDATED },
59 { NULL }
62 void
63 timeval2str(time_t t, char *str, size_t len, int include_time)
65 if(t) {
66 if(include_time)
67 strftime(str, len, "%Y-%m-%d %H:%M:%S UTC", gmtime(&t));
68 else
69 strftime(str, len, "%Y-%m-%d", gmtime(&t));
70 } else
71 snprintf(str, len, "never");
74 void
75 deltat2str(unsigned t, char *str, size_t len)
77 if(t)
78 unparse_time(t, str, len);
79 else
80 snprintf(str, len, "unlimited");
83 int
84 str2deltat(const char *str, unsigned *delta)
86 int res;
88 if(strcasecmp(str, "unlimited") == 0) {
89 *delta = 0;
90 return 0;
92 res = parse_time(str, "day");
93 if (res < 0)
94 return res;
95 else {
96 *delta = res;
97 return 0;
101 void
102 attr2str(krb5_flags attributes, char *str, size_t len)
104 unparse_flags (attributes, kdb_attrs, str, len);
108 str2attr(const char *str, krb5_flags *flags)
110 int res;
112 res = parse_flags (str, kdb_attrs, *flags);
113 if (res < 0)
114 return res;
115 else {
116 *flags = res;
117 return 0;
121 void
122 get_response(const char *prompt, const char *def, char *buf, size_t len)
124 char *p;
126 printf("%s [%s]:", prompt, def);
127 if(fgets(buf, len, stdin) == NULL)
128 *buf = '\0';
129 p = strchr(buf, '\n');
130 if(p)
131 *p = '\0';
132 if(strcmp(buf, "") == 0)
133 strncpy(buf, def, len);
134 buf[len-1] = 0;
137 int
138 get_deltat(const char *prompt, const char *def, unsigned *delta)
140 char buf[128];
141 get_response(prompt, def, buf, sizeof(buf));
142 return str2deltat(buf, delta);
145 static int
146 edit_time (const char *prompt, krb5_deltat *value, int *mask, int bit)
148 char buf[1024], resp[1024];
150 if (*mask & bit)
151 return 0;
153 deltat2str(*value, buf, sizeof(buf));
154 for (;;) {
155 unsigned tmp;
157 get_response(prompt, buf, resp, sizeof(resp));
158 if (str2deltat(resp, &tmp) == 0) {
159 *value = tmp;
160 if (tmp)
161 *mask |= bit;
162 break;
163 } else if(*resp == '?') {
164 print_time_table (stderr);
165 } else {
166 fprintf (stderr, "Unable to parse time '%s'\n", resp);
169 return 0;
172 static int
173 edit_attributes (const char *prompt, krb5_flags *attr, int *mask, int bit)
175 char buf[1024], resp[1024];
177 if (*mask & bit)
178 return 0;
180 attr2str(*attr, buf, sizeof(buf));
181 for (;;) {
182 krb5_flags tmp = *attr;
184 get_response("Attributes", buf, resp, sizeof(resp));
185 if (resp[0] == '\0')
186 break;
187 else if (str2attr(resp, &tmp) == 0) {
188 *attr = tmp;
189 *mask |= bit;
190 break;
191 } else if(*resp == '?') {
192 print_flags_table (kdb_attrs, stderr);
193 } else {
194 fprintf (stderr, "Unable to parse '%s'\n", resp);
197 return 0;
201 edit_entry(kadm5_principal_ent_t ent, int *mask)
203 edit_time ("Max ticket life", &ent->max_life, mask,
204 KADM5_MAX_LIFE);
205 edit_time ("Max renewable life", &ent->max_renewable_life, mask,
206 KADM5_MAX_RLIFE);
207 edit_attributes ("Attributes", &ent->attributes, mask,
208 KADM5_ATTRIBUTES);
209 return 0;
213 set_entry(krb5_context context,
214 kadm5_principal_ent_t ent, int *mask,
215 const char *max_ticket_life,
216 const char *max_renewable_life,
217 const char *attributes)
219 unsigned tmp;
221 if (max_ticket_life != NULL) {
222 if (str2deltat (max_ticket_life, &tmp) != 0) {
223 krb5_warnx (context, "unable to parse `%s'",
224 max_ticket_life);
225 return 1;
227 ent->max_life = tmp;
228 *mask |= KADM5_MAX_LIFE;
230 if (max_renewable_life != NULL) {
231 if (str2deltat (max_renewable_life, &tmp) != 0) {
232 krb5_warnx (context, "unable to parse `%s'",
233 max_renewable_life);
234 return 1;
236 ent->max_renewable_life = tmp;
237 *mask |= KADM5_MAX_RLIFE;
239 if (attributes != NULL) {
240 krb5_flags flags = 0;
242 if (str2attr (attributes, &flags) != 0) {
243 krb5_warnx (context, "unable to parse `%s'",
244 attributes);
245 return 1;
246 } else {
247 ent->attributes = flags;
248 *mask |= KADM5_ATTRIBUTES;
251 return 0;
254 static int
255 is_expression(const char *string)
257 const char *p;
258 int quote = 0;
259 for(p = string; *p; p++) {
260 if(quote)
261 continue;
262 if(*p == '\\')
263 quote++;
264 else if(strchr("[]*?", *p) != NULL)
265 return 1;
267 return 0;
270 /* loop over all principals matching exp */
272 foreach_principal(const char *exp,
273 int (*func)(krb5_principal, void*),
274 void *data)
276 char **princs;
277 int num_princs;
278 int i;
279 krb5_error_code ret;
280 krb5_principal princ_ent;
281 int is_expr;
283 /* if this isn't an expression, there is no point in wading
284 through the whole database looking for matches */
285 is_expr = is_expression(exp);
286 if(is_expr)
287 ret = kadm5_get_principals(kadm_handle, exp, &princs, &num_princs);
288 if(!is_expr || ret == KADM5_AUTH_LIST) {
289 /* we might be able to perform the requested opreration even
290 if we're not allowed to list principals */
291 num_princs = 1;
292 princs = malloc(sizeof(*princs));
293 if(princs == NULL)
294 return ENOMEM;
295 princs[0] = strdup(exp);
296 if(princs[0] == NULL){
297 free(princs);
298 return ENOMEM;
300 } else if(ret) {
301 krb5_warn(context, ret, "kadm5_get_principals");
302 return ret;
304 for(i = 0; i < num_princs; i++) {
305 ret = krb5_parse_name(context, princs[i], &princ_ent);
306 if(ret){
307 krb5_warn(context, ret, "krb5_parse_name(%s)", princs[i]);
308 continue;
310 ret = (*func)(princ_ent, data);
311 if(ret) {
312 char *tmp;
313 krb5_error_code ret2;
315 ret2 = krb5_unparse_name(context, princ_ent, &tmp);
316 if(ret2) {
317 krb5_warn(context, ret2, "krb5_unparse_name");
318 krb5_warn(context, ret, "<unknown principal>");
319 } else {
320 krb5_warn(context, ret, "%s", tmp);
321 free(tmp);
324 krb5_free_principal(context, princ_ent);
326 kadm5_free_name_list(kadm_handle, princs, &num_princs);
327 return 0;