verify_user.c revision 178825
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
36RCSID("$Id: verify_user.c 19078 2006-11-20 18:12:41Z lha $");
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_cred_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 KRB5_LIB_FUNCTION
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
101int KRB5_LIB_FUNCTION
102krb5_verify_opt_alloc(krb5_context context, krb5_verify_opt **opt)
103{
104    *opt = calloc(1, sizeof(**opt));
105    if ((*opt) == NULL) {
106	krb5_set_error_string(context, "malloc: out of memory");
107	return ENOMEM;
108    }
109    krb5_verify_opt_init(*opt);
110    return 0;
111}
112
113void KRB5_LIB_FUNCTION
114krb5_verify_opt_free(krb5_verify_opt *opt)
115{
116    free(opt);
117}
118
119void KRB5_LIB_FUNCTION
120krb5_verify_opt_set_ccache(krb5_verify_opt *opt, krb5_ccache ccache)
121{
122    opt->ccache = ccache;
123}
124
125void KRB5_LIB_FUNCTION
126krb5_verify_opt_set_keytab(krb5_verify_opt *opt, krb5_keytab keytab)
127{
128    opt->keytab = keytab;
129}
130
131void KRB5_LIB_FUNCTION
132krb5_verify_opt_set_secure(krb5_verify_opt *opt, krb5_boolean secure)
133{
134    opt->secure = secure;
135}
136
137void KRB5_LIB_FUNCTION
138krb5_verify_opt_set_service(krb5_verify_opt *opt, const char *service)
139{
140    opt->service = service;
141}
142
143void KRB5_LIB_FUNCTION
144krb5_verify_opt_set_flags(krb5_verify_opt *opt, unsigned int flags)
145{
146    opt->flags |= flags;
147}
148
149static krb5_error_code
150verify_user_opt_int(krb5_context context,
151		    krb5_principal principal,
152		    const char *password,
153		    krb5_verify_opt *vopt)
154
155{
156    krb5_error_code ret;
157    krb5_get_init_creds_opt *opt;
158    krb5_creds cred;
159
160    ret = krb5_get_init_creds_opt_alloc (context, &opt);
161    if (ret)
162	return ret;
163    krb5_get_init_creds_opt_set_default_flags(context, NULL,
164					      krb5_principal_get_realm(context, principal),
165					      opt);
166    ret = krb5_get_init_creds_password (context,
167					&cred,
168					principal,
169					password,
170					krb5_prompter_posix,
171					NULL,
172					0,
173					NULL,
174					opt);
175    krb5_get_init_creds_opt_free(context, opt);
176    if(ret)
177	return ret;
178#define OPT(V, D) ((vopt && (vopt->V)) ? (vopt->V) : (D))
179    return verify_common (context, principal, OPT(ccache, NULL),
180			  OPT(keytab, NULL), vopt ? vopt->secure : TRUE,
181			  OPT(service, "host"), cred);
182#undef OPT
183}
184
185krb5_error_code KRB5_LIB_FUNCTION
186krb5_verify_user_opt(krb5_context context,
187		     krb5_principal principal,
188		     const char *password,
189		     krb5_verify_opt *opt)
190{
191    krb5_error_code ret;
192
193    if(opt && (opt->flags & KRB5_VERIFY_LREALMS)) {
194	krb5_realm *realms, *r;
195	ret = krb5_get_default_realms (context, &realms);
196	if (ret)
197	    return ret;
198	ret = KRB5_CONFIG_NODEFREALM;
199
200	for (r = realms; *r != NULL && ret != 0; ++r) {
201	    char *tmp = strdup (*r);
202
203	    if (tmp == NULL) {
204		krb5_free_host_realm (context, realms);
205		krb5_set_error_string (context, "malloc: out of memory");
206		return ENOMEM;
207	    }
208	    free (*krb5_princ_realm (context, principal));
209	    krb5_princ_set_realm (context, principal, &tmp);
210
211	    ret = verify_user_opt_int(context, principal, password, opt);
212	}
213	krb5_free_host_realm (context, realms);
214	if(ret)
215	    return ret;
216    } else
217	ret = verify_user_opt_int(context, principal, password, opt);
218    return ret;
219}
220
221/* compat function that calls above */
222
223krb5_error_code KRB5_LIB_FUNCTION
224krb5_verify_user(krb5_context context,
225		 krb5_principal principal,
226		 krb5_ccache ccache,
227		 const char *password,
228		 krb5_boolean secure,
229		 const char *service)
230{
231    krb5_verify_opt opt;
232
233    krb5_verify_opt_init(&opt);
234
235    krb5_verify_opt_set_ccache(&opt, ccache);
236    krb5_verify_opt_set_secure(&opt, secure);
237    krb5_verify_opt_set_service(&opt, service);
238
239    return krb5_verify_user_opt(context, principal, password, &opt);
240}
241
242/*
243 * A variant of `krb5_verify_user'.  The realm of `principal' is
244 * ignored and all the local realms are tried.
245 */
246
247krb5_error_code KRB5_LIB_FUNCTION
248krb5_verify_user_lrealm(krb5_context context,
249			krb5_principal principal,
250			krb5_ccache ccache,
251			const char *password,
252			krb5_boolean secure,
253			const char *service)
254{
255    krb5_verify_opt opt;
256
257    krb5_verify_opt_init(&opt);
258
259    krb5_verify_opt_set_ccache(&opt, ccache);
260    krb5_verify_opt_set_secure(&opt, secure);
261    krb5_verify_opt_set_service(&opt, service);
262    krb5_verify_opt_set_flags(&opt, KRB5_VERIFY_LREALMS);
263
264    return krb5_verify_user_opt(context, principal, password, &opt);
265}
266