155682Smarkm/*
2178825Sdfr * Copyright (c) 1997-2005 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 "ktutil_locl.h"
3555682Smarkm
36178825SdfrRCSID("$Id: add.c 14793 2005-04-14 16:45:14Z lha $");
3755682Smarkm
38178825Sdfrstatic char *
39178825Sdfrreadstring(const char *prompt, char *buf, size_t len)
40178825Sdfr{
41178825Sdfr    printf("%s", prompt);
42178825Sdfr    if (fgets(buf, len, stdin) == NULL)
43178825Sdfr	return NULL;
44178825Sdfr    buf[strcspn(buf, "\r\n")] = '\0';
45178825Sdfr    return buf;
46178825Sdfr}
47178825Sdfr
4855682Smarkmint
49178825Sdfrkt_add(struct add_options *opt, int argc, char **argv)
5055682Smarkm{
5155682Smarkm    krb5_error_code ret;
5278527Sassar    krb5_keytab keytab;
5355682Smarkm    krb5_keytab_entry entry;
54178825Sdfr    char buf[1024];
5555682Smarkm    krb5_enctype enctype;
5655682Smarkm
5790926Snectar    if((keytab = ktutil_open_keytab()) == NULL)
5878527Sassar	return 1;
5978527Sassar
6078527Sassar    memset(&entry, 0, sizeof(entry));
61178825Sdfr    if(opt->principal_string == NULL) {
62178825Sdfr	if(readstring("Principal: ", buf, sizeof(buf)) == NULL)
6378527Sassar	    return 1;
64178825Sdfr	opt->principal_string = buf;
6555682Smarkm    }
66178825Sdfr    ret = krb5_parse_name(context, opt->principal_string, &entry.principal);
6755682Smarkm    if(ret) {
68178825Sdfr	krb5_warn(context, ret, "%s", opt->principal_string);
6978527Sassar	goto out;
7055682Smarkm    }
71178825Sdfr    if(opt->enctype_string == NULL) {
72178825Sdfr	if(readstring("Encryption type: ", buf, sizeof(buf)) == NULL) {
73178825Sdfr	    ret = 1;
7478527Sassar	    goto out;
75178825Sdfr	}
76178825Sdfr	opt->enctype_string = buf;
7755682Smarkm    }
78178825Sdfr    ret = krb5_string_to_enctype(context, opt->enctype_string, &enctype);
7955682Smarkm    if(ret) {
8055682Smarkm	int t;
81178825Sdfr	if(sscanf(opt->enctype_string, "%d", &t) == 1)
8255682Smarkm	    enctype = t;
8355682Smarkm	else {
84178825Sdfr	    krb5_warn(context, ret, "%s", opt->enctype_string);
8578527Sassar	    goto out;
8655682Smarkm	}
8755682Smarkm    }
88178825Sdfr    if(opt->kvno_integer == -1) {
89178825Sdfr	if(readstring("Key version: ", buf, sizeof(buf)) == NULL) {
90178825Sdfr	    ret = 1;
9178527Sassar	    goto out;
92178825Sdfr	}
93178825Sdfr	if(sscanf(buf, "%u", &opt->kvno_integer) != 1)
94178825Sdfr	    goto out;
9555682Smarkm    }
96178825Sdfr    if(opt->password_string == NULL && opt->random_flag == 0) {
97178825Sdfr	if(UI_UTIL_read_pw_string(buf, sizeof(buf), "Password: ", 1)) {
98178825Sdfr	    ret = 1;
9978527Sassar	    goto out;
100178825Sdfr	}
101178825Sdfr	opt->password_string = buf;
10255682Smarkm    }
103178825Sdfr    if(opt->password_string) {
104178825Sdfr	if (opt->hex_flag) {
105178825Sdfr	    size_t len;
106178825Sdfr	    void *data;
107178825Sdfr
108178825Sdfr	    len = (strlen(opt->password_string) + 1) / 2;
109178825Sdfr
110178825Sdfr	    data = malloc(len);
111178825Sdfr	    if (data == NULL) {
112178825Sdfr		krb5_warn(context, ENOMEM, "malloc");
113178825Sdfr		goto out;
114178825Sdfr	    }
115178825Sdfr
116178825Sdfr	    if (hex_decode(opt->password_string, data, len) != len) {
117178825Sdfr		free(data);
118178825Sdfr		krb5_warn(context, ENOMEM, "hex decode failed");
119178825Sdfr		goto out;
120178825Sdfr	    }
121178825Sdfr
122178825Sdfr	    ret = krb5_keyblock_init(context, enctype,
123178825Sdfr				     data, len, &entry.keyblock);
124178825Sdfr	    free(data);
125178825Sdfr	} else if (!opt->salt_flag) {
12655682Smarkm	    krb5_salt salt;
12755682Smarkm	    krb5_data pw;
12855682Smarkm
12955682Smarkm	    salt.salttype         = KRB5_PW_SALT;
13055682Smarkm	    salt.saltvalue.data   = NULL;
13155682Smarkm	    salt.saltvalue.length = 0;
132178825Sdfr	    pw.data = (void*)opt->password_string;
133178825Sdfr	    pw.length = strlen(opt->password_string);
134178825Sdfr	    ret = krb5_string_to_key_data_salt(context, enctype, pw, salt,
135178825Sdfr					       &entry.keyblock);
13655682Smarkm        } else {
137178825Sdfr	    ret = krb5_string_to_key(context, enctype, opt->password_string,
138178825Sdfr				     entry.principal, &entry.keyblock);
13955682Smarkm	}
140178825Sdfr	memset (opt->password_string, 0, strlen(opt->password_string));
14155682Smarkm    } else {
142178825Sdfr	ret = krb5_generate_random_keyblock(context, enctype, &entry.keyblock);
14355682Smarkm    }
144178825Sdfr    if(ret) {
145178825Sdfr	krb5_warn(context, ret, "add");
146178825Sdfr	goto out;
147178825Sdfr    }
148178825Sdfr    entry.vno = opt->kvno_integer;
14955682Smarkm    entry.timestamp = time (NULL);
15055682Smarkm    ret = krb5_kt_add_entry(context, keytab, &entry);
15155682Smarkm    if(ret)
15255682Smarkm	krb5_warn(context, ret, "add");
15378527Sassar out:
15455682Smarkm    krb5_kt_free_entry(context, &entry);
15578527Sassar    krb5_kt_close(context, keytab);
156178825Sdfr    return ret != 0;
15755682Smarkm}
158