1/*	$NetBSD: kerberos.c,v 1.3 2021/08/14 16:14:52 christos Exp $	*/
2
3/* $OpenLDAP$ */
4/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 *
6 * Copyright 1998-2021 The OpenLDAP Foundation.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
11 * Public License.
12 *
13 * A copy of this license is available in the file LICENSE in the
14 * top-level directory of the distribution or, alternatively, at
15 * <http://www.OpenLDAP.org/license.html>.
16 */
17
18#include <sys/cdefs.h>
19__RCSID("$NetBSD: kerberos.c,v 1.3 2021/08/14 16:14:52 christos Exp $");
20
21#include "portable.h"
22
23#include <unistd.h>
24
25#include <lber.h>
26#include <lber_pvt.h>	/* BER_BVC definition */
27#include "lutil.h"
28#include <ac/string.h>
29
30#ifdef HAVE_KRB5
31#include <krb5.h>
32#elif defined(HAVE_KRB4)
33#include <krb.h>
34#endif
35
36/* From <ldap_pvt.h> */
37LDAP_F( char *) ldap_pvt_get_fqdn LDAP_P(( char * ));
38
39static LUTIL_PASSWD_CHK_FUNC chk_kerberos;
40static const struct berval scheme = BER_BVC("{KERBEROS}");
41
42static int chk_kerberos(
43	const struct berval *sc,
44	const struct berval * passwd,
45	const struct berval * cred,
46	const char **text )
47{
48	unsigned int i;
49	int rtn;
50
51	for( i=0; i<cred->bv_len; i++) {
52		if(cred->bv_val[i] == '\0') {
53			return LUTIL_PASSWD_ERR;	/* NUL character in password */
54		}
55	}
56
57	if( cred->bv_val[i] != '\0' ) {
58		return LUTIL_PASSWD_ERR;	/* cred must behave like a string */
59	}
60
61	for( i=0; i<passwd->bv_len; i++) {
62		if(passwd->bv_val[i] == '\0') {
63			return LUTIL_PASSWD_ERR;	/* NUL character in password */
64		}
65	}
66
67	if( passwd->bv_val[i] != '\0' ) {
68		return LUTIL_PASSWD_ERR;	/* passwd must behave like a string */
69	}
70
71	rtn = LUTIL_PASSWD_ERR;
72
73#ifdef HAVE_KRB5 /* HAVE_HEIMDAL_KRB5 */
74	{
75/* Portions:
76 * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska H\xf6gskolan
77 * (Royal Institute of Technology, Stockholm, Sweden).
78 * All rights reserved.
79 *
80 * Redistribution and use in source and binary forms, with or without
81 * modification, are permitted provided that the following conditions
82 * are met:
83 *
84 * 1. Redistributions of source code must retain the above copyright
85 *    notice, this list of conditions and the following disclaimer.
86 *
87 * 2. Redistributions in binary form must reproduce the above copyright
88 *    notice, this list of conditions and the following disclaimer in the
89 *    documentation and/or other materials provided with the distribution.
90 *
91 * 3. Neither the name of the Institute nor the names of its contributors
92 *    may be used to endorse or promote products derived from this software
93 *    without specific prior written permission.
94 *
95 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
96 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
97 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
98 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
99 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
100 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
101 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
102 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
103 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
104 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
105 * SUCH DAMAGE.
106 */
107
108		krb5_context context;
109   		krb5_error_code ret;
110   		krb5_creds creds;
111   		krb5_get_init_creds_opt get_options;
112   		krb5_verify_init_creds_opt verify_options;
113		krb5_principal client, server;
114#ifdef notdef
115		krb5_preauthtype pre_auth_types[] = {KRB5_PADATA_ENC_TIMESTAMP};
116#endif
117
118		ret = krb5_init_context( &context );
119		if (ret) {
120			return LUTIL_PASSWD_ERR;
121		}
122
123#ifdef notdef
124		krb5_get_init_creds_opt_set_preauth_list(&get_options,
125			pre_auth_types, 1);
126#endif
127
128   		krb5_get_init_creds_opt_init( &get_options );
129
130		krb5_verify_init_creds_opt_init( &verify_options );
131
132		ret = krb5_parse_name( context, passwd->bv_val, &client );
133
134		if (ret) {
135			krb5_free_context( context );
136			return LUTIL_PASSWD_ERR;
137		}
138
139		ret = krb5_get_init_creds_password( context,
140			&creds, client, cred->bv_val, NULL,
141			NULL, 0, NULL, &get_options );
142
143		if (ret) {
144			krb5_free_principal( context, client );
145			krb5_free_context( context );
146			return LUTIL_PASSWD_ERR;
147		}
148
149		{
150			char *host = ldap_pvt_get_fqdn( NULL );
151
152			if( host == NULL ) {
153				krb5_free_principal( context, client );
154				krb5_free_context( context );
155				return LUTIL_PASSWD_ERR;
156			}
157
158			ret = krb5_sname_to_principal( context,
159				host, "ldap", KRB5_NT_SRV_HST, &server );
160
161			ber_memfree( host );
162		}
163
164		if (ret) {
165			krb5_free_principal( context, client );
166			krb5_free_context( context );
167			return LUTIL_PASSWD_ERR;
168		}
169
170		ret = krb5_verify_init_creds( context,
171			&creds, server, NULL, NULL, &verify_options );
172
173		krb5_free_principal( context, client );
174		krb5_free_principal( context, server );
175		krb5_free_cred_contents( context, &creds );
176		krb5_free_context( context );
177
178		rtn = ret ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
179	}
180#elif	defined(HAVE_KRB4)
181	{
182		/* Borrowed from Heimdal kpopper */
183/* Portions:
184 * Copyright (c) 1989 Regents of the University of California.
185 * All rights reserved.  The Berkeley software License Agreement
186 * specifies the terms and conditions for redistribution.
187 */
188
189		int status;
190		char lrealm[REALM_SZ];
191		char tkt[MAXHOSTNAMELEN];
192
193		status = krb_get_lrealm(lrealm,1);
194		if (status == KFAILURE) {
195			return LUTIL_PASSWD_ERR;
196		}
197
198		snprintf(tkt, sizeof(tkt), "%s_slapd.%u",
199			TKT_ROOT, (unsigned)getpid());
200		krb_set_tkt_string (tkt);
201
202		status = krb_verify_user( passwd->bv_val, "", lrealm,
203			cred->bv_val, 1, "ldap");
204
205		dest_tkt(); /* no point in keeping the tickets */
206
207		return status == KFAILURE ? LUTIL_PASSWD_ERR : LUTIL_PASSWD_OK;
208	}
209#endif
210
211	return rtn;
212}
213
214int init_module(int argc, char *argv[]) {
215	return lutil_passwd_add( (struct berval *)&scheme, chk_kerberos, NULL );
216}
217