/ admin / add.c
add.c
  1  /*
  2   * Copyright (c) 1997-2005 Kungliga Tekniska Högskolan
  3   * (Royal Institute of Technology, Stockholm, Sweden).
  4   * All rights reserved.
  5   *
  6   * Redistribution and use in source and binary forms, with or without
  7   * modification, are permitted provided that the following conditions
  8   * are met:
  9   *
 10   * 1. Redistributions of source code must retain the above copyright
 11   *    notice, this list of conditions and the following disclaimer.
 12   *
 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.
 16   *
 17   * 3. Neither the name of the Institute nor the names of its contributors
 18   *    may be used to endorse or promote products derived from this software
 19   *    without specific prior written permission.
 20   *
 21   * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
 22   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 23   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 24   * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
 25   * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 26   * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 27   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 28   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 29   * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 30   * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 31   * SUCH DAMAGE.
 32   */
 33  
 34  #include "ktutil_locl.h"
 35  
 36  RCSID("$Id$");
 37  
 38  static char *
 39  readstring(const char *prompt, char *buf, size_t len)
 40  {
 41      printf("%s", prompt);
 42      if (fgets(buf, (int)len, stdin) == NULL)
 43  	return NULL;
 44      buf[strcspn(buf, "\r\n")] = '\0';
 45      return buf;
 46  }
 47  
 48  int
 49  kt_add(struct add_options *opt, int argc, char **argv)
 50  {
 51      krb5_error_code ret;
 52      krb5_keytab keytab;
 53      krb5_keytab_entry entry;
 54      char buf[1024];
 55      krb5_enctype enctype;
 56  
 57      if((keytab = ktutil_open_keytab()) == NULL)
 58  	return 1;
 59  
 60      memset(&entry, 0, sizeof(entry));
 61      if(opt->principal_string == NULL) {
 62  	if(readstring("Principal: ", buf, sizeof(buf)) == NULL)
 63  	    return 1;
 64  	opt->principal_string = buf;
 65      }
 66      ret = krb5_parse_name(context, opt->principal_string, &entry.principal);
 67      if(ret) {
 68  	krb5_warn(context, ret, "%s", opt->principal_string);
 69  	goto out;
 70      }
 71      if(opt->enctype_string == NULL) {
 72  	if(readstring("Encryption type: ", buf, sizeof(buf)) == NULL) {
 73  	    ret = 1;
 74  	    goto out;
 75  	}
 76  	opt->enctype_string = buf;
 77      }
 78      ret = krb5_string_to_enctype(context, opt->enctype_string, &enctype);
 79      if(ret) {
 80  	int t;
 81  	if(sscanf(opt->enctype_string, "%d", &t) == 1)
 82  	    enctype = t;
 83  	else {
 84  	    krb5_warn(context, ret, "%s", opt->enctype_string);
 85  	    goto out;
 86  	}
 87      }
 88      if(opt->kvno_integer == -1) {
 89  	if(readstring("Key version: ", buf, sizeof(buf)) == NULL) {
 90  	    ret = 1;
 91  	    goto out;
 92  	}
 93  	if(sscanf(buf, "%u", &opt->kvno_integer) != 1)
 94  	    goto out;
 95      }
 96      if (opt->pw_file_string) {
 97  	FILE *f;
 98  
 99  	if (strcasecmp("STDIN", opt->pw_file_string) == 0)
100  	    f = stdin;
101  	else
102  	    f = fopen(opt->pw_file_string, "r");
103  	if (f == NULL)
104  	    krb5_errx(context, 1, "Failed to open the password file %s",
105  		      opt->pw_file_string);
106  	
107  	if (fgets(buf, sizeof(buf), f) == NULL)
108  	    krb5_errx(context, 1,
109  		      "Failed to read password from file %s",
110  		      opt->pw_file_string);
111  	if (f != stdin)
112  	    fclose(f);
113  	buf[strcspn(buf, "\n")] = '\0';
114  
115  	opt->password_string = buf;
116      }
117      if(opt->password_string == NULL && opt->random_flag == 0) {
118  	if(UI_UTIL_read_pw_string(buf, sizeof(buf), "Password: ", 1)) {
119  	    ret = 1;
120  	    goto out;
121  	}
122  	opt->password_string = buf;
123      }
124      if(opt->password_string) {
125  	if (opt->hex_flag) {
126  	    size_t len;
127  	    void *data;
128  
129  	    len = (strlen(opt->password_string) + 1) / 2;
130  
131  	    data = malloc(len);
132  	    if (data == NULL) {
133  		krb5_warn(context, ENOMEM, "malloc");
134  		goto out;
135  	    }
136  
137  	    if ((size_t)hex_decode(opt->password_string, data, len) != len) {
138  		free(data);
139  		krb5_warn(context, ENOMEM, "hex decode failed");
140  		goto out;
141  	    }
142  
143  	    ret = krb5_keyblock_init(context, enctype,
144  				     data, len, &entry.keyblock);
145  	    free(data);
146  	} else if (!opt->salt_flag) {
147  	    krb5_salt salt;
148  	    krb5_data pw;
149  
150  	    salt.salttype         = KRB5_PW_SALT;
151  	    salt.saltvalue.data   = NULL;
152  	    salt.saltvalue.length = 0;
153  	    pw.data = (void*)opt->password_string;
154  	    pw.length = strlen(opt->password_string);
155  	    ret = krb5_string_to_key_data_salt(context, enctype, pw, salt,
156  					       &entry.keyblock);
157          } else {
158  	    ret = krb5_string_to_key(context, enctype, opt->password_string,
159  				     entry.principal, &entry.keyblock);
160  	}
161  	memset (opt->password_string, 0, strlen(opt->password_string));
162      } else {
163  	ret = krb5_generate_random_keyblock(context, enctype, &entry.keyblock);
164      }
165      if(ret) {
166  	krb5_warn(context, ret, "add");
167  	goto out;
168      }
169      entry.vno = opt->kvno_integer;
170      entry.timestamp = (uint32_t)time (NULL);
171      ret = krb5_kt_add_entry(context, keytab, &entry);
172      if(ret)
173  	krb5_warn(context, ret, "add");
174   out:
175      krb5_kt_free_entry(context, &entry);
176      krb5_kt_close(context, keytab);
177      return ret != 0;
178  }