155682Smarkm/* 2178825Sdfr * Copyright (c) 1997 - 2006 Kungliga Tekniska H�gskolan 355682Smarkm * (Royal Institute of Technology, Stockholm, Sweden). 455682Smarkm * All rights reserved. 555682Smarkm * 655682Smarkm * Redistribution and use in source and binary forms, with or without 755682Smarkm * modification, are permitted provided that the following conditions 855682Smarkm * are met: 955682Smarkm * 1055682Smarkm * 1. Redistributions of source code must retain the above copyright 1155682Smarkm * notice, this list of conditions and the following disclaimer. 1255682Smarkm * 1355682Smarkm * 2. Redistributions in binary form must reproduce the above copyright 1455682Smarkm * notice, this list of conditions and the following disclaimer in the 1555682Smarkm * documentation and/or other materials provided with the distribution. 1655682Smarkm * 1755682Smarkm * 3. Neither the name of the Institute nor the names of its contributors 1855682Smarkm * may be used to endorse or promote products derived from this software 1955682Smarkm * without specific prior written permission. 2055682Smarkm * 2155682Smarkm * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND 2255682Smarkm * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2355682Smarkm * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2455682Smarkm * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE 2555682Smarkm * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2655682Smarkm * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2755682Smarkm * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2855682Smarkm * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2955682Smarkm * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3055682Smarkm * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3155682Smarkm * SUCH DAMAGE. 3255682Smarkm */ 3355682Smarkm 3455682Smarkm#include "kadmin_locl.h" 3555682Smarkm#include <parse_units.h> 3655682Smarkm 37178825SdfrRCSID("$Id: util.c 21745 2007-07-31 16:11:25Z lha $"); 3855682Smarkm 3955682Smarkm/* 4055682Smarkm * util.c - functions for parsing, unparsing, and editing different 4155682Smarkm * types of data used in kadmin. 4255682Smarkm */ 4355682Smarkm 4490926Snectarstatic int 4590926Snectarget_response(const char *prompt, const char *def, char *buf, size_t len); 4690926Snectar 4755682Smarkm/* 4855682Smarkm * attributes 4955682Smarkm */ 5055682Smarkm 5155682Smarkmstruct units kdb_attrs[] = { 52178825Sdfr { "allow-digest", KRB5_KDB_ALLOW_DIGEST }, 53178825Sdfr { "allow-kerberos4", KRB5_KDB_ALLOW_KERBEROS4 }, 54178825Sdfr { "trusted-for-delegation", KRB5_KDB_TRUSTED_FOR_DELEGATION }, 55178825Sdfr { "ok-as-delegate", KRB5_KDB_OK_AS_DELEGATE }, 5655682Smarkm { "new-princ", KRB5_KDB_NEW_PRINC }, 5755682Smarkm { "support-desmd5", KRB5_KDB_SUPPORT_DESMD5 }, 5855682Smarkm { "pwchange-service", KRB5_KDB_PWCHANGE_SERVICE }, 5955682Smarkm { "disallow-svr", KRB5_KDB_DISALLOW_SVR }, 6055682Smarkm { "requires-pw-change", KRB5_KDB_REQUIRES_PWCHANGE }, 6155682Smarkm { "requires-hw-auth", KRB5_KDB_REQUIRES_HW_AUTH }, 6255682Smarkm { "requires-pre-auth", KRB5_KDB_REQUIRES_PRE_AUTH }, 6355682Smarkm { "disallow-all-tix", KRB5_KDB_DISALLOW_ALL_TIX }, 6455682Smarkm { "disallow-dup-skey", KRB5_KDB_DISALLOW_DUP_SKEY }, 6555682Smarkm { "disallow-proxiable", KRB5_KDB_DISALLOW_PROXIABLE }, 6655682Smarkm { "disallow-renewable", KRB5_KDB_DISALLOW_RENEWABLE }, 6755682Smarkm { "disallow-tgt-based", KRB5_KDB_DISALLOW_TGT_BASED }, 6855682Smarkm { "disallow-forwardable", KRB5_KDB_DISALLOW_FORWARDABLE }, 6955682Smarkm { "disallow-postdated", KRB5_KDB_DISALLOW_POSTDATED }, 7055682Smarkm { NULL } 7155682Smarkm}; 7255682Smarkm 7355682Smarkm/* 7455682Smarkm * convert the attributes in `attributes' into a printable string 7555682Smarkm * in `str, len' 7655682Smarkm */ 7755682Smarkm 7855682Smarkmvoid 7955682Smarkmattributes2str(krb5_flags attributes, char *str, size_t len) 8055682Smarkm{ 8155682Smarkm unparse_flags (attributes, kdb_attrs, str, len); 8255682Smarkm} 8355682Smarkm 8455682Smarkm/* 8555682Smarkm * convert the string in `str' into attributes in `flags' 8655682Smarkm * return 0 if parsed ok, else -1. 8755682Smarkm */ 8855682Smarkm 8955682Smarkmint 9055682Smarkmstr2attributes(const char *str, krb5_flags *flags) 9155682Smarkm{ 9255682Smarkm int res; 9355682Smarkm 9455682Smarkm res = parse_flags (str, kdb_attrs, *flags); 9555682Smarkm if (res < 0) 9655682Smarkm return res; 9755682Smarkm else { 9855682Smarkm *flags = res; 9955682Smarkm return 0; 10055682Smarkm } 10155682Smarkm} 10255682Smarkm 10355682Smarkm/* 10455682Smarkm * try to parse the string `resp' into attributes in `attr', also 10555682Smarkm * setting the `bit' in `mask' if attributes are given and valid. 10655682Smarkm */ 10755682Smarkm 10855682Smarkmint 10955682Smarkmparse_attributes (const char *resp, krb5_flags *attr, int *mask, int bit) 11055682Smarkm{ 11155682Smarkm krb5_flags tmp = *attr; 11255682Smarkm 11372445Sassar if (str2attributes(resp, &tmp) == 0) { 11455682Smarkm *attr = tmp; 11555682Smarkm if (mask) 11655682Smarkm *mask |= bit; 11755682Smarkm return 0; 11855682Smarkm } else if(*resp == '?') { 11955682Smarkm print_flags_table (kdb_attrs, stderr); 12055682Smarkm } else { 121178825Sdfr fprintf (stderr, "Unable to parse \"%s\"\n", resp); 12255682Smarkm } 12355682Smarkm return -1; 12455682Smarkm} 12555682Smarkm 12655682Smarkm/* 12755682Smarkm * allow the user to edit the attributes in `attr', prompting with `prompt' 12855682Smarkm */ 12955682Smarkm 13055682Smarkmint 13155682Smarkmedit_attributes (const char *prompt, krb5_flags *attr, int *mask, int bit) 13255682Smarkm{ 13355682Smarkm char buf[1024], resp[1024]; 13455682Smarkm 13555682Smarkm if (mask && (*mask & bit)) 13655682Smarkm return 0; 13755682Smarkm 13855682Smarkm attributes2str(*attr, buf, sizeof(buf)); 13955682Smarkm for (;;) { 14090926Snectar if(get_response("Attributes", buf, resp, sizeof(resp)) != 0) 14190926Snectar return 1; 14272445Sassar if (resp[0] == '\0') 14372445Sassar break; 14455682Smarkm if (parse_attributes (resp, attr, mask, bit) == 0) 14555682Smarkm break; 14655682Smarkm } 14755682Smarkm return 0; 14855682Smarkm} 14955682Smarkm 15055682Smarkm/* 15155682Smarkm * time_t 15255682Smarkm * the special value 0 means ``never'' 15355682Smarkm */ 15455682Smarkm 15555682Smarkm/* 15655682Smarkm * Convert the time `t' to a string representation in `str' (of max 15755682Smarkm * size `len'). If include_time also include time, otherwise just 15855682Smarkm * date. 15955682Smarkm */ 16055682Smarkm 16155682Smarkmvoid 16255682Smarkmtime_t2str(time_t t, char *str, size_t len, int include_time) 16355682Smarkm{ 16455682Smarkm if(t) { 16555682Smarkm if(include_time) 16655682Smarkm strftime(str, len, "%Y-%m-%d %H:%M:%S UTC", gmtime(&t)); 16755682Smarkm else 16855682Smarkm strftime(str, len, "%Y-%m-%d", gmtime(&t)); 16955682Smarkm } else 17055682Smarkm snprintf(str, len, "never"); 17155682Smarkm} 17255682Smarkm 17355682Smarkm/* 17455682Smarkm * Convert the time representation in `str' to a time in `time'. 17555682Smarkm * Return 0 if succesful, else -1. 17655682Smarkm */ 17755682Smarkm 17855682Smarkmint 17972445Sassarstr2time_t (const char *str, time_t *t) 18055682Smarkm{ 18155682Smarkm const char *p; 18272445Sassar struct tm tm, tm2; 18355682Smarkm 18455682Smarkm memset (&tm, 0, sizeof (tm)); 185178825Sdfr memset (&tm2, 0, sizeof (tm2)); 18655682Smarkm 18755682Smarkm if(strcasecmp(str, "never") == 0) { 18872445Sassar *t = 0; 18955682Smarkm return 0; 19055682Smarkm } 19155682Smarkm 19272445Sassar if(strcasecmp(str, "now") == 0) { 19372445Sassar *t = time(NULL); 19472445Sassar return 0; 19572445Sassar } 19672445Sassar 19755682Smarkm p = strptime (str, "%Y-%m-%d", &tm); 19855682Smarkm 19955682Smarkm if (p == NULL) 20055682Smarkm return -1; 20155682Smarkm 202178825Sdfr while(isspace((unsigned char)*p)) 203178825Sdfr p++; 20455682Smarkm 205178825Sdfr /* XXX this is really a bit optimistic, we should really complain 206178825Sdfr if there was a problem parsing the time */ 207178825Sdfr if(p[0] != '\0' && strptime (p, "%H:%M:%S", &tm2) != NULL) { 20872445Sassar tm.tm_hour = tm2.tm_hour; 20972445Sassar tm.tm_min = tm2.tm_min; 21072445Sassar tm.tm_sec = tm2.tm_sec; 211178825Sdfr } else { 212178825Sdfr /* Do it on the end of the day */ 213178825Sdfr tm.tm_hour = 23; 214178825Sdfr tm.tm_min = 59; 215178825Sdfr tm.tm_sec = 59; 21672445Sassar } 21755682Smarkm 21872445Sassar *t = tm2time (tm, 0); 21955682Smarkm return 0; 22055682Smarkm} 22155682Smarkm 22255682Smarkm/* 22355682Smarkm * try to parse the time in `resp' storing it in `value' 22455682Smarkm */ 22555682Smarkm 22655682Smarkmint 22755682Smarkmparse_timet (const char *resp, krb5_timestamp *value, int *mask, int bit) 22855682Smarkm{ 22955682Smarkm time_t tmp; 23055682Smarkm 23155682Smarkm if (str2time_t(resp, &tmp) == 0) { 23255682Smarkm *value = tmp; 23355682Smarkm if(mask) 23455682Smarkm *mask |= bit; 23555682Smarkm return 0; 236178825Sdfr } 237178825Sdfr if(*resp != '?') 238178825Sdfr fprintf (stderr, "Unable to parse time \"%s\"\n", resp); 239178825Sdfr fprintf (stderr, "Print date on format YYYY-mm-dd [hh:mm:ss]\n"); 24055682Smarkm return -1; 24155682Smarkm} 24255682Smarkm 24355682Smarkm/* 24455682Smarkm * allow the user to edit the time in `value' 24555682Smarkm */ 24655682Smarkm 24755682Smarkmint 24855682Smarkmedit_timet (const char *prompt, krb5_timestamp *value, int *mask, int bit) 24955682Smarkm{ 25055682Smarkm char buf[1024], resp[1024]; 25155682Smarkm 25255682Smarkm if (mask && (*mask & bit)) 25355682Smarkm return 0; 25455682Smarkm 25555682Smarkm time_t2str (*value, buf, sizeof (buf), 0); 25655682Smarkm 25755682Smarkm for (;;) { 25890926Snectar if(get_response(prompt, buf, resp, sizeof(resp)) != 0) 25990926Snectar return 1; 26055682Smarkm if (parse_timet (resp, value, mask, bit) == 0) 26155682Smarkm break; 26255682Smarkm } 26355682Smarkm return 0; 26455682Smarkm} 26555682Smarkm 26655682Smarkm/* 26755682Smarkm * deltat 26855682Smarkm * the special value 0 means ``unlimited'' 26955682Smarkm */ 27055682Smarkm 27155682Smarkm/* 27255682Smarkm * convert the delta_t value in `t' into a printable form in `str, len' 27355682Smarkm */ 27455682Smarkm 27555682Smarkmvoid 27655682Smarkmdeltat2str(unsigned t, char *str, size_t len) 27755682Smarkm{ 27872445Sassar if(t == 0 || t == INT_MAX) 27972445Sassar snprintf(str, len, "unlimited"); 28072445Sassar else 28155682Smarkm unparse_time(t, str, len); 28255682Smarkm} 28355682Smarkm 28455682Smarkm/* 28555682Smarkm * parse the delta value in `str', storing result in `*delta' 28655682Smarkm * return 0 if ok, else -1 28755682Smarkm */ 28855682Smarkm 28955682Smarkmint 29055682Smarkmstr2deltat(const char *str, krb5_deltat *delta) 29155682Smarkm{ 29255682Smarkm int res; 29355682Smarkm 29455682Smarkm if(strcasecmp(str, "unlimited") == 0) { 29555682Smarkm *delta = 0; 29655682Smarkm return 0; 29755682Smarkm } 29855682Smarkm res = parse_time(str, "day"); 29955682Smarkm if (res < 0) 30055682Smarkm return res; 30155682Smarkm else { 30255682Smarkm *delta = res; 30355682Smarkm return 0; 30455682Smarkm } 30555682Smarkm} 30655682Smarkm 30755682Smarkm/* 30855682Smarkm * try to parse the string in `resp' into a deltad in `value' 30955682Smarkm * `mask' will get the bit `bit' set if a value was given. 31055682Smarkm */ 31155682Smarkm 31255682Smarkmint 31355682Smarkmparse_deltat (const char *resp, krb5_deltat *value, int *mask, int bit) 31455682Smarkm{ 31555682Smarkm krb5_deltat tmp; 31655682Smarkm 31755682Smarkm if (str2deltat(resp, &tmp) == 0) { 31855682Smarkm *value = tmp; 31955682Smarkm if (mask) 32055682Smarkm *mask |= bit; 32155682Smarkm return 0; 32255682Smarkm } else if(*resp == '?') { 32355682Smarkm print_time_table (stderr); 32455682Smarkm } else { 325178825Sdfr fprintf (stderr, "Unable to parse time \"%s\"\n", resp); 32655682Smarkm } 32755682Smarkm return -1; 32855682Smarkm} 32955682Smarkm 33055682Smarkm/* 33155682Smarkm * allow the user to edit the deltat in `value' 33255682Smarkm */ 33355682Smarkm 33455682Smarkmint 33555682Smarkmedit_deltat (const char *prompt, krb5_deltat *value, int *mask, int bit) 33655682Smarkm{ 33755682Smarkm char buf[1024], resp[1024]; 33855682Smarkm 33955682Smarkm if (mask && (*mask & bit)) 34055682Smarkm return 0; 34155682Smarkm 34255682Smarkm deltat2str(*value, buf, sizeof(buf)); 34355682Smarkm for (;;) { 34490926Snectar if(get_response(prompt, buf, resp, sizeof(resp)) != 0) 34590926Snectar return 1; 34655682Smarkm if (parse_deltat (resp, value, mask, bit) == 0) 34755682Smarkm break; 34855682Smarkm } 34955682Smarkm return 0; 35055682Smarkm} 35155682Smarkm 35255682Smarkm/* 35355682Smarkm * allow the user to edit `ent' 35455682Smarkm */ 35555682Smarkm 35690926Snectarvoid 35790926Snectarset_defaults(kadm5_principal_ent_t ent, int *mask, 35890926Snectar kadm5_principal_ent_t default_ent, int default_mask) 35955682Smarkm{ 36072445Sassar if (default_ent 36172445Sassar && (default_mask & KADM5_MAX_LIFE) 36272445Sassar && !(*mask & KADM5_MAX_LIFE)) 36355682Smarkm ent->max_life = default_ent->max_life; 36455682Smarkm 36572445Sassar if (default_ent 36672445Sassar && (default_mask & KADM5_MAX_RLIFE) 36772445Sassar && !(*mask & KADM5_MAX_RLIFE)) 36855682Smarkm ent->max_renewable_life = default_ent->max_renewable_life; 36955682Smarkm 37072445Sassar if (default_ent 37172445Sassar && (default_mask & KADM5_PRINC_EXPIRE_TIME) 37272445Sassar && !(*mask & KADM5_PRINC_EXPIRE_TIME)) 37355682Smarkm ent->princ_expire_time = default_ent->princ_expire_time; 37455682Smarkm 37572445Sassar if (default_ent 37672445Sassar && (default_mask & KADM5_PW_EXPIRATION) 37772445Sassar && !(*mask & KADM5_PW_EXPIRATION)) 37855682Smarkm ent->pw_expiration = default_ent->pw_expiration; 37955682Smarkm 38072445Sassar if (default_ent 38172445Sassar && (default_mask & KADM5_ATTRIBUTES) 38272445Sassar && !(*mask & KADM5_ATTRIBUTES)) 38355682Smarkm ent->attributes = default_ent->attributes & ~KRB5_KDB_DISALLOW_ALL_TIX; 38490926Snectar} 38590926Snectar 38690926Snectarint 38790926Snectaredit_entry(kadm5_principal_ent_t ent, int *mask, 38890926Snectar kadm5_principal_ent_t default_ent, int default_mask) 38990926Snectar{ 39090926Snectar 39190926Snectar set_defaults(ent, mask, default_ent, default_mask); 39290926Snectar 39390926Snectar if(edit_deltat ("Max ticket life", &ent->max_life, mask, 39490926Snectar KADM5_MAX_LIFE) != 0) 39590926Snectar return 1; 39690926Snectar 39790926Snectar if(edit_deltat ("Max renewable life", &ent->max_renewable_life, mask, 39890926Snectar KADM5_MAX_RLIFE) != 0) 39990926Snectar return 1; 40090926Snectar 40190926Snectar if(edit_timet ("Principal expiration time", &ent->princ_expire_time, mask, 40290926Snectar KADM5_PRINC_EXPIRE_TIME) != 0) 40390926Snectar return 1; 40490926Snectar 40590926Snectar if(edit_timet ("Password expiration time", &ent->pw_expiration, mask, 40690926Snectar KADM5_PW_EXPIRATION) != 0) 40790926Snectar return 1; 40890926Snectar 40990926Snectar if(edit_attributes ("Attributes", &ent->attributes, mask, 41090926Snectar KADM5_ATTRIBUTES) != 0) 41190926Snectar return 1; 41290926Snectar 41355682Smarkm return 0; 41455682Smarkm} 41555682Smarkm 41655682Smarkm/* 41755682Smarkm * Parse the arguments, set the fields in `ent' and the `mask' for the 41855682Smarkm * entries having been set. 41955682Smarkm * Return 1 on failure and 0 on success. 42055682Smarkm */ 42155682Smarkm 42255682Smarkmint 42355682Smarkmset_entry(krb5_context context, 42455682Smarkm kadm5_principal_ent_t ent, 42555682Smarkm int *mask, 42655682Smarkm const char *max_ticket_life, 42755682Smarkm const char *max_renewable_life, 42855682Smarkm const char *expiration, 42955682Smarkm const char *pw_expiration, 43055682Smarkm const char *attributes) 43155682Smarkm{ 43255682Smarkm if (max_ticket_life != NULL) { 43355682Smarkm if (parse_deltat (max_ticket_life, &ent->max_life, 43455682Smarkm mask, KADM5_MAX_LIFE)) { 43555682Smarkm krb5_warnx (context, "unable to parse `%s'", max_ticket_life); 43655682Smarkm return 1; 43755682Smarkm } 43855682Smarkm } 43955682Smarkm if (max_renewable_life != NULL) { 44055682Smarkm if (parse_deltat (max_renewable_life, &ent->max_renewable_life, 44155682Smarkm mask, KADM5_MAX_RLIFE)) { 44255682Smarkm krb5_warnx (context, "unable to parse `%s'", max_renewable_life); 44355682Smarkm return 1; 44455682Smarkm } 44555682Smarkm } 44655682Smarkm 44755682Smarkm if (expiration) { 44855682Smarkm if (parse_timet (expiration, &ent->princ_expire_time, 44955682Smarkm mask, KADM5_PRINC_EXPIRE_TIME)) { 45055682Smarkm krb5_warnx (context, "unable to parse `%s'", expiration); 45155682Smarkm return 1; 45255682Smarkm } 45355682Smarkm } 45455682Smarkm if (pw_expiration) { 45555682Smarkm if (parse_timet (pw_expiration, &ent->pw_expiration, 45655682Smarkm mask, KADM5_PW_EXPIRATION)) { 45755682Smarkm krb5_warnx (context, "unable to parse `%s'", pw_expiration); 45855682Smarkm return 1; 45955682Smarkm } 46055682Smarkm } 46155682Smarkm if (attributes != NULL) { 46255682Smarkm if (parse_attributes (attributes, &ent->attributes, 46355682Smarkm mask, KADM5_ATTRIBUTES)) { 46455682Smarkm krb5_warnx (context, "unable to parse `%s'", attributes); 46555682Smarkm return 1; 46655682Smarkm } 46755682Smarkm } 46855682Smarkm return 0; 46955682Smarkm} 47055682Smarkm 47155682Smarkm/* 47255682Smarkm * Does `string' contain any globing characters? 47355682Smarkm */ 47455682Smarkm 47555682Smarkmstatic int 47655682Smarkmis_expression(const char *string) 47755682Smarkm{ 47855682Smarkm const char *p; 47955682Smarkm int quote = 0; 48055682Smarkm 48155682Smarkm for(p = string; *p; p++) { 48255682Smarkm if(quote) { 48355682Smarkm quote = 0; 48455682Smarkm continue; 48555682Smarkm } 48655682Smarkm if(*p == '\\') 48755682Smarkm quote++; 48855682Smarkm else if(strchr("[]*?", *p) != NULL) 48955682Smarkm return 1; 49055682Smarkm } 49155682Smarkm return 0; 49255682Smarkm} 49355682Smarkm 494178825Sdfr/* 495178825Sdfr * Loop over all principals matching exp. If any of calls to `func' 496178825Sdfr * failes, the first error is returned when all principals are 497178825Sdfr * processed. 498178825Sdfr */ 49955682Smarkmint 500178825Sdfrforeach_principal(const char *exp_str, 50155682Smarkm int (*func)(krb5_principal, void*), 50278527Sassar const char *funcname, 50355682Smarkm void *data) 50455682Smarkm{ 50555682Smarkm char **princs; 50655682Smarkm int num_princs; 50755682Smarkm int i; 508178825Sdfr krb5_error_code saved_ret = 0, ret = 0; 50955682Smarkm krb5_principal princ_ent; 51055682Smarkm int is_expr; 51155682Smarkm 51255682Smarkm /* if this isn't an expression, there is no point in wading 51355682Smarkm through the whole database looking for matches */ 514178825Sdfr is_expr = is_expression(exp_str); 51555682Smarkm if(is_expr) 516178825Sdfr ret = kadm5_get_principals(kadm_handle, exp_str, &princs, &num_princs); 51755682Smarkm if(!is_expr || ret == KADM5_AUTH_LIST) { 51855682Smarkm /* we might be able to perform the requested opreration even 51955682Smarkm if we're not allowed to list principals */ 52055682Smarkm num_princs = 1; 52155682Smarkm princs = malloc(sizeof(*princs)); 52255682Smarkm if(princs == NULL) 52355682Smarkm return ENOMEM; 524178825Sdfr princs[0] = strdup(exp_str); 52555682Smarkm if(princs[0] == NULL){ 52655682Smarkm free(princs); 52755682Smarkm return ENOMEM; 52855682Smarkm } 52955682Smarkm } else if(ret) { 53055682Smarkm krb5_warn(context, ret, "kadm5_get_principals"); 53155682Smarkm return ret; 53255682Smarkm } 53355682Smarkm for(i = 0; i < num_princs; i++) { 53455682Smarkm ret = krb5_parse_name(context, princs[i], &princ_ent); 53555682Smarkm if(ret){ 53655682Smarkm krb5_warn(context, ret, "krb5_parse_name(%s)", princs[i]); 53755682Smarkm continue; 53855682Smarkm } 53955682Smarkm ret = (*func)(princ_ent, data); 540178825Sdfr if(ret) { 541178825Sdfr krb5_clear_error_string(context); 54278527Sassar krb5_warn(context, ret, "%s %s", funcname, princs[i]); 543178825Sdfr if (saved_ret == 0) 544178825Sdfr saved_ret = ret; 545178825Sdfr } 54655682Smarkm krb5_free_principal(context, princ_ent); 54755682Smarkm } 548178825Sdfr if (ret == 0 && saved_ret != 0) 549178825Sdfr ret = saved_ret; 55055682Smarkm kadm5_free_name_list(kadm_handle, princs, &num_princs); 551178825Sdfr return ret; 55255682Smarkm} 55355682Smarkm 55455682Smarkm/* 55555682Smarkm * prompt with `prompt' and default value `def', and store the reply 55655682Smarkm * in `buf, len' 55755682Smarkm */ 55855682Smarkm 55990926Snectar#include <setjmp.h> 56090926Snectar 56190926Snectarstatic jmp_buf jmpbuf; 56290926Snectar 56390926Snectarstatic void 56490926Snectarinterrupt(int sig) 56590926Snectar{ 56690926Snectar longjmp(jmpbuf, 1); 56790926Snectar} 56890926Snectar 56990926Snectarstatic int 57055682Smarkmget_response(const char *prompt, const char *def, char *buf, size_t len) 57155682Smarkm{ 57255682Smarkm char *p; 57390926Snectar void (*osig)(int); 57455682Smarkm 57590926Snectar osig = signal(SIGINT, interrupt); 57690926Snectar if(setjmp(jmpbuf)) { 57790926Snectar signal(SIGINT, osig); 578178825Sdfr fprintf(stderr, "\n"); 57990926Snectar return 1; 58090926Snectar } 58190926Snectar 582178825Sdfr fprintf(stderr, "%s [%s]:", prompt, def); 58390926Snectar if(fgets(buf, len, stdin) == NULL) { 58490926Snectar int save_errno = errno; 58590926Snectar if(ferror(stdin)) 58690926Snectar krb5_err(context, 1, save_errno, "<stdin>"); 58790926Snectar signal(SIGINT, osig); 58890926Snectar return 1; 58990926Snectar } 59055682Smarkm p = strchr(buf, '\n'); 59155682Smarkm if(p) 59255682Smarkm *p = '\0'; 59355682Smarkm if(strcmp(buf, "") == 0) 59490926Snectar strlcpy(buf, def, len); 59590926Snectar signal(SIGINT, osig); 59690926Snectar return 0; 59755682Smarkm} 59872445Sassar 59972445Sassar/* 60072445Sassar * return [0, 16) or -1 60172445Sassar */ 60272445Sassar 60372445Sassarstatic int 60472445Sassarhex2n (char c) 60572445Sassar{ 60672445Sassar static char hexdigits[] = "0123456789abcdef"; 60772445Sassar const char *p; 60872445Sassar 609120945Snectar p = strchr (hexdigits, tolower((unsigned char)c)); 61072445Sassar if (p == NULL) 61172445Sassar return -1; 61272445Sassar else 61372445Sassar return p - hexdigits; 61472445Sassar} 61572445Sassar 61672445Sassar/* 61772445Sassar * convert a key in a readable format into a keyblock. 61872445Sassar * return 0 iff succesful, otherwise `err' should point to an error message 61972445Sassar */ 62072445Sassar 62172445Sassarint 62272445Sassarparse_des_key (const char *key_string, krb5_key_data *key_data, 623178825Sdfr const char **error) 62472445Sassar{ 62572445Sassar const char *p = key_string; 62672445Sassar unsigned char bits[8]; 62772445Sassar int i; 62872445Sassar 62972445Sassar if (strlen (key_string) != 16) { 630178825Sdfr *error = "bad length, should be 16 for DES key"; 63172445Sassar return 1; 63272445Sassar } 63372445Sassar for (i = 0; i < 8; ++i) { 63472445Sassar int d1, d2; 63572445Sassar 63672445Sassar d1 = hex2n(p[2 * i]); 63772445Sassar d2 = hex2n(p[2 * i + 1]); 63872445Sassar if (d1 < 0 || d2 < 0) { 639178825Sdfr *error = "non-hex character"; 64072445Sassar return 1; 64172445Sassar } 64272445Sassar bits[i] = (d1 << 4) | d2; 64372445Sassar } 64472445Sassar for (i = 0; i < 3; ++i) { 64572445Sassar key_data[i].key_data_ver = 2; 64672445Sassar key_data[i].key_data_kvno = 0; 64772445Sassar /* key */ 64872445Sassar key_data[i].key_data_type[0] = ETYPE_DES_CBC_CRC; 64972445Sassar key_data[i].key_data_length[0] = 8; 65072445Sassar key_data[i].key_data_contents[0] = malloc(8); 651178825Sdfr if (key_data[i].key_data_contents[0] == NULL) { 652178825Sdfr *error = "malloc"; 653178825Sdfr return ENOMEM; 654178825Sdfr } 65572445Sassar memcpy (key_data[i].key_data_contents[0], bits, 8); 65672445Sassar /* salt */ 65772445Sassar key_data[i].key_data_type[1] = KRB5_PW_SALT; 65872445Sassar key_data[i].key_data_length[1] = 0; 65972445Sassar key_data[i].key_data_contents[1] = NULL; 66072445Sassar } 66172445Sassar key_data[0].key_data_type[0] = ETYPE_DES_CBC_MD5; 66272445Sassar key_data[1].key_data_type[0] = ETYPE_DES_CBC_MD4; 66372445Sassar return 0; 66472445Sassar} 665