316c2f02ebaa4f2b7ab842d54bc5f152b315dc81
[jelmer/samba4-debian.git] / source / heimdal / lib / krb5 / init_creds.c
1 /*
2  * Copyright (c) 1997 - 2004 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 "krb5_locl.h"
35
36 RCSID("$Id: init_creds.c,v 1.22 2006/02/03 11:42:31 lha Exp $");
37
38 void KRB5_LIB_FUNCTION
39 krb5_get_init_creds_opt_init(krb5_get_init_creds_opt *opt)
40 {
41     memset (opt, 0, sizeof(*opt));
42     opt->flags = 0;
43     opt->opt_private = NULL;
44 }
45
46 krb5_error_code KRB5_LIB_FUNCTION
47 krb5_get_init_creds_opt_alloc(krb5_context context, 
48                               krb5_get_init_creds_opt **opt)
49 {
50     krb5_get_init_creds_opt *o;
51     
52     *opt = NULL;
53     o = calloc(1, sizeof(*o));
54     if (o == NULL) {
55         krb5_set_error_string(context, "out of memory");
56         return ENOMEM;
57     }
58     krb5_get_init_creds_opt_init(o);
59     o->opt_private = calloc(1, sizeof(*o->opt_private));
60     if (o->opt_private == NULL) {
61         krb5_set_error_string(context, "out of memory");
62         free(o);
63         return ENOMEM;
64     }
65     o->opt_private->refcount = 1;
66     *opt = o;
67     return 0;
68 }
69
70 krb5_error_code
71 _krb5_get_init_creds_opt_copy(krb5_context context, 
72                               const krb5_get_init_creds_opt *in,
73                               krb5_get_init_creds_opt **out)
74 {
75     krb5_get_init_creds_opt *opt;
76
77     *out = NULL;
78     opt = malloc(sizeof(*opt));
79     if (opt == NULL) {
80         krb5_set_error_string(context, "out of memory");
81         return ENOMEM;
82     }
83     if (in)
84         *opt = *in;
85     if(opt->opt_private == NULL) {
86         opt->opt_private = calloc(1, sizeof(*opt->opt_private));
87         if (opt->opt_private == NULL) {
88             krb5_set_error_string(context, "out of memory");
89             free(opt);
90             return ENOMEM;
91         }
92         opt->opt_private->refcount = 1;
93     } else
94         opt->opt_private->refcount++;
95     *out = opt;
96     return 0;
97 }
98
99 void KRB5_LIB_FUNCTION
100 krb5_get_init_creds_opt_free(krb5_get_init_creds_opt *opt)
101 {
102     if (opt->opt_private == NULL)
103         return;
104     if (opt->opt_private->refcount < 1) /* abort ? */
105         return;
106     if (--opt->opt_private->refcount == 0) {
107         _krb5_get_init_creds_opt_free_pkinit(opt);
108         free(opt->opt_private);
109     }
110     memset(opt, 0, sizeof(*opt));
111     free(opt);
112 }
113
114 static int
115 get_config_time (krb5_context context,
116                  const char *realm,
117                  const char *name,
118                  int def)
119 {
120     int ret;
121
122     ret = krb5_config_get_time (context, NULL,
123                                 "realms",
124                                 realm,
125                                 name,
126                                 NULL);
127     if (ret >= 0)
128         return ret;
129     ret = krb5_config_get_time (context, NULL,
130                                 "libdefaults",
131                                 name,
132                                 NULL);
133     if (ret >= 0)
134         return ret;
135     return def;
136 }
137
138 static krb5_boolean
139 get_config_bool (krb5_context context,
140                  const char *realm,
141                  const char *name)
142 {
143     return krb5_config_get_bool (context,
144                                  NULL,
145                                  "realms",
146                                  realm,
147                                  name,
148                                  NULL)
149         || krb5_config_get_bool (context,
150                                  NULL,
151                                  "libdefaults",
152                                  name,
153                                  NULL);
154 }
155
156 /*
157  * set all the values in `opt' to the appropriate values for
158  * application `appname' (default to getprogname() if NULL), and realm
159  * `realm'.  First looks in [appdefaults] but falls back to
160  * [realms] or [libdefaults] for some of the values.
161  */
162
163 static krb5_addresses no_addrs = {0, NULL};
164
165 void KRB5_LIB_FUNCTION
166 krb5_get_init_creds_opt_set_default_flags(krb5_context context,
167                                           const char *appname,
168                                           krb5_const_realm realm,
169                                           krb5_get_init_creds_opt *opt)
170 {
171     krb5_boolean b;
172     time_t t;
173
174     b = get_config_bool (context, realm, "forwardable");
175     krb5_appdefault_boolean(context, appname, realm, "forwardable", b, &b);
176     krb5_get_init_creds_opt_set_forwardable(opt, b);
177
178     b = get_config_bool (context, realm, "proxiable");
179     krb5_appdefault_boolean(context, appname, realm, "proxiable", b, &b);
180     krb5_get_init_creds_opt_set_proxiable (opt, b);
181
182     krb5_appdefault_time(context, appname, realm, "ticket_lifetime", 0, &t);
183     if (t == 0)
184         t = get_config_time (context, realm, "ticket_lifetime", 0);
185     if(t != 0)
186         krb5_get_init_creds_opt_set_tkt_life(opt, t);
187
188     krb5_appdefault_time(context, appname, realm, "renew_lifetime", 0, &t);
189     if (t == 0)
190         t = get_config_time (context, realm, "renew_lifetime", 0);
191     if(t != 0)
192         krb5_get_init_creds_opt_set_renew_life(opt, t);
193
194     krb5_appdefault_boolean(context, appname, realm, "no-addresses", 
195                             KRB5_ADDRESSLESS_DEFAULT, &b);
196     if (b)
197         krb5_get_init_creds_opt_set_address_list (opt, &no_addrs);
198
199 #if 0
200     krb5_appdefault_boolean(context, appname, realm, "anonymous", FALSE, &b);
201     krb5_get_init_creds_opt_set_anonymous (opt, b);
202
203     krb5_get_init_creds_opt_set_etype_list(opt, enctype,
204                                            etype_str.num_strings);
205
206     krb5_get_init_creds_opt_set_salt(krb5_get_init_creds_opt *opt,
207                                      krb5_data *salt);
208
209     krb5_get_init_creds_opt_set_preauth_list(krb5_get_init_creds_opt *opt,
210                                              krb5_preauthtype *preauth_list,
211                                              int preauth_list_length);
212 #endif
213 }
214
215
216 void KRB5_LIB_FUNCTION
217 krb5_get_init_creds_opt_set_tkt_life(krb5_get_init_creds_opt *opt,
218                                      krb5_deltat tkt_life)
219 {
220     opt->flags |= KRB5_GET_INIT_CREDS_OPT_TKT_LIFE;
221     opt->tkt_life = tkt_life;
222 }
223
224 void KRB5_LIB_FUNCTION
225 krb5_get_init_creds_opt_set_renew_life(krb5_get_init_creds_opt *opt,
226                                        krb5_deltat renew_life)
227 {
228     opt->flags |= KRB5_GET_INIT_CREDS_OPT_RENEW_LIFE;
229     opt->renew_life = renew_life;
230 }
231
232 void KRB5_LIB_FUNCTION
233 krb5_get_init_creds_opt_set_forwardable(krb5_get_init_creds_opt *opt,
234                                         int forwardable)
235 {
236     opt->flags |= KRB5_GET_INIT_CREDS_OPT_FORWARDABLE;
237     opt->forwardable = forwardable;
238 }
239
240 void KRB5_LIB_FUNCTION
241 krb5_get_init_creds_opt_set_proxiable(krb5_get_init_creds_opt *opt,
242                                       int proxiable)
243 {
244     opt->flags |= KRB5_GET_INIT_CREDS_OPT_PROXIABLE;
245     opt->proxiable = proxiable;
246 }
247
248 void KRB5_LIB_FUNCTION
249 krb5_get_init_creds_opt_set_etype_list(krb5_get_init_creds_opt *opt,
250                                        krb5_enctype *etype_list,
251                                        int etype_list_length)
252 {
253     opt->flags |= KRB5_GET_INIT_CREDS_OPT_ETYPE_LIST;
254     opt->etype_list = etype_list;
255     opt->etype_list_length = etype_list_length;
256 }
257
258 void KRB5_LIB_FUNCTION
259 krb5_get_init_creds_opt_set_address_list(krb5_get_init_creds_opt *opt,
260                                          krb5_addresses *addresses)
261 {
262     opt->flags |= KRB5_GET_INIT_CREDS_OPT_ADDRESS_LIST;
263     opt->address_list = addresses;
264 }
265
266 void KRB5_LIB_FUNCTION
267 krb5_get_init_creds_opt_set_preauth_list(krb5_get_init_creds_opt *opt,
268                                          krb5_preauthtype *preauth_list,
269                                          int preauth_list_length)
270 {
271     opt->flags |= KRB5_GET_INIT_CREDS_OPT_PREAUTH_LIST;
272     opt->preauth_list_length = preauth_list_length;
273     opt->preauth_list = preauth_list;
274 }
275
276 void KRB5_LIB_FUNCTION
277 krb5_get_init_creds_opt_set_salt(krb5_get_init_creds_opt *opt,
278                                  krb5_data *salt)
279 {
280     opt->flags |= KRB5_GET_INIT_CREDS_OPT_SALT;
281     opt->salt = salt;
282 }
283
284 void KRB5_LIB_FUNCTION
285 krb5_get_init_creds_opt_set_anonymous(krb5_get_init_creds_opt *opt,
286                                       int anonymous)
287 {
288     opt->flags |= KRB5_GET_INIT_CREDS_OPT_ANONYMOUS;
289     opt->anonymous = anonymous;
290 }
291
292 static krb5_error_code
293 require_ext_opt(krb5_context context,
294                 krb5_get_init_creds_opt *opt,
295                 const char *type)
296 {
297     if (opt->opt_private == NULL) {
298         krb5_set_error_string(context, "%s on non extendable opt", type);
299         return EINVAL;
300     }
301     return 0;
302 }
303
304 krb5_error_code KRB5_LIB_FUNCTION
305 krb5_get_init_creds_opt_set_pa_password(krb5_context context,
306                                         krb5_get_init_creds_opt *opt,
307                                         const char *password,
308                                         krb5_s2k_proc key_proc)
309 {
310     krb5_error_code ret;
311     ret = require_ext_opt(context, opt, "init_creds_opt_set_pa_password");
312     if (ret)
313         return ret;
314     opt->opt_private->password = password;
315     opt->opt_private->key_proc = key_proc;
316     return 0;
317 }
318
319 krb5_error_code KRB5_LIB_FUNCTION
320 krb5_get_init_creds_opt_set_pac_request(krb5_context context,
321                                         krb5_get_init_creds_opt *opt,
322                                         krb5_boolean req_pac)
323 {
324     krb5_error_code ret;
325     ret = require_ext_opt(context, opt, "init_creds_opt_set_pac_req");
326     if (ret)
327         return ret;
328     opt->opt_private->req_pac = req_pac ?
329         KRB5_PA_PAC_REQ_TRUE :
330         KRB5_PA_PAC_REQ_FALSE;
331     return 0;
332 }