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"
35178825Sdfr#include "kadmin-commands.h"
3655682Smarkm
37178825SdfrRCSID("$Id: mod.c 21968 2007-10-18 18:50:33Z lha $");
3855682Smarkm
39178825Sdfrstatic void
40178825Sdfradd_tl(kadm5_principal_ent_rec *princ, int type, krb5_data *data)
4155682Smarkm{
42178825Sdfr    krb5_tl_data *tl, **ptl;
4355682Smarkm
44178825Sdfr    tl = ecalloc(1, sizeof(*tl));
45178825Sdfr    tl->tl_data_next = NULL;
46178825Sdfr    tl->tl_data_type = KRB5_TL_EXTENSION;
47178825Sdfr    tl->tl_data_length = data->length;
48178825Sdfr    tl->tl_data_contents = data->data;
49178825Sdfr
50178825Sdfr    princ->n_tl_data++;
51178825Sdfr    ptl = &princ->tl_data;
52178825Sdfr    while (*ptl != NULL)
53178825Sdfr	ptl = &(*ptl)->tl_data_next;
54178825Sdfr    *ptl = tl;
5555682Smarkm
56178825Sdfr    return;
57178825Sdfr}
5855682Smarkm
59178825Sdfrstatic void
60178825Sdfradd_constrained_delegation(krb5_context context,
61178825Sdfr			   kadm5_principal_ent_rec *princ,
62178825Sdfr			   struct getarg_strings *strings)
63178825Sdfr{
64178825Sdfr    krb5_error_code ret;
65178825Sdfr    HDB_extension ext;
66178825Sdfr    krb5_data buf;
67178825Sdfr    size_t size;
68178825Sdfr
69178825Sdfr    memset(&ext, 0, sizeof(ext));
70178825Sdfr    ext.mandatory = FALSE;
71178825Sdfr    ext.data.element = choice_HDB_extension_data_allowed_to_delegate_to;
7255682Smarkm
73178825Sdfr    if (strings->num_strings == 1 && strings->strings[0][0] == '\0') {
74178825Sdfr	ext.data.u.allowed_to_delegate_to.val = NULL;
75178825Sdfr	ext.data.u.allowed_to_delegate_to.len = 0;
76178825Sdfr    } else {
77178825Sdfr	krb5_principal p;
78178825Sdfr	int i;
79178825Sdfr
80178825Sdfr	ext.data.u.allowed_to_delegate_to.val =
81178825Sdfr	    calloc(strings->num_strings,
82178825Sdfr		   sizeof(ext.data.u.allowed_to_delegate_to.val[0]));
83178825Sdfr	ext.data.u.allowed_to_delegate_to.len = strings->num_strings;
84178825Sdfr
85178825Sdfr	for (i = 0; i < strings->num_strings; i++) {
86178825Sdfr	    ret = krb5_parse_name(context, strings->strings[i], &p);
87178825Sdfr	    ret = copy_Principal(p, &ext.data.u.allowed_to_delegate_to.val[i]);
88178825Sdfr	    krb5_free_principal(context, p);
89178825Sdfr	}
9055682Smarkm    }
91178825Sdfr
92178825Sdfr    ASN1_MALLOC_ENCODE(HDB_extension, buf.data, buf.length,
93178825Sdfr		       &ext, &size, ret);
94178825Sdfr    free_HDB_extension(&ext);
9555682Smarkm    if (ret)
96178825Sdfr	abort();
97178825Sdfr    if (buf.length != size)
98178825Sdfr	abort();
9972445Sassar
100178825Sdfr    add_tl(princ, KRB5_TL_EXTENSION, &buf);
10155682Smarkm}
10255682Smarkm
103178825Sdfrstatic void
104178825Sdfradd_aliases(krb5_context context, kadm5_principal_ent_rec *princ,
105178825Sdfr	    struct getarg_strings *strings)
10655682Smarkm{
10755682Smarkm    krb5_error_code ret;
108178825Sdfr    HDB_extension ext;
109178825Sdfr    krb5_data buf;
110178825Sdfr    krb5_principal p;
111178825Sdfr    size_t size;
112178825Sdfr    int i;
113178825Sdfr
114178825Sdfr    memset(&ext, 0, sizeof(ext));
115178825Sdfr    ext.mandatory = FALSE;
116178825Sdfr    ext.data.element = choice_HDB_extension_data_aliases;
117178825Sdfr    ext.data.u.aliases.case_insensitive = 0;
11855682Smarkm
119178825Sdfr    if (strings->num_strings == 1 && strings->strings[0][0] == '\0') {
120178825Sdfr	ext.data.u.aliases.aliases.val = NULL;
121178825Sdfr	ext.data.u.aliases.aliases.len = 0;
122178825Sdfr    } else {
123178825Sdfr	ext.data.u.aliases.aliases.val =
124178825Sdfr	    calloc(strings->num_strings,
125178825Sdfr		   sizeof(ext.data.u.aliases.aliases.val[0]));
126178825Sdfr	ext.data.u.aliases.aliases.len = strings->num_strings;
127178825Sdfr
128178825Sdfr	for (i = 0; i < strings->num_strings; i++) {
129178825Sdfr	    ret = krb5_parse_name(context, strings->strings[i], &p);
130178825Sdfr	    ret = copy_Principal(p, &ext.data.u.aliases.aliases.val[i]);
131178825Sdfr	    krb5_free_principal(context, p);
132178825Sdfr	}
133178825Sdfr    }
13455682Smarkm
135178825Sdfr    ASN1_MALLOC_ENCODE(HDB_extension, buf.data, buf.length,
136178825Sdfr		       &ext, &size, ret);
137178825Sdfr    free_HDB_extension(&ext);
13855682Smarkm    if (ret)
139178825Sdfr	abort();
140178825Sdfr    if (buf.length != size)
141178825Sdfr	abort();
142178825Sdfr
143178825Sdfr    add_tl(princ, KRB5_TL_EXTENSION, &buf);
144178825Sdfr}
14555682Smarkm
146178825Sdfrstatic void
147178825Sdfradd_pkinit_acl(krb5_context context, kadm5_principal_ent_rec *princ,
148178825Sdfr	       struct getarg_strings *strings)
149178825Sdfr{
150178825Sdfr    krb5_error_code ret;
151178825Sdfr    HDB_extension ext;
152178825Sdfr    krb5_data buf;
153178825Sdfr    size_t size;
154178825Sdfr    int i;
15555682Smarkm
156178825Sdfr    memset(&ext, 0, sizeof(ext));
157178825Sdfr    ext.mandatory = FALSE;
158178825Sdfr    ext.data.element = choice_HDB_extension_data_pkinit_acl;
159178825Sdfr    ext.data.u.aliases.case_insensitive = 0;
160178825Sdfr
161178825Sdfr    if (strings->num_strings == 1 && strings->strings[0][0] == '\0') {
162178825Sdfr	ext.data.u.pkinit_acl.val = NULL;
163178825Sdfr	ext.data.u.pkinit_acl.len = 0;
164178825Sdfr    } else {
165178825Sdfr	ext.data.u.pkinit_acl.val =
166178825Sdfr	    calloc(strings->num_strings,
167178825Sdfr		   sizeof(ext.data.u.pkinit_acl.val[0]));
168178825Sdfr	ext.data.u.pkinit_acl.len = strings->num_strings;
169178825Sdfr
170178825Sdfr	for (i = 0; i < strings->num_strings; i++) {
171178825Sdfr	    ext.data.u.pkinit_acl.val[i].subject = estrdup(strings->strings[i]);
172178825Sdfr	}
17355682Smarkm    }
17455682Smarkm
175178825Sdfr    ASN1_MALLOC_ENCODE(HDB_extension, buf.data, buf.length,
176178825Sdfr		       &ext, &size, ret);
177178825Sdfr    free_HDB_extension(&ext);
178178825Sdfr    if (ret)
179178825Sdfr	abort();
180178825Sdfr    if (buf.length != size)
181178825Sdfr	abort();
182178825Sdfr
183178825Sdfr    add_tl(princ, KRB5_TL_EXTENSION, &buf);
184178825Sdfr}
18555682Smarkm
186178825Sdfrstatic int
187178825Sdfrdo_mod_entry(krb5_principal principal, void *data)
188178825Sdfr{
189178825Sdfr    krb5_error_code ret;
190178825Sdfr    kadm5_principal_ent_rec princ;
191178825Sdfr    int mask = 0;
192178825Sdfr    struct modify_options *e = data;
193178825Sdfr
194178825Sdfr    memset (&princ, 0, sizeof(princ));
195178825Sdfr    ret = kadm5_get_principal(kadm_handle, principal, &princ,
196178825Sdfr			      KADM5_PRINCIPAL | KADM5_ATTRIBUTES |
197178825Sdfr			      KADM5_MAX_LIFE | KADM5_MAX_RLIFE |
198178825Sdfr			      KADM5_PRINC_EXPIRE_TIME |
199178825Sdfr			      KADM5_PW_EXPIRATION);
200178825Sdfr    if(ret)
201178825Sdfr	return ret;
202178825Sdfr
203178825Sdfr    if(e->max_ticket_life_string ||
204178825Sdfr       e->max_renewable_life_string ||
205178825Sdfr       e->expiration_time_string ||
206178825Sdfr       e->pw_expiration_time_string ||
207178825Sdfr       e->attributes_string ||
208178825Sdfr       e->kvno_integer != -1 ||
209178825Sdfr       e->constrained_delegation_strings.num_strings ||
210178825Sdfr       e->alias_strings.num_strings ||
211178825Sdfr       e->pkinit_acl_strings.num_strings) {
212178825Sdfr	ret = set_entry(context, &princ, &mask,
213178825Sdfr			e->max_ticket_life_string,
214178825Sdfr			e->max_renewable_life_string,
215178825Sdfr			e->expiration_time_string,
216178825Sdfr			e->pw_expiration_time_string,
217178825Sdfr			e->attributes_string);
218178825Sdfr	if(e->kvno_integer != -1) {
219178825Sdfr	    princ.kvno = e->kvno_integer;
220178825Sdfr	    mask |= KADM5_KVNO;
22155682Smarkm	}
222178825Sdfr	if (e->constrained_delegation_strings.num_strings) {
223178825Sdfr	    add_constrained_delegation(context, &princ,
224178825Sdfr				       &e->constrained_delegation_strings);
225178825Sdfr	    mask |= KADM5_TL_DATA;
226178825Sdfr	}
227178825Sdfr	if (e->alias_strings.num_strings) {
228178825Sdfr	    add_aliases(context, &princ, &e->alias_strings);
229178825Sdfr	    mask |= KADM5_TL_DATA;
230178825Sdfr	}
231178825Sdfr	if (e->pkinit_acl_strings.num_strings) {
232178825Sdfr	    add_pkinit_acl(context, &princ, &e->pkinit_acl_strings);
233178825Sdfr	    mask |= KADM5_TL_DATA;
234178825Sdfr	}
235178825Sdfr
236178825Sdfr    } else
237178825Sdfr	ret = edit_entry(&princ, &mask, NULL, 0);
238178825Sdfr    if(ret == 0) {
239178825Sdfr	ret = kadm5_modify_principal(kadm_handle, &princ, mask);
240178825Sdfr	if(ret)
241178825Sdfr	    krb5_warn(context, ret, "kadm5_modify_principal");
24255682Smarkm    }
243178825Sdfr
24455682Smarkm    kadm5_free_principal_ent(kadm_handle, &princ);
245178825Sdfr    return ret;
24655682Smarkm}
247178825Sdfr
248178825Sdfrint
249178825Sdfrmod_entry(struct modify_options *opt, int argc, char **argv)
250178825Sdfr{
251178825Sdfr    krb5_error_code ret = 0;
252178825Sdfr    int i;
253178825Sdfr
254178825Sdfr    for(i = 0; i < argc; i++) {
255178825Sdfr	ret = foreach_principal(argv[i], do_mod_entry, "mod", opt);
256178825Sdfr	if (ret)
257178825Sdfr	    break;
258178825Sdfr    }
259178825Sdfr    return ret != 0;
260178825Sdfr}
261178825Sdfr
262