verify_user.c revision 78527
1/*
2 * Copyright (c) 1997-2001 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
36RCSID("$Id: verify_user.c,v 1.14 2001/05/14 09:06:53 joda Exp $");
37
38static krb5_error_code
39verify_common (krb5_context context,
40	       krb5_principal principal,
41	       krb5_ccache ccache,
42	       krb5_keytab keytab,
43	       krb5_boolean secure,
44	       const char *service,
45	       krb5_creds cred)
46{
47    krb5_error_code ret;
48    krb5_principal server;
49    krb5_verify_init_creds_opt vopt;
50    krb5_ccache id;
51
52    ret = krb5_sname_to_principal (context, NULL, service, KRB5_NT_SRV_HST,
53				   &server);
54    if(ret)
55	return ret;
56
57    krb5_verify_init_creds_opt_init(&vopt);
58    krb5_verify_init_creds_opt_set_ap_req_nofail(&vopt, secure);
59
60    ret = krb5_verify_init_creds(context,
61				 &cred,
62				 server,
63				 keytab,
64				 NULL,
65				 &vopt);
66    krb5_free_principal(context, server);
67    if(ret)
68	return ret;
69    if(ccache == NULL)
70	ret = krb5_cc_default (context, &id);
71    else
72	id = ccache;
73    if(ret == 0){
74	ret = krb5_cc_initialize(context, id, principal);
75	if(ret == 0){
76	    ret = krb5_cc_store_cred(context, id, &cred);
77	}
78	if(ccache == NULL)
79	    krb5_cc_close(context, id);
80    }
81    krb5_free_creds_contents(context, &cred);
82    return ret;
83}
84
85/*
86 * Verify user `principal' with `password'.
87 *
88 * If `secure', also verify against local service key for `service'.
89 *
90 * As a side effect, fresh tickets are obtained and stored in `ccache'.
91 */
92
93void
94krb5_verify_opt_init(krb5_verify_opt *opt)
95{
96    memset(opt, 0, sizeof(*opt));
97    opt->secure = TRUE;
98    opt->service = "host";
99}
100
101void
102krb5_verify_opt_set_ccache(krb5_verify_opt *opt, krb5_ccache ccache)
103{
104    opt->ccache = ccache;
105}
106
107void
108krb5_verify_opt_set_keytab(krb5_verify_opt *opt, krb5_keytab keytab)
109{
110    opt->keytab = keytab;
111}
112
113void
114krb5_verify_opt_set_secure(krb5_verify_opt *opt, krb5_boolean secure)
115{
116    opt->secure = secure;
117}
118
119void
120krb5_verify_opt_set_service(krb5_verify_opt *opt, const char *service)
121{
122    opt->service = service;
123}
124
125void
126krb5_verify_opt_set_flags(krb5_verify_opt *opt, unsigned int flags)
127{
128    opt->flags |= flags;
129}
130
131static krb5_error_code
132verify_user_opt_int(krb5_context context,
133		    krb5_principal principal,
134		    const char *password,
135		    krb5_verify_opt *vopt)
136
137{
138    krb5_error_code ret;
139    krb5_get_init_creds_opt opt;
140    krb5_creds cred;
141
142    krb5_get_init_creds_opt_init (&opt);
143    krb5_get_init_creds_opt_set_default_flags(context, NULL,
144					      *krb5_princ_realm(context, principal),
145					      &opt);
146    ret = krb5_get_init_creds_password (context,
147					&cred,
148					principal,
149					(char*)password,
150					krb5_prompter_posix,
151					NULL,
152					0,
153					NULL,
154					&opt);
155    if(ret)
156	return ret;
157#define OPT(V, D) ((vopt && (vopt->V)) ? (vopt->V) : (D))
158    return verify_common (context, principal, OPT(ccache, NULL),
159			  OPT(keytab, NULL), vopt ? vopt->secure : TRUE,
160			  OPT(service, "host"), cred);
161#undef OPT
162}
163
164krb5_error_code
165krb5_verify_user_opt(krb5_context context,
166		     krb5_principal principal,
167		     const char *password,
168		     krb5_verify_opt *opt)
169{
170    krb5_error_code ret;
171
172    if(opt && (opt->flags & KRB5_VERIFY_LREALMS)) {
173	krb5_realm *realms, *r;
174	ret = krb5_get_default_realms (context, &realms);
175	if (ret)
176	    return ret;
177	ret = KRB5_CONFIG_NODEFREALM;
178
179	for (r = realms; *r != NULL && ret != 0; ++r) {
180	    char *tmp = strdup (*r);
181
182	    if (tmp == NULL) {
183		krb5_free_host_realm (context, realms);
184		krb5_set_error_string (context, "malloc: out of memory");
185		return ENOMEM;
186	    }
187	    free (*krb5_princ_realm (context, principal));
188	    krb5_princ_set_realm (context, principal, &tmp);
189
190	    ret = verify_user_opt_int(context, principal, password, opt);
191	}
192	krb5_free_host_realm (context, realms);
193	if(ret)
194	    return ret;
195    } else
196	ret = verify_user_opt_int(context, principal, password, opt);
197    return ret;
198}
199
200/* compat function that calls above */
201
202krb5_error_code
203krb5_verify_user(krb5_context context,
204		 krb5_principal principal,
205		 krb5_ccache ccache,
206		 const char *password,
207		 krb5_boolean secure,
208		 const char *service)
209{
210    krb5_verify_opt opt;
211
212    krb5_verify_opt_init(&opt);
213
214    krb5_verify_opt_set_ccache(&opt, ccache);
215    krb5_verify_opt_set_secure(&opt, secure);
216    krb5_verify_opt_set_service(&opt, service);
217
218    return krb5_verify_user_opt(context, principal, password, &opt);
219}
220
221/*
222 * A variant of `krb5_verify_user'.  The realm of `principal' is
223 * ignored and all the local realms are tried.
224 */
225
226krb5_error_code
227krb5_verify_user_lrealm(krb5_context context,
228			krb5_principal principal,
229			krb5_ccache ccache,
230			const char *password,
231			krb5_boolean secure,
232			const char *service)
233{
234    krb5_verify_opt opt;
235
236    krb5_verify_opt_init(&opt);
237
238    krb5_verify_opt_set_ccache(&opt, ccache);
239    krb5_verify_opt_set_secure(&opt, secure);
240    krb5_verify_opt_set_service(&opt, service);
241    krb5_verify_opt_set_flags(&opt, KRB5_VERIFY_LREALMS);
242
243    return krb5_verify_user_opt(context, principal, password, &opt);
244}
245