155682Smarkm/* 2233294Sstas * Copyright (c) 1997 - 2006 Kungliga Tekniska H��gskolan 3233294Sstas * (Royal Institute of Technology, Stockholm, Sweden). 4233294Sstas * All rights reserved. 555682Smarkm * 6233294Sstas * Redistribution and use in source and binary forms, with or without 7233294Sstas * modification, are permitted provided that the following conditions 8233294Sstas * are met: 955682Smarkm * 10233294Sstas * 1. Redistributions of source code must retain the above copyright 11233294Sstas * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 13233294Sstas * 2. Redistributions in binary form must reproduce the above copyright 14233294Sstas * notice, this list of conditions and the following disclaimer in the 15233294Sstas * documentation and/or other materials provided with the distribution. 1655682Smarkm * 17233294Sstas * 3. Neither the name of the Institute nor the names of its contributors 18233294Sstas * may be used to endorse or promote products derived from this software 19233294Sstas * without specific prior written permission. 2055682Smarkm * 21233294Sstas * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 22233294Sstas * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23233294Sstas * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24233294Sstas * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 25233294Sstas * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26233294Sstas * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27233294Sstas * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28233294Sstas * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29233294Sstas * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30233294Sstas * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31233294Sstas * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "kadmin_locl.h" 3555682Smarkm#include <parse_units.h> 3655682Smarkm 3755682Smarkm/* 3855682Smarkm * util.c - functions for parsing, unparsing, and editing different 3955682Smarkm * types of data used in kadmin. 4055682Smarkm */ 4155682Smarkm 4290926Snectarstatic int 4390926Snectarget_response(const char *prompt, const char *def, char *buf, size_t len); 4490926Snectar 4555682Smarkm/* 46233294Sstas * attributes 4755682Smarkm */ 4855682Smarkm 4955682Smarkmstruct units kdb_attrs[] = { 50178825Sdfr { "allow-digest", KRB5_KDB_ALLOW_DIGEST }, 51178825Sdfr { "allow-kerberos4", KRB5_KDB_ALLOW_KERBEROS4 }, 52178825Sdfr { "trusted-for-delegation", KRB5_KDB_TRUSTED_FOR_DELEGATION }, 53178825Sdfr { "ok-as-delegate", KRB5_KDB_OK_AS_DELEGATE }, 5455682Smarkm { "new-princ", KRB5_KDB_NEW_PRINC }, 5555682Smarkm { "support-desmd5", KRB5_KDB_SUPPORT_DESMD5 }, 5655682Smarkm { "pwchange-service", KRB5_KDB_PWCHANGE_SERVICE }, 5755682Smarkm { "disallow-svr", KRB5_KDB_DISALLOW_SVR }, 5855682Smarkm { "requires-pw-change", KRB5_KDB_REQUIRES_PWCHANGE }, 5955682Smarkm { "requires-hw-auth", KRB5_KDB_REQUIRES_HW_AUTH }, 6055682Smarkm { "requires-pre-auth", KRB5_KDB_REQUIRES_PRE_AUTH }, 6155682Smarkm { "disallow-all-tix", KRB5_KDB_DISALLOW_ALL_TIX }, 6255682Smarkm { "disallow-dup-skey", KRB5_KDB_DISALLOW_DUP_SKEY }, 6355682Smarkm { "disallow-proxiable", KRB5_KDB_DISALLOW_PROXIABLE }, 6455682Smarkm { "disallow-renewable", KRB5_KDB_DISALLOW_RENEWABLE }, 6555682Smarkm { "disallow-tgt-based", KRB5_KDB_DISALLOW_TGT_BASED }, 6655682Smarkm { "disallow-forwardable", KRB5_KDB_DISALLOW_FORWARDABLE }, 6755682Smarkm { "disallow-postdated", KRB5_KDB_DISALLOW_POSTDATED }, 68233294Sstas { NULL, 0 } 6955682Smarkm}; 7055682Smarkm 7155682Smarkm/* 7255682Smarkm * convert the attributes in `attributes' into a printable string 7355682Smarkm * in `str, len' 7455682Smarkm */ 7555682Smarkm 7655682Smarkmvoid 7755682Smarkmattributes2str(krb5_flags attributes, char *str, size_t len) 7855682Smarkm{ 7955682Smarkm unparse_flags (attributes, kdb_attrs, str, len); 8055682Smarkm} 8155682Smarkm 8255682Smarkm/* 8355682Smarkm * convert the string in `str' into attributes in `flags' 8455682Smarkm * return 0 if parsed ok, else -1. 8555682Smarkm */ 8655682Smarkm 8755682Smarkmint 8855682Smarkmstr2attributes(const char *str, krb5_flags *flags) 8955682Smarkm{ 9055682Smarkm int res; 9155682Smarkm 9255682Smarkm res = parse_flags (str, kdb_attrs, *flags); 9355682Smarkm if (res < 0) 9455682Smarkm return res; 9555682Smarkm else { 9655682Smarkm *flags = res; 9755682Smarkm return 0; 9855682Smarkm } 9955682Smarkm} 10055682Smarkm 10155682Smarkm/* 10255682Smarkm * try to parse the string `resp' into attributes in `attr', also 10355682Smarkm * setting the `bit' in `mask' if attributes are given and valid. 10455682Smarkm */ 10555682Smarkm 10655682Smarkmint 10755682Smarkmparse_attributes (const char *resp, krb5_flags *attr, int *mask, int bit) 10855682Smarkm{ 10955682Smarkm krb5_flags tmp = *attr; 11055682Smarkm 11172445Sassar if (str2attributes(resp, &tmp) == 0) { 11255682Smarkm *attr = tmp; 11355682Smarkm if (mask) 11455682Smarkm *mask |= bit; 11555682Smarkm return 0; 11655682Smarkm } else if(*resp == '?') { 11755682Smarkm print_flags_table (kdb_attrs, stderr); 11855682Smarkm } else { 119178825Sdfr fprintf (stderr, "Unable to parse \"%s\"\n", resp); 12055682Smarkm } 12155682Smarkm return -1; 12255682Smarkm} 12355682Smarkm 12455682Smarkm/* 12555682Smarkm * allow the user to edit the attributes in `attr', prompting with `prompt' 12655682Smarkm */ 12755682Smarkm 12855682Smarkmint 12955682Smarkmedit_attributes (const char *prompt, krb5_flags *attr, int *mask, int bit) 13055682Smarkm{ 13155682Smarkm char buf[1024], resp[1024]; 13255682Smarkm 13355682Smarkm if (mask && (*mask & bit)) 13455682Smarkm return 0; 13555682Smarkm 13655682Smarkm attributes2str(*attr, buf, sizeof(buf)); 13755682Smarkm for (;;) { 13890926Snectar if(get_response("Attributes", buf, resp, sizeof(resp)) != 0) 13990926Snectar return 1; 14072445Sassar if (resp[0] == '\0') 14172445Sassar break; 14255682Smarkm if (parse_attributes (resp, attr, mask, bit) == 0) 14355682Smarkm break; 14455682Smarkm } 14555682Smarkm return 0; 14655682Smarkm} 14755682Smarkm 14855682Smarkm/* 14955682Smarkm * time_t 15055682Smarkm * the special value 0 means ``never'' 15155682Smarkm */ 15255682Smarkm 15355682Smarkm/* 15455682Smarkm * Convert the time `t' to a string representation in `str' (of max 15555682Smarkm * size `len'). If include_time also include time, otherwise just 156233294Sstas * date. 15755682Smarkm */ 15855682Smarkm 15955682Smarkmvoid 16055682Smarkmtime_t2str(time_t t, char *str, size_t len, int include_time) 16155682Smarkm{ 16255682Smarkm if(t) { 16355682Smarkm if(include_time) 16455682Smarkm strftime(str, len, "%Y-%m-%d %H:%M:%S UTC", gmtime(&t)); 16555682Smarkm else 16655682Smarkm strftime(str, len, "%Y-%m-%d", gmtime(&t)); 16755682Smarkm } else 16855682Smarkm snprintf(str, len, "never"); 16955682Smarkm} 17055682Smarkm 17155682Smarkm/* 17255682Smarkm * Convert the time representation in `str' to a time in `time'. 17355682Smarkm * Return 0 if succesful, else -1. 17455682Smarkm */ 17555682Smarkm 17655682Smarkmint 17772445Sassarstr2time_t (const char *str, time_t *t) 17855682Smarkm{ 17955682Smarkm const char *p; 18072445Sassar struct tm tm, tm2; 18155682Smarkm 18255682Smarkm memset (&tm, 0, sizeof (tm)); 183178825Sdfr memset (&tm2, 0, sizeof (tm2)); 18455682Smarkm 185233294Sstas while(isspace((unsigned char)*str)) 186233294Sstas str++; 187233294Sstas 188233294Sstas if (str[0] == '+') { 189233294Sstas str++; 190233294Sstas *t = parse_time(str, "month"); 191233294Sstas if (*t < 0) 192233294Sstas return -1; 193233294Sstas *t += time(NULL); 194233294Sstas return 0; 195233294Sstas } 196233294Sstas 19755682Smarkm if(strcasecmp(str, "never") == 0) { 19872445Sassar *t = 0; 19955682Smarkm return 0; 20055682Smarkm } 20155682Smarkm 20272445Sassar if(strcasecmp(str, "now") == 0) { 20372445Sassar *t = time(NULL); 20472445Sassar return 0; 20572445Sassar } 20672445Sassar 20755682Smarkm p = strptime (str, "%Y-%m-%d", &tm); 20855682Smarkm 20955682Smarkm if (p == NULL) 21055682Smarkm return -1; 21155682Smarkm 212178825Sdfr while(isspace((unsigned char)*p)) 213178825Sdfr p++; 21455682Smarkm 215178825Sdfr /* XXX this is really a bit optimistic, we should really complain 216178825Sdfr if there was a problem parsing the time */ 217178825Sdfr if(p[0] != '\0' && strptime (p, "%H:%M:%S", &tm2) != NULL) { 21872445Sassar tm.tm_hour = tm2.tm_hour; 21972445Sassar tm.tm_min = tm2.tm_min; 22072445Sassar tm.tm_sec = tm2.tm_sec; 221178825Sdfr } else { 222178825Sdfr /* Do it on the end of the day */ 223178825Sdfr tm.tm_hour = 23; 224178825Sdfr tm.tm_min = 59; 225178825Sdfr tm.tm_sec = 59; 22672445Sassar } 22755682Smarkm 22872445Sassar *t = tm2time (tm, 0); 22955682Smarkm return 0; 23055682Smarkm} 23155682Smarkm 23255682Smarkm/* 23355682Smarkm * try to parse the time in `resp' storing it in `value' 23455682Smarkm */ 23555682Smarkm 23655682Smarkmint 23755682Smarkmparse_timet (const char *resp, krb5_timestamp *value, int *mask, int bit) 23855682Smarkm{ 23955682Smarkm time_t tmp; 24055682Smarkm 24155682Smarkm if (str2time_t(resp, &tmp) == 0) { 24255682Smarkm *value = tmp; 24355682Smarkm if(mask) 24455682Smarkm *mask |= bit; 24555682Smarkm return 0; 246233294Sstas } 247178825Sdfr if(*resp != '?') 248178825Sdfr fprintf (stderr, "Unable to parse time \"%s\"\n", resp); 249178825Sdfr fprintf (stderr, "Print date on format YYYY-mm-dd [hh:mm:ss]\n"); 25055682Smarkm return -1; 25155682Smarkm} 25255682Smarkm 25355682Smarkm/* 25455682Smarkm * allow the user to edit the time in `value' 25555682Smarkm */ 25655682Smarkm 25755682Smarkmint 25855682Smarkmedit_timet (const char *prompt, krb5_timestamp *value, int *mask, int bit) 25955682Smarkm{ 26055682Smarkm char buf[1024], resp[1024]; 26155682Smarkm 26255682Smarkm if (mask && (*mask & bit)) 26355682Smarkm return 0; 26455682Smarkm 26555682Smarkm time_t2str (*value, buf, sizeof (buf), 0); 26655682Smarkm 26755682Smarkm for (;;) { 26890926Snectar if(get_response(prompt, buf, resp, sizeof(resp)) != 0) 26990926Snectar return 1; 27055682Smarkm if (parse_timet (resp, value, mask, bit) == 0) 27155682Smarkm break; 27255682Smarkm } 27355682Smarkm return 0; 27455682Smarkm} 27555682Smarkm 27655682Smarkm/* 27755682Smarkm * deltat 27855682Smarkm * the special value 0 means ``unlimited'' 27955682Smarkm */ 28055682Smarkm 28155682Smarkm/* 28255682Smarkm * convert the delta_t value in `t' into a printable form in `str, len' 28355682Smarkm */ 28455682Smarkm 28555682Smarkmvoid 28655682Smarkmdeltat2str(unsigned t, char *str, size_t len) 28755682Smarkm{ 28872445Sassar if(t == 0 || t == INT_MAX) 28972445Sassar snprintf(str, len, "unlimited"); 29072445Sassar else 29155682Smarkm unparse_time(t, str, len); 29255682Smarkm} 29355682Smarkm 29455682Smarkm/* 29555682Smarkm * parse the delta value in `str', storing result in `*delta' 29655682Smarkm * return 0 if ok, else -1 29755682Smarkm */ 29855682Smarkm 29955682Smarkmint 30055682Smarkmstr2deltat(const char *str, krb5_deltat *delta) 30155682Smarkm{ 30255682Smarkm int res; 30355682Smarkm 30455682Smarkm if(strcasecmp(str, "unlimited") == 0) { 30555682Smarkm *delta = 0; 30655682Smarkm return 0; 30755682Smarkm } 30855682Smarkm res = parse_time(str, "day"); 30955682Smarkm if (res < 0) 31055682Smarkm return res; 31155682Smarkm else { 31255682Smarkm *delta = res; 31355682Smarkm return 0; 31455682Smarkm } 31555682Smarkm} 31655682Smarkm 31755682Smarkm/* 31855682Smarkm * try to parse the string in `resp' into a deltad in `value' 31955682Smarkm * `mask' will get the bit `bit' set if a value was given. 32055682Smarkm */ 32155682Smarkm 32255682Smarkmint 32355682Smarkmparse_deltat (const char *resp, krb5_deltat *value, int *mask, int bit) 32455682Smarkm{ 32555682Smarkm krb5_deltat tmp; 32655682Smarkm 32755682Smarkm if (str2deltat(resp, &tmp) == 0) { 32855682Smarkm *value = tmp; 32955682Smarkm if (mask) 33055682Smarkm *mask |= bit; 33155682Smarkm return 0; 33255682Smarkm } else if(*resp == '?') { 33355682Smarkm print_time_table (stderr); 33455682Smarkm } else { 335178825Sdfr fprintf (stderr, "Unable to parse time \"%s\"\n", resp); 33655682Smarkm } 33755682Smarkm return -1; 33855682Smarkm} 33955682Smarkm 34055682Smarkm/* 34155682Smarkm * allow the user to edit the deltat in `value' 34255682Smarkm */ 34355682Smarkm 34455682Smarkmint 34555682Smarkmedit_deltat (const char *prompt, krb5_deltat *value, int *mask, int bit) 34655682Smarkm{ 34755682Smarkm char buf[1024], resp[1024]; 34855682Smarkm 34955682Smarkm if (mask && (*mask & bit)) 35055682Smarkm return 0; 35155682Smarkm 35255682Smarkm deltat2str(*value, buf, sizeof(buf)); 35355682Smarkm for (;;) { 35490926Snectar if(get_response(prompt, buf, resp, sizeof(resp)) != 0) 35590926Snectar return 1; 35655682Smarkm if (parse_deltat (resp, value, mask, bit) == 0) 35755682Smarkm break; 35855682Smarkm } 35955682Smarkm return 0; 36055682Smarkm} 36155682Smarkm 36255682Smarkm/* 36355682Smarkm * allow the user to edit `ent' 36455682Smarkm */ 36555682Smarkm 36690926Snectarvoid 36790926Snectarset_defaults(kadm5_principal_ent_t ent, int *mask, 36890926Snectar kadm5_principal_ent_t default_ent, int default_mask) 36955682Smarkm{ 37072445Sassar if (default_ent 37172445Sassar && (default_mask & KADM5_MAX_LIFE) 37272445Sassar && !(*mask & KADM5_MAX_LIFE)) 37355682Smarkm ent->max_life = default_ent->max_life; 37455682Smarkm 37572445Sassar if (default_ent 37672445Sassar && (default_mask & KADM5_MAX_RLIFE) 37772445Sassar && !(*mask & KADM5_MAX_RLIFE)) 37855682Smarkm ent->max_renewable_life = default_ent->max_renewable_life; 37955682Smarkm 38072445Sassar if (default_ent 38172445Sassar && (default_mask & KADM5_PRINC_EXPIRE_TIME) 38272445Sassar && !(*mask & KADM5_PRINC_EXPIRE_TIME)) 38355682Smarkm ent->princ_expire_time = default_ent->princ_expire_time; 38455682Smarkm 38572445Sassar if (default_ent 38672445Sassar && (default_mask & KADM5_PW_EXPIRATION) 38772445Sassar && !(*mask & KADM5_PW_EXPIRATION)) 38855682Smarkm ent->pw_expiration = default_ent->pw_expiration; 38955682Smarkm 39072445Sassar if (default_ent 39172445Sassar && (default_mask & KADM5_ATTRIBUTES) 39272445Sassar && !(*mask & KADM5_ATTRIBUTES)) 39355682Smarkm ent->attributes = default_ent->attributes & ~KRB5_KDB_DISALLOW_ALL_TIX; 39490926Snectar} 39590926Snectar 39690926Snectarint 39790926Snectaredit_entry(kadm5_principal_ent_t ent, int *mask, 39890926Snectar kadm5_principal_ent_t default_ent, int default_mask) 39990926Snectar{ 40090926Snectar 40190926Snectar set_defaults(ent, mask, default_ent, default_mask); 40290926Snectar 40390926Snectar if(edit_deltat ("Max ticket life", &ent->max_life, mask, 40490926Snectar KADM5_MAX_LIFE) != 0) 40590926Snectar return 1; 406233294Sstas 40790926Snectar if(edit_deltat ("Max renewable life", &ent->max_renewable_life, mask, 40890926Snectar KADM5_MAX_RLIFE) != 0) 40990926Snectar return 1; 41090926Snectar 41190926Snectar if(edit_timet ("Principal expiration time", &ent->princ_expire_time, mask, 41290926Snectar KADM5_PRINC_EXPIRE_TIME) != 0) 41390926Snectar return 1; 41490926Snectar 41590926Snectar if(edit_timet ("Password expiration time", &ent->pw_expiration, mask, 41690926Snectar KADM5_PW_EXPIRATION) != 0) 41790926Snectar return 1; 41890926Snectar 41990926Snectar if(edit_attributes ("Attributes", &ent->attributes, mask, 42090926Snectar KADM5_ATTRIBUTES) != 0) 42190926Snectar return 1; 42290926Snectar 42355682Smarkm return 0; 42455682Smarkm} 42555682Smarkm 42655682Smarkm/* 42755682Smarkm * Parse the arguments, set the fields in `ent' and the `mask' for the 42855682Smarkm * entries having been set. 42955682Smarkm * Return 1 on failure and 0 on success. 43055682Smarkm */ 43155682Smarkm 43255682Smarkmint 433233294Sstasset_entry(krb5_context contextp, 43455682Smarkm kadm5_principal_ent_t ent, 43555682Smarkm int *mask, 43655682Smarkm const char *max_ticket_life, 43755682Smarkm const char *max_renewable_life, 43855682Smarkm const char *expiration, 43955682Smarkm const char *pw_expiration, 44055682Smarkm const char *attributes) 44155682Smarkm{ 44255682Smarkm if (max_ticket_life != NULL) { 443233294Sstas if (parse_deltat (max_ticket_life, &ent->max_life, 44455682Smarkm mask, KADM5_MAX_LIFE)) { 445233294Sstas krb5_warnx (contextp, "unable to parse `%s'", max_ticket_life); 44655682Smarkm return 1; 44755682Smarkm } 44855682Smarkm } 44955682Smarkm if (max_renewable_life != NULL) { 450233294Sstas if (parse_deltat (max_renewable_life, &ent->max_renewable_life, 45155682Smarkm mask, KADM5_MAX_RLIFE)) { 452233294Sstas krb5_warnx (contextp, "unable to parse `%s'", max_renewable_life); 45355682Smarkm return 1; 45455682Smarkm } 45555682Smarkm } 45655682Smarkm 45755682Smarkm if (expiration) { 458233294Sstas if (parse_timet (expiration, &ent->princ_expire_time, 45955682Smarkm mask, KADM5_PRINC_EXPIRE_TIME)) { 460233294Sstas krb5_warnx (contextp, "unable to parse `%s'", expiration); 46155682Smarkm return 1; 46255682Smarkm } 46355682Smarkm } 46455682Smarkm if (pw_expiration) { 465233294Sstas if (parse_timet (pw_expiration, &ent->pw_expiration, 46655682Smarkm mask, KADM5_PW_EXPIRATION)) { 467233294Sstas krb5_warnx (contextp, "unable to parse `%s'", pw_expiration); 46855682Smarkm return 1; 46955682Smarkm } 47055682Smarkm } 47155682Smarkm if (attributes != NULL) { 472233294Sstas if (parse_attributes (attributes, &ent->attributes, 47355682Smarkm mask, KADM5_ATTRIBUTES)) { 474233294Sstas krb5_warnx (contextp, "unable to parse `%s'", attributes); 47555682Smarkm return 1; 47655682Smarkm } 47755682Smarkm } 47855682Smarkm return 0; 47955682Smarkm} 48055682Smarkm 48155682Smarkm/* 48255682Smarkm * Does `string' contain any globing characters? 48355682Smarkm */ 48455682Smarkm 48555682Smarkmstatic int 48655682Smarkmis_expression(const char *string) 48755682Smarkm{ 48855682Smarkm const char *p; 48955682Smarkm int quote = 0; 49055682Smarkm 49155682Smarkm for(p = string; *p; p++) { 49255682Smarkm if(quote) { 49355682Smarkm quote = 0; 49455682Smarkm continue; 49555682Smarkm } 49655682Smarkm if(*p == '\\') 49755682Smarkm quote++; 498233294Sstas else if(strchr("[]*?", *p) != NULL) 49955682Smarkm return 1; 50055682Smarkm } 50155682Smarkm return 0; 50255682Smarkm} 50355682Smarkm 504178825Sdfr/* 505178825Sdfr * Loop over all principals matching exp. If any of calls to `func' 506178825Sdfr * failes, the first error is returned when all principals are 507178825Sdfr * processed. 508178825Sdfr */ 50955682Smarkmint 510233294Sstasforeach_principal(const char *exp_str, 511233294Sstas int (*func)(krb5_principal, void*), 51278527Sassar const char *funcname, 51355682Smarkm void *data) 51455682Smarkm{ 515233294Sstas char **princs = NULL; 516233294Sstas int num_princs = 0; 51755682Smarkm int i; 518178825Sdfr krb5_error_code saved_ret = 0, ret = 0; 51955682Smarkm krb5_principal princ_ent; 52055682Smarkm int is_expr; 52155682Smarkm 52255682Smarkm /* if this isn't an expression, there is no point in wading 52355682Smarkm through the whole database looking for matches */ 524178825Sdfr is_expr = is_expression(exp_str); 52555682Smarkm if(is_expr) 526178825Sdfr ret = kadm5_get_principals(kadm_handle, exp_str, &princs, &num_princs); 52755682Smarkm if(!is_expr || ret == KADM5_AUTH_LIST) { 52855682Smarkm /* we might be able to perform the requested opreration even 52955682Smarkm if we're not allowed to list principals */ 53055682Smarkm num_princs = 1; 53155682Smarkm princs = malloc(sizeof(*princs)); 53255682Smarkm if(princs == NULL) 53355682Smarkm return ENOMEM; 534178825Sdfr princs[0] = strdup(exp_str); 535233294Sstas if(princs[0] == NULL){ 53655682Smarkm free(princs); 53755682Smarkm return ENOMEM; 53855682Smarkm } 53955682Smarkm } else if(ret) { 54055682Smarkm krb5_warn(context, ret, "kadm5_get_principals"); 54155682Smarkm return ret; 54255682Smarkm } 54355682Smarkm for(i = 0; i < num_princs; i++) { 54455682Smarkm ret = krb5_parse_name(context, princs[i], &princ_ent); 54555682Smarkm if(ret){ 54655682Smarkm krb5_warn(context, ret, "krb5_parse_name(%s)", princs[i]); 54755682Smarkm continue; 54855682Smarkm } 54955682Smarkm ret = (*func)(princ_ent, data); 550178825Sdfr if(ret) { 551233294Sstas krb5_clear_error_message(context); 55278527Sassar krb5_warn(context, ret, "%s %s", funcname, princs[i]); 553178825Sdfr if (saved_ret == 0) 554178825Sdfr saved_ret = ret; 555178825Sdfr } 55655682Smarkm krb5_free_principal(context, princ_ent); 55755682Smarkm } 558178825Sdfr if (ret == 0 && saved_ret != 0) 559178825Sdfr ret = saved_ret; 56055682Smarkm kadm5_free_name_list(kadm_handle, princs, &num_princs); 561178825Sdfr return ret; 56255682Smarkm} 56355682Smarkm 56455682Smarkm/* 56555682Smarkm * prompt with `prompt' and default value `def', and store the reply 56655682Smarkm * in `buf, len' 56755682Smarkm */ 56855682Smarkm 56990926Snectar#include <setjmp.h> 57090926Snectar 57190926Snectarstatic jmp_buf jmpbuf; 57290926Snectar 57390926Snectarstatic void 57490926Snectarinterrupt(int sig) 57590926Snectar{ 57690926Snectar longjmp(jmpbuf, 1); 57790926Snectar} 57890926Snectar 57990926Snectarstatic int 58055682Smarkmget_response(const char *prompt, const char *def, char *buf, size_t len) 58155682Smarkm{ 58255682Smarkm char *p; 58390926Snectar void (*osig)(int); 58455682Smarkm 58590926Snectar osig = signal(SIGINT, interrupt); 58690926Snectar if(setjmp(jmpbuf)) { 58790926Snectar signal(SIGINT, osig); 588178825Sdfr fprintf(stderr, "\n"); 58990926Snectar return 1; 59090926Snectar } 59190926Snectar 592178825Sdfr fprintf(stderr, "%s [%s]:", prompt, def); 59390926Snectar if(fgets(buf, len, stdin) == NULL) { 59490926Snectar int save_errno = errno; 59590926Snectar if(ferror(stdin)) 59690926Snectar krb5_err(context, 1, save_errno, "<stdin>"); 59790926Snectar signal(SIGINT, osig); 59890926Snectar return 1; 59990926Snectar } 60055682Smarkm p = strchr(buf, '\n'); 60155682Smarkm if(p) 60255682Smarkm *p = '\0'; 60355682Smarkm if(strcmp(buf, "") == 0) 60490926Snectar strlcpy(buf, def, len); 60590926Snectar signal(SIGINT, osig); 60690926Snectar return 0; 60755682Smarkm} 60872445Sassar 60972445Sassar/* 61072445Sassar * return [0, 16) or -1 61172445Sassar */ 61272445Sassar 61372445Sassarstatic int 61472445Sassarhex2n (char c) 61572445Sassar{ 61672445Sassar static char hexdigits[] = "0123456789abcdef"; 61772445Sassar const char *p; 61872445Sassar 619120945Snectar p = strchr (hexdigits, tolower((unsigned char)c)); 62072445Sassar if (p == NULL) 62172445Sassar return -1; 62272445Sassar else 62372445Sassar return p - hexdigits; 62472445Sassar} 62572445Sassar 62672445Sassar/* 62772445Sassar * convert a key in a readable format into a keyblock. 62872445Sassar * return 0 iff succesful, otherwise `err' should point to an error message 62972445Sassar */ 63072445Sassar 63172445Sassarint 63272445Sassarparse_des_key (const char *key_string, krb5_key_data *key_data, 633178825Sdfr const char **error) 63472445Sassar{ 63572445Sassar const char *p = key_string; 63672445Sassar unsigned char bits[8]; 63772445Sassar int i; 63872445Sassar 63972445Sassar if (strlen (key_string) != 16) { 640178825Sdfr *error = "bad length, should be 16 for DES key"; 64172445Sassar return 1; 64272445Sassar } 64372445Sassar for (i = 0; i < 8; ++i) { 64472445Sassar int d1, d2; 64572445Sassar 64672445Sassar d1 = hex2n(p[2 * i]); 64772445Sassar d2 = hex2n(p[2 * i + 1]); 64872445Sassar if (d1 < 0 || d2 < 0) { 649178825Sdfr *error = "non-hex character"; 65072445Sassar return 1; 65172445Sassar } 65272445Sassar bits[i] = (d1 << 4) | d2; 65372445Sassar } 65472445Sassar for (i = 0; i < 3; ++i) { 65572445Sassar key_data[i].key_data_ver = 2; 65672445Sassar key_data[i].key_data_kvno = 0; 65772445Sassar /* key */ 65872445Sassar key_data[i].key_data_type[0] = ETYPE_DES_CBC_CRC; 65972445Sassar key_data[i].key_data_length[0] = 8; 66072445Sassar key_data[i].key_data_contents[0] = malloc(8); 661178825Sdfr if (key_data[i].key_data_contents[0] == NULL) { 662178825Sdfr *error = "malloc"; 663178825Sdfr return ENOMEM; 664178825Sdfr } 66572445Sassar memcpy (key_data[i].key_data_contents[0], bits, 8); 66672445Sassar /* salt */ 66772445Sassar key_data[i].key_data_type[1] = KRB5_PW_SALT; 66872445Sassar key_data[i].key_data_length[1] = 0; 66972445Sassar key_data[i].key_data_contents[1] = NULL; 67072445Sassar } 67172445Sassar key_data[0].key_data_type[0] = ETYPE_DES_CBC_MD5; 67272445Sassar key_data[1].key_data_type[0] = ETYPE_DES_CBC_MD4; 67372445Sassar return 0; 67472445Sassar} 675