1b528cefcSMark Murray /* 25e9cd1aeSAssar Westerlund * Copyright (c) 1997 - 2001 Kungliga Tekniska H�gskolan 3b528cefcSMark Murray * (Royal Institute of Technology, Stockholm, Sweden). 4b528cefcSMark Murray * All rights reserved. 5b528cefcSMark Murray * 6b528cefcSMark Murray * Redistribution and use in source and binary forms, with or without 7b528cefcSMark Murray * modification, are permitted provided that the following conditions 8b528cefcSMark Murray * are met: 9b528cefcSMark Murray * 10b528cefcSMark Murray * 1. Redistributions of source code must retain the above copyright 11b528cefcSMark Murray * notice, this list of conditions and the following disclaimer. 12b528cefcSMark Murray * 13b528cefcSMark Murray * 2. Redistributions in binary form must reproduce the above copyright 14b528cefcSMark Murray * notice, this list of conditions and the following disclaimer in the 15b528cefcSMark Murray * documentation and/or other materials provided with the distribution. 16b528cefcSMark Murray * 17b528cefcSMark Murray * 3. Neither the name of the Institute nor the names of its contributors 18b528cefcSMark Murray * may be used to endorse or promote products derived from this software 19b528cefcSMark Murray * without specific prior written permission. 20b528cefcSMark Murray * 21b528cefcSMark Murray * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22b528cefcSMark Murray * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23b528cefcSMark Murray * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24b528cefcSMark Murray * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25b528cefcSMark Murray * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26b528cefcSMark Murray * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27b528cefcSMark Murray * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28b528cefcSMark Murray * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29b528cefcSMark Murray * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30b528cefcSMark Murray * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31b528cefcSMark Murray * SUCH DAMAGE. 32b528cefcSMark Murray */ 33b528cefcSMark Murray 34b528cefcSMark Murray #include "kadmin_locl.h" 35b528cefcSMark Murray #include <parse_units.h> 36b528cefcSMark Murray 375e9cd1aeSAssar Westerlund RCSID("$Id: util.c,v 1.30 2001/01/11 23:07:29 assar Exp $"); 38b528cefcSMark Murray 39b528cefcSMark Murray /* 40b528cefcSMark Murray * util.c - functions for parsing, unparsing, and editing different 41b528cefcSMark Murray * types of data used in kadmin. 42b528cefcSMark Murray */ 43b528cefcSMark Murray 44b528cefcSMark Murray /* 45b528cefcSMark Murray * attributes 46b528cefcSMark Murray */ 47b528cefcSMark Murray 48b528cefcSMark Murray struct units kdb_attrs[] = { 49b528cefcSMark Murray { "new-princ", KRB5_KDB_NEW_PRINC }, 50b528cefcSMark Murray { "support-desmd5", KRB5_KDB_SUPPORT_DESMD5 }, 51b528cefcSMark Murray { "pwchange-service", KRB5_KDB_PWCHANGE_SERVICE }, 52b528cefcSMark Murray { "disallow-svr", KRB5_KDB_DISALLOW_SVR }, 53b528cefcSMark Murray { "requires-pw-change", KRB5_KDB_REQUIRES_PWCHANGE }, 54b528cefcSMark Murray { "requires-hw-auth", KRB5_KDB_REQUIRES_HW_AUTH }, 55b528cefcSMark Murray { "requires-pre-auth", KRB5_KDB_REQUIRES_PRE_AUTH }, 56b528cefcSMark Murray { "disallow-all-tix", KRB5_KDB_DISALLOW_ALL_TIX }, 57b528cefcSMark Murray { "disallow-dup-skey", KRB5_KDB_DISALLOW_DUP_SKEY }, 58b528cefcSMark Murray { "disallow-proxiable", KRB5_KDB_DISALLOW_PROXIABLE }, 59b528cefcSMark Murray { "disallow-renewable", KRB5_KDB_DISALLOW_RENEWABLE }, 60b528cefcSMark Murray { "disallow-tgt-based", KRB5_KDB_DISALLOW_TGT_BASED }, 61b528cefcSMark Murray { "disallow-forwardable", KRB5_KDB_DISALLOW_FORWARDABLE }, 62b528cefcSMark Murray { "disallow-postdated", KRB5_KDB_DISALLOW_POSTDATED }, 63b528cefcSMark Murray { NULL } 64b528cefcSMark Murray }; 65b528cefcSMark Murray 66b528cefcSMark Murray /* 67b528cefcSMark Murray * convert the attributes in `attributes' into a printable string 68b528cefcSMark Murray * in `str, len' 69b528cefcSMark Murray */ 70b528cefcSMark Murray 71b528cefcSMark Murray void 72b528cefcSMark Murray attributes2str(krb5_flags attributes, char *str, size_t len) 73b528cefcSMark Murray { 74b528cefcSMark Murray unparse_flags (attributes, kdb_attrs, str, len); 75b528cefcSMark Murray } 76b528cefcSMark Murray 77b528cefcSMark Murray /* 78b528cefcSMark Murray * convert the string in `str' into attributes in `flags' 79b528cefcSMark Murray * return 0 if parsed ok, else -1. 80b528cefcSMark Murray */ 81b528cefcSMark Murray 82b528cefcSMark Murray int 83b528cefcSMark Murray str2attributes(const char *str, krb5_flags *flags) 84b528cefcSMark Murray { 85b528cefcSMark Murray int res; 86b528cefcSMark Murray 87b528cefcSMark Murray res = parse_flags (str, kdb_attrs, *flags); 88b528cefcSMark Murray if (res < 0) 89b528cefcSMark Murray return res; 90b528cefcSMark Murray else { 91b528cefcSMark Murray *flags = res; 92b528cefcSMark Murray return 0; 93b528cefcSMark Murray } 94b528cefcSMark Murray } 95b528cefcSMark Murray 96b528cefcSMark Murray /* 97b528cefcSMark Murray * try to parse the string `resp' into attributes in `attr', also 98b528cefcSMark Murray * setting the `bit' in `mask' if attributes are given and valid. 99b528cefcSMark Murray */ 100b528cefcSMark Murray 101b528cefcSMark Murray int 102b528cefcSMark Murray parse_attributes (const char *resp, krb5_flags *attr, int *mask, int bit) 103b528cefcSMark Murray { 104b528cefcSMark Murray krb5_flags tmp = *attr; 105b528cefcSMark Murray 1065e9cd1aeSAssar Westerlund if (str2attributes(resp, &tmp) == 0) { 107b528cefcSMark Murray *attr = tmp; 108b528cefcSMark Murray if (mask) 109b528cefcSMark Murray *mask |= bit; 110b528cefcSMark Murray return 0; 111b528cefcSMark Murray } else if(*resp == '?') { 112b528cefcSMark Murray print_flags_table (kdb_attrs, stderr); 113b528cefcSMark Murray } else { 114b528cefcSMark Murray fprintf (stderr, "Unable to parse '%s'\n", resp); 115b528cefcSMark Murray } 116b528cefcSMark Murray return -1; 117b528cefcSMark Murray } 118b528cefcSMark Murray 119b528cefcSMark Murray /* 120b528cefcSMark Murray * allow the user to edit the attributes in `attr', prompting with `prompt' 121b528cefcSMark Murray */ 122b528cefcSMark Murray 123b528cefcSMark Murray int 124b528cefcSMark Murray edit_attributes (const char *prompt, krb5_flags *attr, int *mask, int bit) 125b528cefcSMark Murray { 126b528cefcSMark Murray char buf[1024], resp[1024]; 127b528cefcSMark Murray 128b528cefcSMark Murray if (mask && (*mask & bit)) 129b528cefcSMark Murray return 0; 130b528cefcSMark Murray 131b528cefcSMark Murray attributes2str(*attr, buf, sizeof(buf)); 132b528cefcSMark Murray for (;;) { 133b528cefcSMark Murray get_response("Attributes", buf, resp, sizeof(resp)); 1345e9cd1aeSAssar Westerlund if (resp[0] == '\0') 1355e9cd1aeSAssar Westerlund break; 136b528cefcSMark Murray if (parse_attributes (resp, attr, mask, bit) == 0) 137b528cefcSMark Murray break; 138b528cefcSMark Murray } 139b528cefcSMark Murray return 0; 140b528cefcSMark Murray } 141b528cefcSMark Murray 142b528cefcSMark Murray /* 143b528cefcSMark Murray * time_t 144b528cefcSMark Murray * the special value 0 means ``never'' 145b528cefcSMark Murray */ 146b528cefcSMark Murray 147b528cefcSMark Murray /* 148b528cefcSMark Murray * Convert the time `t' to a string representation in `str' (of max 149b528cefcSMark Murray * size `len'). If include_time also include time, otherwise just 150b528cefcSMark Murray * date. 151b528cefcSMark Murray */ 152b528cefcSMark Murray 153b528cefcSMark Murray void 154b528cefcSMark Murray time_t2str(time_t t, char *str, size_t len, int include_time) 155b528cefcSMark Murray { 156b528cefcSMark Murray if(t) { 157b528cefcSMark Murray if(include_time) 158b528cefcSMark Murray strftime(str, len, "%Y-%m-%d %H:%M:%S UTC", gmtime(&t)); 159b528cefcSMark Murray else 160b528cefcSMark Murray strftime(str, len, "%Y-%m-%d", gmtime(&t)); 161b528cefcSMark Murray } else 162b528cefcSMark Murray snprintf(str, len, "never"); 163b528cefcSMark Murray } 164b528cefcSMark Murray 165b528cefcSMark Murray /* 166b528cefcSMark Murray * Convert the time representation in `str' to a time in `time'. 167b528cefcSMark Murray * Return 0 if succesful, else -1. 168b528cefcSMark Murray */ 169b528cefcSMark Murray 170b528cefcSMark Murray int 1715e9cd1aeSAssar Westerlund str2time_t (const char *str, time_t *t) 172b528cefcSMark Murray { 173b528cefcSMark Murray const char *p; 1745e9cd1aeSAssar Westerlund struct tm tm, tm2; 175b528cefcSMark Murray 176b528cefcSMark Murray memset (&tm, 0, sizeof (tm)); 177b528cefcSMark Murray 178b528cefcSMark Murray if(strcasecmp(str, "never") == 0) { 1795e9cd1aeSAssar Westerlund *t = 0; 1805e9cd1aeSAssar Westerlund return 0; 1815e9cd1aeSAssar Westerlund } 1825e9cd1aeSAssar Westerlund 1835e9cd1aeSAssar Westerlund if(strcasecmp(str, "now") == 0) { 1845e9cd1aeSAssar Westerlund *t = time(NULL); 185b528cefcSMark Murray return 0; 186b528cefcSMark Murray } 187b528cefcSMark Murray 188b528cefcSMark Murray p = strptime (str, "%Y-%m-%d", &tm); 189b528cefcSMark Murray 190b528cefcSMark Murray if (p == NULL) 191b528cefcSMark Murray return -1; 192b528cefcSMark Murray 193b528cefcSMark Murray /* Do it on the end of the day */ 1945e9cd1aeSAssar Westerlund tm2.tm_hour = 23; 1955e9cd1aeSAssar Westerlund tm2.tm_min = 59; 1965e9cd1aeSAssar Westerlund tm2.tm_sec = 59; 197b528cefcSMark Murray 1985e9cd1aeSAssar Westerlund if(strptime (p, "%H:%M:%S", &tm2) != NULL) { 1995e9cd1aeSAssar Westerlund tm.tm_hour = tm2.tm_hour; 2005e9cd1aeSAssar Westerlund tm.tm_min = tm2.tm_min; 2015e9cd1aeSAssar Westerlund tm.tm_sec = tm2.tm_sec; 2025e9cd1aeSAssar Westerlund } 203b528cefcSMark Murray 2045e9cd1aeSAssar Westerlund *t = tm2time (tm, 0); 205b528cefcSMark Murray return 0; 206b528cefcSMark Murray } 207b528cefcSMark Murray 208b528cefcSMark Murray /* 209b528cefcSMark Murray * try to parse the time in `resp' storing it in `value' 210b528cefcSMark Murray */ 211b528cefcSMark Murray 212b528cefcSMark Murray int 213b528cefcSMark Murray parse_timet (const char *resp, krb5_timestamp *value, int *mask, int bit) 214b528cefcSMark Murray { 215b528cefcSMark Murray time_t tmp; 216b528cefcSMark Murray 217b528cefcSMark Murray if (str2time_t(resp, &tmp) == 0) { 218b528cefcSMark Murray *value = tmp; 219b528cefcSMark Murray if(mask) 220b528cefcSMark Murray *mask |= bit; 221b528cefcSMark Murray return 0; 222b528cefcSMark Murray } else if(*resp == '?') { 223b528cefcSMark Murray printf ("Print date on format YYYY-mm-dd [hh:mm:ss]\n"); 224b528cefcSMark Murray } else { 225b528cefcSMark Murray fprintf (stderr, "Unable to parse time '%s'\n", resp); 226b528cefcSMark Murray } 227b528cefcSMark Murray return -1; 228b528cefcSMark Murray } 229b528cefcSMark Murray 230b528cefcSMark Murray /* 231b528cefcSMark Murray * allow the user to edit the time in `value' 232b528cefcSMark Murray */ 233b528cefcSMark Murray 234b528cefcSMark Murray int 235b528cefcSMark Murray edit_timet (const char *prompt, krb5_timestamp *value, int *mask, int bit) 236b528cefcSMark Murray { 237b528cefcSMark Murray char buf[1024], resp[1024]; 238b528cefcSMark Murray 239b528cefcSMark Murray if (mask && (*mask & bit)) 240b528cefcSMark Murray return 0; 241b528cefcSMark Murray 242b528cefcSMark Murray time_t2str (*value, buf, sizeof (buf), 0); 243b528cefcSMark Murray 244b528cefcSMark Murray for (;;) { 245b528cefcSMark Murray get_response(prompt, buf, resp, sizeof(resp)); 246b528cefcSMark Murray if (parse_timet (resp, value, mask, bit) == 0) 247b528cefcSMark Murray break; 248b528cefcSMark Murray } 249b528cefcSMark Murray return 0; 250b528cefcSMark Murray } 251b528cefcSMark Murray 252b528cefcSMark Murray /* 253b528cefcSMark Murray * deltat 254b528cefcSMark Murray * the special value 0 means ``unlimited'' 255b528cefcSMark Murray */ 256b528cefcSMark Murray 257b528cefcSMark Murray /* 258b528cefcSMark Murray * convert the delta_t value in `t' into a printable form in `str, len' 259b528cefcSMark Murray */ 260b528cefcSMark Murray 261b528cefcSMark Murray void 262b528cefcSMark Murray deltat2str(unsigned t, char *str, size_t len) 263b528cefcSMark Murray { 2645e9cd1aeSAssar Westerlund if(t == 0 || t == INT_MAX) 265b528cefcSMark Murray snprintf(str, len, "unlimited"); 2665e9cd1aeSAssar Westerlund else 2675e9cd1aeSAssar Westerlund unparse_time(t, str, len); 268b528cefcSMark Murray } 269b528cefcSMark Murray 270b528cefcSMark Murray /* 271b528cefcSMark Murray * parse the delta value in `str', storing result in `*delta' 272b528cefcSMark Murray * return 0 if ok, else -1 273b528cefcSMark Murray */ 274b528cefcSMark Murray 275b528cefcSMark Murray int 276b528cefcSMark Murray str2deltat(const char *str, krb5_deltat *delta) 277b528cefcSMark Murray { 278b528cefcSMark Murray int res; 279b528cefcSMark Murray 280b528cefcSMark Murray if(strcasecmp(str, "unlimited") == 0) { 281b528cefcSMark Murray *delta = 0; 282b528cefcSMark Murray return 0; 283b528cefcSMark Murray } 284b528cefcSMark Murray res = parse_time(str, "day"); 285b528cefcSMark Murray if (res < 0) 286b528cefcSMark Murray return res; 287b528cefcSMark Murray else { 288b528cefcSMark Murray *delta = res; 289b528cefcSMark Murray return 0; 290b528cefcSMark Murray } 291b528cefcSMark Murray } 292b528cefcSMark Murray 293b528cefcSMark Murray /* 294b528cefcSMark Murray * try to parse the string in `resp' into a deltad in `value' 295b528cefcSMark Murray * `mask' will get the bit `bit' set if a value was given. 296b528cefcSMark Murray */ 297b528cefcSMark Murray 298b528cefcSMark Murray int 299b528cefcSMark Murray parse_deltat (const char *resp, krb5_deltat *value, int *mask, int bit) 300b528cefcSMark Murray { 301b528cefcSMark Murray krb5_deltat tmp; 302b528cefcSMark Murray 303b528cefcSMark Murray if (str2deltat(resp, &tmp) == 0) { 304b528cefcSMark Murray *value = tmp; 305b528cefcSMark Murray if (mask) 306b528cefcSMark Murray *mask |= bit; 307b528cefcSMark Murray return 0; 308b528cefcSMark Murray } else if(*resp == '?') { 309b528cefcSMark Murray print_time_table (stderr); 310b528cefcSMark Murray } else { 311b528cefcSMark Murray fprintf (stderr, "Unable to parse time '%s'\n", resp); 312b528cefcSMark Murray } 313b528cefcSMark Murray return -1; 314b528cefcSMark Murray } 315b528cefcSMark Murray 316b528cefcSMark Murray /* 317b528cefcSMark Murray * allow the user to edit the deltat in `value' 318b528cefcSMark Murray */ 319b528cefcSMark Murray 320b528cefcSMark Murray int 321b528cefcSMark Murray edit_deltat (const char *prompt, krb5_deltat *value, int *mask, int bit) 322b528cefcSMark Murray { 323b528cefcSMark Murray char buf[1024], resp[1024]; 324b528cefcSMark Murray 325b528cefcSMark Murray if (mask && (*mask & bit)) 326b528cefcSMark Murray return 0; 327b528cefcSMark Murray 328b528cefcSMark Murray deltat2str(*value, buf, sizeof(buf)); 329b528cefcSMark Murray for (;;) { 330b528cefcSMark Murray get_response(prompt, buf, resp, sizeof(resp)); 331b528cefcSMark Murray if (parse_deltat (resp, value, mask, bit) == 0) 332b528cefcSMark Murray break; 333b528cefcSMark Murray } 334b528cefcSMark Murray return 0; 335b528cefcSMark Murray } 336b528cefcSMark Murray 337b528cefcSMark Murray /* 338b528cefcSMark Murray * allow the user to edit `ent' 339b528cefcSMark Murray */ 340b528cefcSMark Murray 341b528cefcSMark Murray int 342b528cefcSMark Murray edit_entry(kadm5_principal_ent_t ent, int *mask, 343b528cefcSMark Murray kadm5_principal_ent_t default_ent, int default_mask) 344b528cefcSMark Murray { 3455e9cd1aeSAssar Westerlund if (default_ent 3465e9cd1aeSAssar Westerlund && (default_mask & KADM5_MAX_LIFE) 3475e9cd1aeSAssar Westerlund && !(*mask & KADM5_MAX_LIFE)) 348b528cefcSMark Murray ent->max_life = default_ent->max_life; 349b528cefcSMark Murray edit_deltat ("Max ticket life", &ent->max_life, mask, 350b528cefcSMark Murray KADM5_MAX_LIFE); 351b528cefcSMark Murray 3525e9cd1aeSAssar Westerlund if (default_ent 3535e9cd1aeSAssar Westerlund && (default_mask & KADM5_MAX_RLIFE) 3545e9cd1aeSAssar Westerlund && !(*mask & KADM5_MAX_RLIFE)) 355b528cefcSMark Murray ent->max_renewable_life = default_ent->max_renewable_life; 356b528cefcSMark Murray edit_deltat ("Max renewable life", &ent->max_renewable_life, mask, 357b528cefcSMark Murray KADM5_MAX_RLIFE); 358b528cefcSMark Murray 3595e9cd1aeSAssar Westerlund if (default_ent 3605e9cd1aeSAssar Westerlund && (default_mask & KADM5_PRINC_EXPIRE_TIME) 3615e9cd1aeSAssar Westerlund && !(*mask & KADM5_PRINC_EXPIRE_TIME)) 362b528cefcSMark Murray ent->princ_expire_time = default_ent->princ_expire_time; 363b528cefcSMark Murray edit_timet ("Principal expiration time", &ent->princ_expire_time, mask, 364b528cefcSMark Murray KADM5_PRINC_EXPIRE_TIME); 365b528cefcSMark Murray 3665e9cd1aeSAssar Westerlund if (default_ent 3675e9cd1aeSAssar Westerlund && (default_mask & KADM5_PW_EXPIRATION) 3685e9cd1aeSAssar Westerlund && !(*mask & KADM5_PW_EXPIRATION)) 369b528cefcSMark Murray ent->pw_expiration = default_ent->pw_expiration; 370b528cefcSMark Murray edit_timet ("Password expiration time", &ent->pw_expiration, mask, 371b528cefcSMark Murray KADM5_PW_EXPIRATION); 372b528cefcSMark Murray 3735e9cd1aeSAssar Westerlund if (default_ent 3745e9cd1aeSAssar Westerlund && (default_mask & KADM5_ATTRIBUTES) 3755e9cd1aeSAssar Westerlund && !(*mask & KADM5_ATTRIBUTES)) 376b528cefcSMark Murray ent->attributes = default_ent->attributes & ~KRB5_KDB_DISALLOW_ALL_TIX; 377b528cefcSMark Murray edit_attributes ("Attributes", &ent->attributes, mask, 378b528cefcSMark Murray KADM5_ATTRIBUTES); 379b528cefcSMark Murray return 0; 380b528cefcSMark Murray } 381b528cefcSMark Murray 382b528cefcSMark Murray /* 383b528cefcSMark Murray * Parse the arguments, set the fields in `ent' and the `mask' for the 384b528cefcSMark Murray * entries having been set. 385b528cefcSMark Murray * Return 1 on failure and 0 on success. 386b528cefcSMark Murray */ 387b528cefcSMark Murray 388b528cefcSMark Murray int 389b528cefcSMark Murray set_entry(krb5_context context, 390b528cefcSMark Murray kadm5_principal_ent_t ent, 391b528cefcSMark Murray int *mask, 392b528cefcSMark Murray const char *max_ticket_life, 393b528cefcSMark Murray const char *max_renewable_life, 394b528cefcSMark Murray const char *expiration, 395b528cefcSMark Murray const char *pw_expiration, 396b528cefcSMark Murray const char *attributes) 397b528cefcSMark Murray { 398b528cefcSMark Murray if (max_ticket_life != NULL) { 399b528cefcSMark Murray if (parse_deltat (max_ticket_life, &ent->max_life, 400b528cefcSMark Murray mask, KADM5_MAX_LIFE)) { 401b528cefcSMark Murray krb5_warnx (context, "unable to parse `%s'", max_ticket_life); 402b528cefcSMark Murray return 1; 403b528cefcSMark Murray } 404b528cefcSMark Murray } 405b528cefcSMark Murray if (max_renewable_life != NULL) { 406b528cefcSMark Murray if (parse_deltat (max_renewable_life, &ent->max_renewable_life, 407b528cefcSMark Murray mask, KADM5_MAX_RLIFE)) { 408b528cefcSMark Murray krb5_warnx (context, "unable to parse `%s'", max_renewable_life); 409b528cefcSMark Murray return 1; 410b528cefcSMark Murray } 411b528cefcSMark Murray } 412b528cefcSMark Murray 413b528cefcSMark Murray if (expiration) { 414b528cefcSMark Murray if (parse_timet (expiration, &ent->princ_expire_time, 415b528cefcSMark Murray mask, KADM5_PRINC_EXPIRE_TIME)) { 416b528cefcSMark Murray krb5_warnx (context, "unable to parse `%s'", expiration); 417b528cefcSMark Murray return 1; 418b528cefcSMark Murray } 419b528cefcSMark Murray } 420b528cefcSMark Murray if (pw_expiration) { 421b528cefcSMark Murray if (parse_timet (pw_expiration, &ent->pw_expiration, 422b528cefcSMark Murray mask, KADM5_PW_EXPIRATION)) { 423b528cefcSMark Murray krb5_warnx (context, "unable to parse `%s'", pw_expiration); 424b528cefcSMark Murray return 1; 425b528cefcSMark Murray } 426b528cefcSMark Murray } 427b528cefcSMark Murray if (attributes != NULL) { 428b528cefcSMark Murray if (parse_attributes (attributes, &ent->attributes, 429b528cefcSMark Murray mask, KADM5_ATTRIBUTES)) { 430b528cefcSMark Murray krb5_warnx (context, "unable to parse `%s'", attributes); 431b528cefcSMark Murray return 1; 432b528cefcSMark Murray } 433b528cefcSMark Murray } 434b528cefcSMark Murray return 0; 435b528cefcSMark Murray } 436b528cefcSMark Murray 437b528cefcSMark Murray /* 438b528cefcSMark Murray * Does `string' contain any globing characters? 439b528cefcSMark Murray */ 440b528cefcSMark Murray 441b528cefcSMark Murray static int 442b528cefcSMark Murray is_expression(const char *string) 443b528cefcSMark Murray { 444b528cefcSMark Murray const char *p; 445b528cefcSMark Murray int quote = 0; 446b528cefcSMark Murray 447b528cefcSMark Murray for(p = string; *p; p++) { 448b528cefcSMark Murray if(quote) { 449b528cefcSMark Murray quote = 0; 450b528cefcSMark Murray continue; 451b528cefcSMark Murray } 452b528cefcSMark Murray if(*p == '\\') 453b528cefcSMark Murray quote++; 454b528cefcSMark Murray else if(strchr("[]*?", *p) != NULL) 455b528cefcSMark Murray return 1; 456b528cefcSMark Murray } 457b528cefcSMark Murray return 0; 458b528cefcSMark Murray } 459b528cefcSMark Murray 460b528cefcSMark Murray /* loop over all principals matching exp */ 461b528cefcSMark Murray int 462b528cefcSMark Murray foreach_principal(const char *exp, 463b528cefcSMark Murray int (*func)(krb5_principal, void*), 464b528cefcSMark Murray void *data) 465b528cefcSMark Murray { 466b528cefcSMark Murray char **princs; 467b528cefcSMark Murray int num_princs; 468b528cefcSMark Murray int i; 469b528cefcSMark Murray krb5_error_code ret; 470b528cefcSMark Murray krb5_principal princ_ent; 471b528cefcSMark Murray int is_expr; 472b528cefcSMark Murray 473b528cefcSMark Murray /* if this isn't an expression, there is no point in wading 474b528cefcSMark Murray through the whole database looking for matches */ 475b528cefcSMark Murray is_expr = is_expression(exp); 476b528cefcSMark Murray if(is_expr) 477b528cefcSMark Murray ret = kadm5_get_principals(kadm_handle, exp, &princs, &num_princs); 478b528cefcSMark Murray if(!is_expr || ret == KADM5_AUTH_LIST) { 479b528cefcSMark Murray /* we might be able to perform the requested opreration even 480b528cefcSMark Murray if we're not allowed to list principals */ 481b528cefcSMark Murray num_princs = 1; 482b528cefcSMark Murray princs = malloc(sizeof(*princs)); 483b528cefcSMark Murray if(princs == NULL) 484b528cefcSMark Murray return ENOMEM; 485b528cefcSMark Murray princs[0] = strdup(exp); 486b528cefcSMark Murray if(princs[0] == NULL){ 487b528cefcSMark Murray free(princs); 488b528cefcSMark Murray return ENOMEM; 489b528cefcSMark Murray } 490b528cefcSMark Murray } else if(ret) { 491b528cefcSMark Murray krb5_warn(context, ret, "kadm5_get_principals"); 492b528cefcSMark Murray return ret; 493b528cefcSMark Murray } 494b528cefcSMark Murray for(i = 0; i < num_princs; i++) { 495b528cefcSMark Murray ret = krb5_parse_name(context, princs[i], &princ_ent); 496b528cefcSMark Murray if(ret){ 497b528cefcSMark Murray krb5_warn(context, ret, "krb5_parse_name(%s)", princs[i]); 498b528cefcSMark Murray continue; 499b528cefcSMark Murray } 500b528cefcSMark Murray ret = (*func)(princ_ent, data); 501b528cefcSMark Murray if(ret) { 502b528cefcSMark Murray char *tmp; 503b528cefcSMark Murray krb5_error_code ret2; 504b528cefcSMark Murray 505b528cefcSMark Murray ret2 = krb5_unparse_name(context, princ_ent, &tmp); 506b528cefcSMark Murray if(ret2) { 507b528cefcSMark Murray krb5_warn(context, ret2, "krb5_unparse_name"); 508b528cefcSMark Murray krb5_warn(context, ret, "<unknown principal>"); 509b528cefcSMark Murray } else { 510b528cefcSMark Murray krb5_warn(context, ret, "%s", tmp); 511b528cefcSMark Murray free(tmp); 512b528cefcSMark Murray } 513b528cefcSMark Murray } 514b528cefcSMark Murray krb5_free_principal(context, princ_ent); 515b528cefcSMark Murray } 516b528cefcSMark Murray kadm5_free_name_list(kadm_handle, princs, &num_princs); 517b528cefcSMark Murray return 0; 518b528cefcSMark Murray } 519b528cefcSMark Murray 520b528cefcSMark Murray /* 521b528cefcSMark Murray * prompt with `prompt' and default value `def', and store the reply 522b528cefcSMark Murray * in `buf, len' 523b528cefcSMark Murray */ 524b528cefcSMark Murray 525b528cefcSMark Murray void 526b528cefcSMark Murray get_response(const char *prompt, const char *def, char *buf, size_t len) 527b528cefcSMark Murray { 528b528cefcSMark Murray char *p; 529b528cefcSMark Murray 530b528cefcSMark Murray printf("%s [%s]:", prompt, def); 531b528cefcSMark Murray if(fgets(buf, len, stdin) == NULL) 532b528cefcSMark Murray *buf = '\0'; 533b528cefcSMark Murray p = strchr(buf, '\n'); 534b528cefcSMark Murray if(p) 535b528cefcSMark Murray *p = '\0'; 536b528cefcSMark Murray if(strcmp(buf, "") == 0) 537b528cefcSMark Murray strncpy(buf, def, len); 538b528cefcSMark Murray buf[len-1] = 0; 539b528cefcSMark Murray } 5405e9cd1aeSAssar Westerlund 5415e9cd1aeSAssar Westerlund /* 5425e9cd1aeSAssar Westerlund * return [0, 16) or -1 5435e9cd1aeSAssar Westerlund */ 5445e9cd1aeSAssar Westerlund 5455e9cd1aeSAssar Westerlund static int 5465e9cd1aeSAssar Westerlund hex2n (char c) 5475e9cd1aeSAssar Westerlund { 5485e9cd1aeSAssar Westerlund static char hexdigits[] = "0123456789abcdef"; 5495e9cd1aeSAssar Westerlund const char *p; 5505e9cd1aeSAssar Westerlund 5515e9cd1aeSAssar Westerlund p = strchr (hexdigits, tolower((int)c)); 5525e9cd1aeSAssar Westerlund if (p == NULL) 5535e9cd1aeSAssar Westerlund return -1; 5545e9cd1aeSAssar Westerlund else 5555e9cd1aeSAssar Westerlund return p - hexdigits; 5565e9cd1aeSAssar Westerlund } 5575e9cd1aeSAssar Westerlund 5585e9cd1aeSAssar Westerlund /* 5595e9cd1aeSAssar Westerlund * convert a key in a readable format into a keyblock. 5605e9cd1aeSAssar Westerlund * return 0 iff succesful, otherwise `err' should point to an error message 5615e9cd1aeSAssar Westerlund */ 5625e9cd1aeSAssar Westerlund 5635e9cd1aeSAssar Westerlund int 5645e9cd1aeSAssar Westerlund parse_des_key (const char *key_string, krb5_key_data *key_data, 5655e9cd1aeSAssar Westerlund const char **err) 5665e9cd1aeSAssar Westerlund { 5675e9cd1aeSAssar Westerlund const char *p = key_string; 5685e9cd1aeSAssar Westerlund unsigned char bits[8]; 5695e9cd1aeSAssar Westerlund int i; 5705e9cd1aeSAssar Westerlund 5715e9cd1aeSAssar Westerlund if (strlen (key_string) != 16) { 5725e9cd1aeSAssar Westerlund *err = "bad length, should be 16 for DES key"; 5735e9cd1aeSAssar Westerlund return 1; 5745e9cd1aeSAssar Westerlund } 5755e9cd1aeSAssar Westerlund for (i = 0; i < 8; ++i) { 5765e9cd1aeSAssar Westerlund int d1, d2; 5775e9cd1aeSAssar Westerlund 5785e9cd1aeSAssar Westerlund d1 = hex2n(p[2 * i]); 5795e9cd1aeSAssar Westerlund d2 = hex2n(p[2 * i + 1]); 5805e9cd1aeSAssar Westerlund if (d1 < 0 || d2 < 0) { 5815e9cd1aeSAssar Westerlund *err = "non-hex character"; 5825e9cd1aeSAssar Westerlund return 1; 5835e9cd1aeSAssar Westerlund } 5845e9cd1aeSAssar Westerlund bits[i] = (d1 << 4) | d2; 5855e9cd1aeSAssar Westerlund } 5865e9cd1aeSAssar Westerlund for (i = 0; i < 3; ++i) { 5875e9cd1aeSAssar Westerlund key_data[i].key_data_ver = 2; 5885e9cd1aeSAssar Westerlund key_data[i].key_data_kvno = 0; 5895e9cd1aeSAssar Westerlund /* key */ 5905e9cd1aeSAssar Westerlund key_data[i].key_data_type[0] = ETYPE_DES_CBC_CRC; 5915e9cd1aeSAssar Westerlund key_data[i].key_data_length[0] = 8; 5925e9cd1aeSAssar Westerlund key_data[i].key_data_contents[0] = malloc(8); 5935e9cd1aeSAssar Westerlund memcpy (key_data[i].key_data_contents[0], bits, 8); 5945e9cd1aeSAssar Westerlund /* salt */ 5955e9cd1aeSAssar Westerlund key_data[i].key_data_type[1] = KRB5_PW_SALT; 5965e9cd1aeSAssar Westerlund key_data[i].key_data_length[1] = 0; 5975e9cd1aeSAssar Westerlund key_data[i].key_data_contents[1] = NULL; 5985e9cd1aeSAssar Westerlund } 5995e9cd1aeSAssar Westerlund key_data[0].key_data_type[0] = ETYPE_DES_CBC_MD5; 6005e9cd1aeSAssar Westerlund key_data[1].key_data_type[0] = ETYPE_DES_CBC_MD4; 6015e9cd1aeSAssar Westerlund return 0; 6025e9cd1aeSAssar Westerlund } 603