xref: /minix3/crypto/external/bsd/heimdal/dist/lib/kadm5/ad.c (revision ebfedea0ce5bbe81e252ddf32d732e40fb633fae)
1*ebfedea0SLionel Sambuc /*	$NetBSD: ad.c,v 1.1.1.1 2011/04/13 18:15:29 elric Exp $	*/
2*ebfedea0SLionel Sambuc 
3*ebfedea0SLionel Sambuc /*
4*ebfedea0SLionel Sambuc  * Copyright (c) 2004 Kungliga Tekniska Högskolan
5*ebfedea0SLionel Sambuc  * (Royal Institute of Technology, Stockholm, Sweden).
6*ebfedea0SLionel Sambuc  * All rights reserved.
7*ebfedea0SLionel Sambuc  *
8*ebfedea0SLionel Sambuc  * Redistribution and use in source and binary forms, with or without
9*ebfedea0SLionel Sambuc  * modification, are permitted provided that the following conditions
10*ebfedea0SLionel Sambuc  * are met:
11*ebfedea0SLionel Sambuc  *
12*ebfedea0SLionel Sambuc  * 1. Redistributions of source code must retain the above copyright
13*ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer.
14*ebfedea0SLionel Sambuc  *
15*ebfedea0SLionel Sambuc  * 2. Redistributions in binary form must reproduce the above copyright
16*ebfedea0SLionel Sambuc  *    notice, this list of conditions and the following disclaimer in the
17*ebfedea0SLionel Sambuc  *    documentation and/or other materials provided with the distribution.
18*ebfedea0SLionel Sambuc  *
19*ebfedea0SLionel Sambuc  * 3. Neither the name of the Institute nor the names of its contributors
20*ebfedea0SLionel Sambuc  *    may be used to endorse or promote products derived from this software
21*ebfedea0SLionel Sambuc  *    without specific prior written permission.
22*ebfedea0SLionel Sambuc  *
23*ebfedea0SLionel Sambuc  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24*ebfedea0SLionel Sambuc  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25*ebfedea0SLionel Sambuc  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26*ebfedea0SLionel Sambuc  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27*ebfedea0SLionel Sambuc  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28*ebfedea0SLionel Sambuc  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29*ebfedea0SLionel Sambuc  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30*ebfedea0SLionel Sambuc  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31*ebfedea0SLionel Sambuc  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32*ebfedea0SLionel Sambuc  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33*ebfedea0SLionel Sambuc  * SUCH DAMAGE.
34*ebfedea0SLionel Sambuc  */
35*ebfedea0SLionel Sambuc 
36*ebfedea0SLionel Sambuc #define HAVE_TSASL 1
37*ebfedea0SLionel Sambuc 
38*ebfedea0SLionel Sambuc #include "kadm5_locl.h"
39*ebfedea0SLionel Sambuc #if 1
40*ebfedea0SLionel Sambuc #undef OPENLDAP
41*ebfedea0SLionel Sambuc #undef HAVE_TSASL
42*ebfedea0SLionel Sambuc #endif
43*ebfedea0SLionel Sambuc #ifdef OPENLDAP
44*ebfedea0SLionel Sambuc #include <ldap.h>
45*ebfedea0SLionel Sambuc #ifdef HAVE_TSASL
46*ebfedea0SLionel Sambuc #include <tsasl.h>
47*ebfedea0SLionel Sambuc #endif
48*ebfedea0SLionel Sambuc #include <krb5/resolve.h>
49*ebfedea0SLionel Sambuc #include <krb5/base64.h>
50*ebfedea0SLionel Sambuc #endif
51*ebfedea0SLionel Sambuc 
52*ebfedea0SLionel Sambuc __RCSID("$NetBSD: ad.c,v 1.1.1.1 2011/04/13 18:15:29 elric Exp $");
53*ebfedea0SLionel Sambuc 
54*ebfedea0SLionel Sambuc #ifdef OPENLDAP
55*ebfedea0SLionel Sambuc 
56*ebfedea0SLionel Sambuc #define CTX2LP(context) ((LDAP *)((context)->ldap_conn))
57*ebfedea0SLionel Sambuc #define CTX2BASE(context) ((context)->base_dn)
58*ebfedea0SLionel Sambuc 
59*ebfedea0SLionel Sambuc /*
60*ebfedea0SLionel Sambuc  * userAccountControl
61*ebfedea0SLionel Sambuc  */
62*ebfedea0SLionel Sambuc 
63*ebfedea0SLionel Sambuc #define UF_SCRIPT	 			0x00000001
64*ebfedea0SLionel Sambuc #define UF_ACCOUNTDISABLE			0x00000002
65*ebfedea0SLionel Sambuc #define UF_UNUSED_0	 			0x00000004
66*ebfedea0SLionel Sambuc #define UF_HOMEDIR_REQUIRED			0x00000008
67*ebfedea0SLionel Sambuc #define UF_LOCKOUT	 			0x00000010
68*ebfedea0SLionel Sambuc #define UF_PASSWD_NOTREQD 			0x00000020
69*ebfedea0SLionel Sambuc #define UF_PASSWD_CANT_CHANGE 			0x00000040
70*ebfedea0SLionel Sambuc #define UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED	0x00000080
71*ebfedea0SLionel Sambuc #define UF_TEMP_DUPLICATE_ACCOUNT       	0x00000100
72*ebfedea0SLionel Sambuc #define UF_NORMAL_ACCOUNT               	0x00000200
73*ebfedea0SLionel Sambuc #define UF_UNUSED_1	 			0x00000400
74*ebfedea0SLionel Sambuc #define UF_INTERDOMAIN_TRUST_ACCOUNT    	0x00000800
75*ebfedea0SLionel Sambuc #define UF_WORKSTATION_TRUST_ACCOUNT    	0x00001000
76*ebfedea0SLionel Sambuc #define UF_SERVER_TRUST_ACCOUNT         	0x00002000
77*ebfedea0SLionel Sambuc #define UF_UNUSED_2	 			0x00004000
78*ebfedea0SLionel Sambuc #define UF_UNUSED_3	 			0x00008000
79*ebfedea0SLionel Sambuc #define UF_PASSWD_NOT_EXPIRE			0x00010000
80*ebfedea0SLionel Sambuc #define UF_MNS_LOGON_ACCOUNT			0x00020000
81*ebfedea0SLionel Sambuc #define UF_SMARTCARD_REQUIRED			0x00040000
82*ebfedea0SLionel Sambuc #define UF_TRUSTED_FOR_DELEGATION		0x00080000
83*ebfedea0SLionel Sambuc #define UF_NOT_DELEGATED			0x00100000
84*ebfedea0SLionel Sambuc #define UF_USE_DES_KEY_ONLY			0x00200000
85*ebfedea0SLionel Sambuc #define UF_DONT_REQUIRE_PREAUTH			0x00400000
86*ebfedea0SLionel Sambuc #define UF_UNUSED_4				0x00800000
87*ebfedea0SLionel Sambuc #define UF_UNUSED_5				0x01000000
88*ebfedea0SLionel Sambuc #define UF_UNUSED_6				0x02000000
89*ebfedea0SLionel Sambuc #define UF_UNUSED_7				0x04000000
90*ebfedea0SLionel Sambuc #define UF_UNUSED_8				0x08000000
91*ebfedea0SLionel Sambuc #define UF_UNUSED_9				0x10000000
92*ebfedea0SLionel Sambuc #define UF_UNUSED_10				0x20000000
93*ebfedea0SLionel Sambuc #define UF_UNUSED_11				0x40000000
94*ebfedea0SLionel Sambuc #define UF_UNUSED_12				0x80000000
95*ebfedea0SLionel Sambuc 
96*ebfedea0SLionel Sambuc /*
97*ebfedea0SLionel Sambuc  *
98*ebfedea0SLionel Sambuc  */
99*ebfedea0SLionel Sambuc 
100*ebfedea0SLionel Sambuc #ifndef HAVE_TSASL
101*ebfedea0SLionel Sambuc static int
102*ebfedea0SLionel Sambuc sasl_interact(LDAP *ld, unsigned flags, void *defaults, void *interact)
103*ebfedea0SLionel Sambuc {
104*ebfedea0SLionel Sambuc     return LDAP_SUCCESS;
105*ebfedea0SLionel Sambuc }
106*ebfedea0SLionel Sambuc #endif
107*ebfedea0SLionel Sambuc 
108*ebfedea0SLionel Sambuc #if 0
109*ebfedea0SLionel Sambuc static Sockbuf_IO ldap_tsasl_io = {
110*ebfedea0SLionel Sambuc     NULL,			/* sbi_setup */
111*ebfedea0SLionel Sambuc     NULL,			/* sbi_remove */
112*ebfedea0SLionel Sambuc     NULL,			/* sbi_ctrl */
113*ebfedea0SLionel Sambuc     NULL,			/* sbi_read */
114*ebfedea0SLionel Sambuc     NULL,			/* sbi_write */
115*ebfedea0SLionel Sambuc     NULL			/* sbi_close */
116*ebfedea0SLionel Sambuc };
117*ebfedea0SLionel Sambuc #endif
118*ebfedea0SLionel Sambuc 
119*ebfedea0SLionel Sambuc #ifdef HAVE_TSASL
120*ebfedea0SLionel Sambuc static int
121*ebfedea0SLionel Sambuc ldap_tsasl_bind_s(LDAP *ld,
122*ebfedea0SLionel Sambuc 		  LDAP_CONST char *dn,
123*ebfedea0SLionel Sambuc 		  LDAPControl **serverControls,
124*ebfedea0SLionel Sambuc 		  LDAPControl **clientControls,
125*ebfedea0SLionel Sambuc 		  const char *host)
126*ebfedea0SLionel Sambuc {
127*ebfedea0SLionel Sambuc     char *attrs[] = { "supportedSASLMechanisms", NULL };
128*ebfedea0SLionel Sambuc     struct tsasl_peer *peer = NULL;
129*ebfedea0SLionel Sambuc     struct tsasl_buffer in, out;
130*ebfedea0SLionel Sambuc     struct berval ccred, *scred;
131*ebfedea0SLionel Sambuc     LDAPMessage *m, *m0;
132*ebfedea0SLionel Sambuc     const char *mech;
133*ebfedea0SLionel Sambuc     char **vals;
134*ebfedea0SLionel Sambuc     int ret, rc;
135*ebfedea0SLionel Sambuc 
136*ebfedea0SLionel Sambuc     ret = tsasl_peer_init(TSASL_FLAGS_INITIATOR | TSASL_FLAGS_CLEAR,
137*ebfedea0SLionel Sambuc 			  "ldap", host, &peer);
138*ebfedea0SLionel Sambuc     if (ret != TSASL_DONE) {
139*ebfedea0SLionel Sambuc 	rc = LDAP_LOCAL_ERROR;
140*ebfedea0SLionel Sambuc 	goto out;
141*ebfedea0SLionel Sambuc     }
142*ebfedea0SLionel Sambuc 
143*ebfedea0SLionel Sambuc     rc = ldap_search_s(ld, "", LDAP_SCOPE_BASE, NULL, attrs, 0, &m0);
144*ebfedea0SLionel Sambuc     if (rc != LDAP_SUCCESS)
145*ebfedea0SLionel Sambuc 	goto out;
146*ebfedea0SLionel Sambuc 
147*ebfedea0SLionel Sambuc     m = ldap_first_entry(ld, m0);
148*ebfedea0SLionel Sambuc     if (m == NULL) {
149*ebfedea0SLionel Sambuc 	ldap_msgfree(m0);
150*ebfedea0SLionel Sambuc 	goto out;
151*ebfedea0SLionel Sambuc     }
152*ebfedea0SLionel Sambuc 
153*ebfedea0SLionel Sambuc     vals = ldap_get_values(ld, m, "supportedSASLMechanisms");
154*ebfedea0SLionel Sambuc     if (vals == NULL) {
155*ebfedea0SLionel Sambuc 	ldap_msgfree(m0);
156*ebfedea0SLionel Sambuc 	goto out;
157*ebfedea0SLionel Sambuc     }
158*ebfedea0SLionel Sambuc 
159*ebfedea0SLionel Sambuc     ret = tsasl_find_best_mech(peer, vals, &mech);
160*ebfedea0SLionel Sambuc     if (ret) {
161*ebfedea0SLionel Sambuc 	ldap_msgfree(m0);
162*ebfedea0SLionel Sambuc 	goto out;
163*ebfedea0SLionel Sambuc     }
164*ebfedea0SLionel Sambuc 
165*ebfedea0SLionel Sambuc     ldap_msgfree(m0);
166*ebfedea0SLionel Sambuc 
167*ebfedea0SLionel Sambuc     ret = tsasl_select_mech(peer, mech);
168*ebfedea0SLionel Sambuc     if (ret != TSASL_DONE) {
169*ebfedea0SLionel Sambuc 	rc = LDAP_LOCAL_ERROR;
170*ebfedea0SLionel Sambuc 	goto out;
171*ebfedea0SLionel Sambuc     }
172*ebfedea0SLionel Sambuc 
173*ebfedea0SLionel Sambuc     in.tb_data = NULL;
174*ebfedea0SLionel Sambuc     in.tb_size = 0;
175*ebfedea0SLionel Sambuc 
176*ebfedea0SLionel Sambuc     do {
177*ebfedea0SLionel Sambuc 	ret = tsasl_request(peer, &in, &out);
178*ebfedea0SLionel Sambuc 	if (in.tb_size != 0) {
179*ebfedea0SLionel Sambuc 	    free(in.tb_data);
180*ebfedea0SLionel Sambuc 	    in.tb_data = NULL;
181*ebfedea0SLionel Sambuc 	    in.tb_size = 0;
182*ebfedea0SLionel Sambuc 	}
183*ebfedea0SLionel Sambuc 	if (ret != TSASL_DONE && ret != TSASL_CONTINUE) {
184*ebfedea0SLionel Sambuc 	    rc = LDAP_AUTH_UNKNOWN;
185*ebfedea0SLionel Sambuc 	    goto out;
186*ebfedea0SLionel Sambuc 	}
187*ebfedea0SLionel Sambuc 
188*ebfedea0SLionel Sambuc 	ccred.bv_val = out.tb_data;
189*ebfedea0SLionel Sambuc 	ccred.bv_len = out.tb_size;
190*ebfedea0SLionel Sambuc 
191*ebfedea0SLionel Sambuc 	rc = ldap_sasl_bind_s(ld, dn, mech, &ccred,
192*ebfedea0SLionel Sambuc 			      serverControls, clientControls, &scred);
193*ebfedea0SLionel Sambuc 	tsasl_buffer_free(&out);
194*ebfedea0SLionel Sambuc 
195*ebfedea0SLionel Sambuc 	if (rc != LDAP_SUCCESS && rc != LDAP_SASL_BIND_IN_PROGRESS) {
196*ebfedea0SLionel Sambuc 	    if(scred && scred->bv_len)
197*ebfedea0SLionel Sambuc 		ber_bvfree(scred);
198*ebfedea0SLionel Sambuc 	    goto out;
199*ebfedea0SLionel Sambuc 	}
200*ebfedea0SLionel Sambuc 
201*ebfedea0SLionel Sambuc 	in.tb_data = malloc(scred->bv_len);
202*ebfedea0SLionel Sambuc 	if (in.tb_data == NULL) {
203*ebfedea0SLionel Sambuc 	    rc = LDAP_LOCAL_ERROR;
204*ebfedea0SLionel Sambuc 	    goto out;
205*ebfedea0SLionel Sambuc 	}
206*ebfedea0SLionel Sambuc 	memcpy(in.tb_data, scred->bv_val, scred->bv_len);
207*ebfedea0SLionel Sambuc 	in.tb_size = scred->bv_len;
208*ebfedea0SLionel Sambuc 	ber_bvfree(scred);
209*ebfedea0SLionel Sambuc 
210*ebfedea0SLionel Sambuc     } while (rc == LDAP_SASL_BIND_IN_PROGRESS);
211*ebfedea0SLionel Sambuc 
212*ebfedea0SLionel Sambuc  out:
213*ebfedea0SLionel Sambuc     if (rc == LDAP_SUCCESS) {
214*ebfedea0SLionel Sambuc #if 0
215*ebfedea0SLionel Sambuc 	ber_sockbuf_add_io(ld->ld_conns->lconn_sb, &ldap_tsasl_io,
216*ebfedea0SLionel Sambuc 			   LBER_SBIOD_LEVEL_APPLICATION, peer);
217*ebfedea0SLionel Sambuc 
218*ebfedea0SLionel Sambuc #endif
219*ebfedea0SLionel Sambuc     } else if (peer != NULL)
220*ebfedea0SLionel Sambuc 	tsasl_peer_free(peer);
221*ebfedea0SLionel Sambuc 
222*ebfedea0SLionel Sambuc     return rc;
223*ebfedea0SLionel Sambuc }
224*ebfedea0SLionel Sambuc #endif /* HAVE_TSASL */
225*ebfedea0SLionel Sambuc 
226*ebfedea0SLionel Sambuc 
227*ebfedea0SLionel Sambuc static int
228*ebfedea0SLionel Sambuc check_ldap(kadm5_ad_context *context, int ret)
229*ebfedea0SLionel Sambuc {
230*ebfedea0SLionel Sambuc     switch (ret) {
231*ebfedea0SLionel Sambuc     case LDAP_SUCCESS:
232*ebfedea0SLionel Sambuc 	return 0;
233*ebfedea0SLionel Sambuc     case LDAP_SERVER_DOWN: {
234*ebfedea0SLionel Sambuc 	LDAP *lp = CTX2LP(context);
235*ebfedea0SLionel Sambuc 	ldap_unbind(lp);
236*ebfedea0SLionel Sambuc 	context->ldap_conn = NULL;
237*ebfedea0SLionel Sambuc 	free(context->base_dn);
238*ebfedea0SLionel Sambuc 	context->base_dn = NULL;
239*ebfedea0SLionel Sambuc 	return 1;
240*ebfedea0SLionel Sambuc     }
241*ebfedea0SLionel Sambuc     default:
242*ebfedea0SLionel Sambuc 	return 1;
243*ebfedea0SLionel Sambuc     }
244*ebfedea0SLionel Sambuc }
245*ebfedea0SLionel Sambuc 
246*ebfedea0SLionel Sambuc /*
247*ebfedea0SLionel Sambuc  *
248*ebfedea0SLionel Sambuc  */
249*ebfedea0SLionel Sambuc 
250*ebfedea0SLionel Sambuc static void
251*ebfedea0SLionel Sambuc laddattr(char ***al, int *attrlen, char *attr)
252*ebfedea0SLionel Sambuc {
253*ebfedea0SLionel Sambuc     char **a;
254*ebfedea0SLionel Sambuc     a = realloc(*al, (*attrlen + 2) * sizeof(**al));
255*ebfedea0SLionel Sambuc     if (a == NULL)
256*ebfedea0SLionel Sambuc 	return;
257*ebfedea0SLionel Sambuc     a[*attrlen] = attr;
258*ebfedea0SLionel Sambuc     a[*attrlen + 1] = NULL;
259*ebfedea0SLionel Sambuc     (*attrlen)++;
260*ebfedea0SLionel Sambuc     *al = a;
261*ebfedea0SLionel Sambuc }
262*ebfedea0SLionel Sambuc 
263*ebfedea0SLionel Sambuc static kadm5_ret_t
264*ebfedea0SLionel Sambuc _kadm5_ad_connect(void *server_handle)
265*ebfedea0SLionel Sambuc {
266*ebfedea0SLionel Sambuc     kadm5_ad_context *context = server_handle;
267*ebfedea0SLionel Sambuc     struct {
268*ebfedea0SLionel Sambuc 	char *server;
269*ebfedea0SLionel Sambuc 	int port;
270*ebfedea0SLionel Sambuc     } *s, *servers = NULL;
271*ebfedea0SLionel Sambuc     int i, num_servers = 0;
272*ebfedea0SLionel Sambuc 
273*ebfedea0SLionel Sambuc     if (context->ldap_conn)
274*ebfedea0SLionel Sambuc 	return 0;
275*ebfedea0SLionel Sambuc 
276*ebfedea0SLionel Sambuc     {
277*ebfedea0SLionel Sambuc 	struct dns_reply *r;
278*ebfedea0SLionel Sambuc 	struct resource_record *rr;
279*ebfedea0SLionel Sambuc 	char *domain;
280*ebfedea0SLionel Sambuc 
281*ebfedea0SLionel Sambuc 	asprintf(&domain, "_ldap._tcp.%s", context->realm);
282*ebfedea0SLionel Sambuc 	if (domain == NULL) {
283*ebfedea0SLionel Sambuc 	    krb5_set_error_message(context->context, KADM5_NO_SRV, "malloc");
284*ebfedea0SLionel Sambuc 	    return KADM5_NO_SRV;
285*ebfedea0SLionel Sambuc 	}
286*ebfedea0SLionel Sambuc 
287*ebfedea0SLionel Sambuc 	r = dns_lookup(domain, "SRV");
288*ebfedea0SLionel Sambuc 	free(domain);
289*ebfedea0SLionel Sambuc 	if (r == NULL) {
290*ebfedea0SLionel Sambuc 	    krb5_set_error_message(context->context, KADM5_NO_SRV, "Didn't find ldap dns");
291*ebfedea0SLionel Sambuc 	    return KADM5_NO_SRV;
292*ebfedea0SLionel Sambuc 	}
293*ebfedea0SLionel Sambuc 
294*ebfedea0SLionel Sambuc 	for (rr = r->head ; rr != NULL; rr = rr->next) {
295*ebfedea0SLionel Sambuc 	    if (rr->type != rk_ns_t_srv)
296*ebfedea0SLionel Sambuc 		continue;
297*ebfedea0SLionel Sambuc 	    s = realloc(servers, sizeof(*servers) * (num_servers + 1));
298*ebfedea0SLionel Sambuc 	    if (s == NULL) {
299*ebfedea0SLionel Sambuc 		krb5_set_error_message(context->context, KADM5_RPC_ERROR, "malloc");
300*ebfedea0SLionel Sambuc 		dns_free_data(r);
301*ebfedea0SLionel Sambuc 		goto fail;
302*ebfedea0SLionel Sambuc 	    }
303*ebfedea0SLionel Sambuc 	    servers = s;
304*ebfedea0SLionel Sambuc 	    num_servers++;
305*ebfedea0SLionel Sambuc 	    servers[num_servers - 1].port =  rr->u.srv->port;
306*ebfedea0SLionel Sambuc 	    servers[num_servers - 1].server =  strdup(rr->u.srv->target);
307*ebfedea0SLionel Sambuc 	}
308*ebfedea0SLionel Sambuc 	dns_free_data(r);
309*ebfedea0SLionel Sambuc     }
310*ebfedea0SLionel Sambuc 
311*ebfedea0SLionel Sambuc     if (num_servers == 0) {
312*ebfedea0SLionel Sambuc 	krb5_set_error_message(context->context, KADM5_NO_SRV, "No AD server found in DNS");
313*ebfedea0SLionel Sambuc 	return KADM5_NO_SRV;
314*ebfedea0SLionel Sambuc     }
315*ebfedea0SLionel Sambuc 
316*ebfedea0SLionel Sambuc     for (i = 0; i < num_servers; i++) {
317*ebfedea0SLionel Sambuc 	int lret, version = LDAP_VERSION3;
318*ebfedea0SLionel Sambuc 	LDAP *lp;
319*ebfedea0SLionel Sambuc 
320*ebfedea0SLionel Sambuc 	lp = ldap_init(servers[i].server, servers[i].port);
321*ebfedea0SLionel Sambuc 	if (lp == NULL)
322*ebfedea0SLionel Sambuc 	    continue;
323*ebfedea0SLionel Sambuc 
324*ebfedea0SLionel Sambuc 	if (ldap_set_option(lp, LDAP_OPT_PROTOCOL_VERSION, &version)) {
325*ebfedea0SLionel Sambuc 	    ldap_unbind(lp);
326*ebfedea0SLionel Sambuc 	    continue;
327*ebfedea0SLionel Sambuc 	}
328*ebfedea0SLionel Sambuc 
329*ebfedea0SLionel Sambuc 	if (ldap_set_option(lp, LDAP_OPT_REFERRALS, LDAP_OPT_OFF)) {
330*ebfedea0SLionel Sambuc 	    ldap_unbind(lp);
331*ebfedea0SLionel Sambuc 	    continue;
332*ebfedea0SLionel Sambuc 	}
333*ebfedea0SLionel Sambuc 
334*ebfedea0SLionel Sambuc #ifdef HAVE_TSASL
335*ebfedea0SLionel Sambuc 	lret = ldap_tsasl_bind_s(lp, NULL, NULL, NULL, servers[i].server);
336*ebfedea0SLionel Sambuc 
337*ebfedea0SLionel Sambuc #else
338*ebfedea0SLionel Sambuc 	lret = ldap_sasl_interactive_bind_s(lp, NULL, NULL, NULL, NULL,
339*ebfedea0SLionel Sambuc 					    LDAP_SASL_QUIET,
340*ebfedea0SLionel Sambuc 					    sasl_interact, NULL);
341*ebfedea0SLionel Sambuc #endif
342*ebfedea0SLionel Sambuc 	if (lret != LDAP_SUCCESS) {
343*ebfedea0SLionel Sambuc 	    krb5_set_error_message(context->context, 0,
344*ebfedea0SLionel Sambuc 				   "Couldn't contact any AD servers: %s",
345*ebfedea0SLionel Sambuc 				   ldap_err2string(lret));
346*ebfedea0SLionel Sambuc 	    ldap_unbind(lp);
347*ebfedea0SLionel Sambuc 	    continue;
348*ebfedea0SLionel Sambuc 	}
349*ebfedea0SLionel Sambuc 
350*ebfedea0SLionel Sambuc 	context->ldap_conn = lp;
351*ebfedea0SLionel Sambuc 	break;
352*ebfedea0SLionel Sambuc     }
353*ebfedea0SLionel Sambuc     if (i >= num_servers) {
354*ebfedea0SLionel Sambuc 	goto fail;
355*ebfedea0SLionel Sambuc     }
356*ebfedea0SLionel Sambuc 
357*ebfedea0SLionel Sambuc     {
358*ebfedea0SLionel Sambuc 	LDAPMessage *m, *m0;
359*ebfedea0SLionel Sambuc 	char **attr = NULL;
360*ebfedea0SLionel Sambuc 	int attrlen = 0;
361*ebfedea0SLionel Sambuc 	char **vals;
362*ebfedea0SLionel Sambuc 	int ret;
363*ebfedea0SLionel Sambuc 
364*ebfedea0SLionel Sambuc 	laddattr(&attr, &attrlen, "defaultNamingContext");
365*ebfedea0SLionel Sambuc 
366*ebfedea0SLionel Sambuc 	ret = ldap_search_s(CTX2LP(context), "", LDAP_SCOPE_BASE,
367*ebfedea0SLionel Sambuc 			    "objectclass=*", attr, 0, &m);
368*ebfedea0SLionel Sambuc 	free(attr);
369*ebfedea0SLionel Sambuc 	if (check_ldap(context, ret))
370*ebfedea0SLionel Sambuc 	    goto fail;
371*ebfedea0SLionel Sambuc 
372*ebfedea0SLionel Sambuc 	if (ldap_count_entries(CTX2LP(context), m) > 0) {
373*ebfedea0SLionel Sambuc 	    m0 = ldap_first_entry(CTX2LP(context), m);
374*ebfedea0SLionel Sambuc 	    if (m0 == NULL) {
375*ebfedea0SLionel Sambuc 		krb5_set_error_message(context->context, KADM5_RPC_ERROR,
376*ebfedea0SLionel Sambuc 				       "Error in AD ldap responce");
377*ebfedea0SLionel Sambuc 		ldap_msgfree(m);
378*ebfedea0SLionel Sambuc 		goto fail;
379*ebfedea0SLionel Sambuc 	    }
380*ebfedea0SLionel Sambuc 	    vals = ldap_get_values(CTX2LP(context),
381*ebfedea0SLionel Sambuc 				   m0, "defaultNamingContext");
382*ebfedea0SLionel Sambuc 	    if (vals == NULL) {
383*ebfedea0SLionel Sambuc 		krb5_set_error_message(context->context, KADM5_RPC_ERROR,
384*ebfedea0SLionel Sambuc 				       "No naming context found");
385*ebfedea0SLionel Sambuc 		goto fail;
386*ebfedea0SLionel Sambuc 	    }
387*ebfedea0SLionel Sambuc 	    context->base_dn = strdup(vals[0]);
388*ebfedea0SLionel Sambuc 	} else
389*ebfedea0SLionel Sambuc 	    goto fail;
390*ebfedea0SLionel Sambuc 	ldap_msgfree(m);
391*ebfedea0SLionel Sambuc     }
392*ebfedea0SLionel Sambuc 
393*ebfedea0SLionel Sambuc     for (i = 0; i < num_servers; i++)
394*ebfedea0SLionel Sambuc 	free(servers[i].server);
395*ebfedea0SLionel Sambuc     free(servers);
396*ebfedea0SLionel Sambuc 
397*ebfedea0SLionel Sambuc     return 0;
398*ebfedea0SLionel Sambuc 
399*ebfedea0SLionel Sambuc  fail:
400*ebfedea0SLionel Sambuc     for (i = 0; i < num_servers; i++)
401*ebfedea0SLionel Sambuc 	free(servers[i].server);
402*ebfedea0SLionel Sambuc     free(servers);
403*ebfedea0SLionel Sambuc 
404*ebfedea0SLionel Sambuc     if (context->ldap_conn) {
405*ebfedea0SLionel Sambuc 	ldap_unbind(CTX2LP(context));
406*ebfedea0SLionel Sambuc 	context->ldap_conn = NULL;
407*ebfedea0SLionel Sambuc     }
408*ebfedea0SLionel Sambuc     return KADM5_RPC_ERROR;
409*ebfedea0SLionel Sambuc }
410*ebfedea0SLionel Sambuc 
411*ebfedea0SLionel Sambuc #define NTTIME_EPOCH 0x019DB1DED53E8000LL
412*ebfedea0SLionel Sambuc 
413*ebfedea0SLionel Sambuc static time_t
414*ebfedea0SLionel Sambuc nt2unixtime(const char *str)
415*ebfedea0SLionel Sambuc {
416*ebfedea0SLionel Sambuc     unsigned long long t;
417*ebfedea0SLionel Sambuc     t = strtoll(str, NULL, 10);
418*ebfedea0SLionel Sambuc     t = ((t - NTTIME_EPOCH) / (long long)10000000);
419*ebfedea0SLionel Sambuc     if (t > (((time_t)(~(long long)0)) >> 1))
420*ebfedea0SLionel Sambuc 	return 0;
421*ebfedea0SLionel Sambuc     return (time_t)t;
422*ebfedea0SLionel Sambuc }
423*ebfedea0SLionel Sambuc 
424*ebfedea0SLionel Sambuc static long long
425*ebfedea0SLionel Sambuc unix2nttime(time_t unix_time)
426*ebfedea0SLionel Sambuc {
427*ebfedea0SLionel Sambuc     long long wt;
428*ebfedea0SLionel Sambuc     wt = unix_time * (long long)10000000 + (long long)NTTIME_EPOCH;
429*ebfedea0SLionel Sambuc     return wt;
430*ebfedea0SLionel Sambuc }
431*ebfedea0SLionel Sambuc 
432*ebfedea0SLionel Sambuc /* XXX create filter in a better way */
433*ebfedea0SLionel Sambuc 
434*ebfedea0SLionel Sambuc static int
435*ebfedea0SLionel Sambuc ad_find_entry(kadm5_ad_context *context,
436*ebfedea0SLionel Sambuc 	      const char *fqdn,
437*ebfedea0SLionel Sambuc 	      const char *pn,
438*ebfedea0SLionel Sambuc 	      char **name)
439*ebfedea0SLionel Sambuc {
440*ebfedea0SLionel Sambuc     LDAPMessage *m, *m0;
441*ebfedea0SLionel Sambuc     char *attr[] = { "distinguishedName", NULL };
442*ebfedea0SLionel Sambuc     char *filter;
443*ebfedea0SLionel Sambuc     int ret;
444*ebfedea0SLionel Sambuc 
445*ebfedea0SLionel Sambuc     if (name)
446*ebfedea0SLionel Sambuc 	*name = NULL;
447*ebfedea0SLionel Sambuc 
448*ebfedea0SLionel Sambuc     if (fqdn)
449*ebfedea0SLionel Sambuc 	asprintf(&filter,
450*ebfedea0SLionel Sambuc 		 "(&(objectClass=computer)(|(dNSHostName=%s)(servicePrincipalName=%s)))",
451*ebfedea0SLionel Sambuc 		 fqdn, pn);
452*ebfedea0SLionel Sambuc     else if(pn)
453*ebfedea0SLionel Sambuc 	asprintf(&filter, "(&(objectClass=account)(userPrincipalName=%s))", pn);
454*ebfedea0SLionel Sambuc     else
455*ebfedea0SLionel Sambuc 	return KADM5_RPC_ERROR;
456*ebfedea0SLionel Sambuc 
457*ebfedea0SLionel Sambuc     ret = ldap_search_s(CTX2LP(context), CTX2BASE(context),
458*ebfedea0SLionel Sambuc 			LDAP_SCOPE_SUBTREE,
459*ebfedea0SLionel Sambuc 			filter, attr, 0, &m);
460*ebfedea0SLionel Sambuc     free(filter);
461*ebfedea0SLionel Sambuc     if (check_ldap(context, ret))
462*ebfedea0SLionel Sambuc 	return KADM5_RPC_ERROR;
463*ebfedea0SLionel Sambuc 
464*ebfedea0SLionel Sambuc     if (ldap_count_entries(CTX2LP(context), m) > 0) {
465*ebfedea0SLionel Sambuc 	char **vals;
466*ebfedea0SLionel Sambuc 	m0 = ldap_first_entry(CTX2LP(context), m);
467*ebfedea0SLionel Sambuc 	vals = ldap_get_values(CTX2LP(context), m0, "distinguishedName");
468*ebfedea0SLionel Sambuc 	if (vals == NULL || vals[0] == NULL) {
469*ebfedea0SLionel Sambuc 	    ldap_msgfree(m);
470*ebfedea0SLionel Sambuc 	    return KADM5_RPC_ERROR;
471*ebfedea0SLionel Sambuc 	}
472*ebfedea0SLionel Sambuc 	if (name)
473*ebfedea0SLionel Sambuc 	    *name = strdup(vals[0]);
474*ebfedea0SLionel Sambuc 	ldap_msgfree(m);
475*ebfedea0SLionel Sambuc     } else
476*ebfedea0SLionel Sambuc 	return KADM5_UNK_PRINC;
477*ebfedea0SLionel Sambuc 
478*ebfedea0SLionel Sambuc     return 0;
479*ebfedea0SLionel Sambuc }
480*ebfedea0SLionel Sambuc 
481*ebfedea0SLionel Sambuc #endif /* OPENLDAP */
482*ebfedea0SLionel Sambuc 
483*ebfedea0SLionel Sambuc static kadm5_ret_t
484*ebfedea0SLionel Sambuc ad_get_cred(kadm5_ad_context *context, const char *password)
485*ebfedea0SLionel Sambuc {
486*ebfedea0SLionel Sambuc     kadm5_ret_t ret;
487*ebfedea0SLionel Sambuc     krb5_ccache cc;
488*ebfedea0SLionel Sambuc     char *service;
489*ebfedea0SLionel Sambuc 
490*ebfedea0SLionel Sambuc     if (context->ccache)
491*ebfedea0SLionel Sambuc 	return 0;
492*ebfedea0SLionel Sambuc 
493*ebfedea0SLionel Sambuc     asprintf(&service, "%s/%s@%s", KRB5_TGS_NAME,
494*ebfedea0SLionel Sambuc 	     context->realm, context->realm);
495*ebfedea0SLionel Sambuc     if (service == NULL)
496*ebfedea0SLionel Sambuc 	return ENOMEM;
497*ebfedea0SLionel Sambuc 
498*ebfedea0SLionel Sambuc     ret = _kadm5_c_get_cred_cache(context->context,
499*ebfedea0SLionel Sambuc 				  context->client_name,
500*ebfedea0SLionel Sambuc 				  service,
501*ebfedea0SLionel Sambuc 				  password, krb5_prompter_posix,
502*ebfedea0SLionel Sambuc 				  NULL, NULL, &cc);
503*ebfedea0SLionel Sambuc     free(service);
504*ebfedea0SLionel Sambuc     if(ret)
505*ebfedea0SLionel Sambuc 	return ret; /* XXX */
506*ebfedea0SLionel Sambuc     context->ccache = cc;
507*ebfedea0SLionel Sambuc     return 0;
508*ebfedea0SLionel Sambuc }
509*ebfedea0SLionel Sambuc 
510*ebfedea0SLionel Sambuc static kadm5_ret_t
511*ebfedea0SLionel Sambuc kadm5_ad_chpass_principal(void *server_handle,
512*ebfedea0SLionel Sambuc 			  krb5_principal principal,
513*ebfedea0SLionel Sambuc 			  const char *password)
514*ebfedea0SLionel Sambuc {
515*ebfedea0SLionel Sambuc     kadm5_ad_context *context = server_handle;
516*ebfedea0SLionel Sambuc     krb5_data result_code_string, result_string;
517*ebfedea0SLionel Sambuc     int result_code;
518*ebfedea0SLionel Sambuc     kadm5_ret_t ret;
519*ebfedea0SLionel Sambuc 
520*ebfedea0SLionel Sambuc     ret = ad_get_cred(context, NULL);
521*ebfedea0SLionel Sambuc     if (ret)
522*ebfedea0SLionel Sambuc 	return ret;
523*ebfedea0SLionel Sambuc 
524*ebfedea0SLionel Sambuc     krb5_data_zero (&result_code_string);
525*ebfedea0SLionel Sambuc     krb5_data_zero (&result_string);
526*ebfedea0SLionel Sambuc 
527*ebfedea0SLionel Sambuc     ret = krb5_set_password_using_ccache (context->context,
528*ebfedea0SLionel Sambuc 					  context->ccache,
529*ebfedea0SLionel Sambuc 					  password,
530*ebfedea0SLionel Sambuc 					  principal,
531*ebfedea0SLionel Sambuc 					  &result_code,
532*ebfedea0SLionel Sambuc 					  &result_code_string,
533*ebfedea0SLionel Sambuc 					  &result_string);
534*ebfedea0SLionel Sambuc 
535*ebfedea0SLionel Sambuc     krb5_data_free (&result_code_string);
536*ebfedea0SLionel Sambuc     krb5_data_free (&result_string);
537*ebfedea0SLionel Sambuc 
538*ebfedea0SLionel Sambuc     /* XXX do mapping here on error codes */
539*ebfedea0SLionel Sambuc 
540*ebfedea0SLionel Sambuc     return ret;
541*ebfedea0SLionel Sambuc }
542*ebfedea0SLionel Sambuc 
543*ebfedea0SLionel Sambuc #ifdef OPENLDAP
544*ebfedea0SLionel Sambuc static const char *
545*ebfedea0SLionel Sambuc get_fqdn(krb5_context context, const krb5_principal p)
546*ebfedea0SLionel Sambuc {
547*ebfedea0SLionel Sambuc     const char *s, *hosttypes[] = { "host", "ldap", "gc", "cifs", "dns" };
548*ebfedea0SLionel Sambuc     int i;
549*ebfedea0SLionel Sambuc 
550*ebfedea0SLionel Sambuc     s = krb5_principal_get_comp_string(context, p, 0);
551*ebfedea0SLionel Sambuc     if (p == NULL)
552*ebfedea0SLionel Sambuc 	return NULL;
553*ebfedea0SLionel Sambuc 
554*ebfedea0SLionel Sambuc     for (i = 0; i < sizeof(hosttypes)/sizeof(hosttypes[0]); i++) {
555*ebfedea0SLionel Sambuc 	if (strcasecmp(s, hosttypes[i]) == 0)
556*ebfedea0SLionel Sambuc 	    return krb5_principal_get_comp_string(context, p, 1);
557*ebfedea0SLionel Sambuc     }
558*ebfedea0SLionel Sambuc     return 0;
559*ebfedea0SLionel Sambuc }
560*ebfedea0SLionel Sambuc #endif
561*ebfedea0SLionel Sambuc 
562*ebfedea0SLionel Sambuc 
563*ebfedea0SLionel Sambuc static kadm5_ret_t
564*ebfedea0SLionel Sambuc kadm5_ad_create_principal(void *server_handle,
565*ebfedea0SLionel Sambuc 			  kadm5_principal_ent_t entry,
566*ebfedea0SLionel Sambuc 			  uint32_t mask,
567*ebfedea0SLionel Sambuc 			  const char *password)
568*ebfedea0SLionel Sambuc {
569*ebfedea0SLionel Sambuc     kadm5_ad_context *context = server_handle;
570*ebfedea0SLionel Sambuc 
571*ebfedea0SLionel Sambuc     /*
572*ebfedea0SLionel Sambuc      * KADM5_PRINC_EXPIRE_TIME
573*ebfedea0SLionel Sambuc      *
574*ebfedea0SLionel Sambuc      * return 0 || KADM5_DUP;
575*ebfedea0SLionel Sambuc      */
576*ebfedea0SLionel Sambuc 
577*ebfedea0SLionel Sambuc #ifdef OPENLDAP
578*ebfedea0SLionel Sambuc     LDAPMod *attrs[8], rattrs[7], *a;
579*ebfedea0SLionel Sambuc     char *useraccvals[2] = { NULL, NULL },
580*ebfedea0SLionel Sambuc 	*samvals[2], *dnsvals[2], *spnvals[5], *upnvals[2], *tv[2];
581*ebfedea0SLionel Sambuc     char *ocvals_spn[] = { "top", "person", "organizationalPerson",
582*ebfedea0SLionel Sambuc 			   "user", "computer", NULL};
583*ebfedea0SLionel Sambuc     char *p, *realmless_p, *p_msrealm = NULL, *dn = NULL;
584*ebfedea0SLionel Sambuc     const char *fqdn;
585*ebfedea0SLionel Sambuc     char *s, *samname = NULL, *short_spn = NULL;
586*ebfedea0SLionel Sambuc     int ret, i;
587*ebfedea0SLionel Sambuc     int32_t uf_flags = 0;
588*ebfedea0SLionel Sambuc 
589*ebfedea0SLionel Sambuc     if ((mask & KADM5_PRINCIPAL) == 0)
590*ebfedea0SLionel Sambuc 	return KADM5_BAD_MASK;
591*ebfedea0SLionel Sambuc 
592*ebfedea0SLionel Sambuc     for (i = 0; i < sizeof(rattrs)/sizeof(rattrs[0]); i++)
593*ebfedea0SLionel Sambuc 	attrs[i] = &rattrs[i];
594*ebfedea0SLionel Sambuc     attrs[i] = NULL;
595*ebfedea0SLionel Sambuc 
596*ebfedea0SLionel Sambuc     ret = ad_get_cred(context, NULL);
597*ebfedea0SLionel Sambuc     if (ret)
598*ebfedea0SLionel Sambuc 	return ret;
599*ebfedea0SLionel Sambuc 
600*ebfedea0SLionel Sambuc     ret = _kadm5_ad_connect(server_handle);
601*ebfedea0SLionel Sambuc     if (ret)
602*ebfedea0SLionel Sambuc 	return ret;
603*ebfedea0SLionel Sambuc 
604*ebfedea0SLionel Sambuc     fqdn = get_fqdn(context->context, entry->principal);
605*ebfedea0SLionel Sambuc 
606*ebfedea0SLionel Sambuc     ret = krb5_unparse_name(context->context, entry->principal, &p);
607*ebfedea0SLionel Sambuc     if (ret)
608*ebfedea0SLionel Sambuc 	return ret;
609*ebfedea0SLionel Sambuc 
610*ebfedea0SLionel Sambuc     if (ad_find_entry(context, fqdn, p, NULL) == 0) {
611*ebfedea0SLionel Sambuc 	free(p);
612*ebfedea0SLionel Sambuc 	return KADM5_DUP;
613*ebfedea0SLionel Sambuc     }
614*ebfedea0SLionel Sambuc 
615*ebfedea0SLionel Sambuc     if (mask & KADM5_ATTRIBUTES) {
616*ebfedea0SLionel Sambuc 	if (entry->attributes & KRB5_KDB_DISALLOW_ALL_TIX)
617*ebfedea0SLionel Sambuc 	    uf_flags |= UF_ACCOUNTDISABLE|UF_LOCKOUT;
618*ebfedea0SLionel Sambuc 	if ((entry->attributes & KRB5_KDB_REQUIRES_PRE_AUTH) == 0)
619*ebfedea0SLionel Sambuc 	    uf_flags |= UF_DONT_REQUIRE_PREAUTH;
620*ebfedea0SLionel Sambuc 	if (entry->attributes & KRB5_KDB_REQUIRES_HW_AUTH)
621*ebfedea0SLionel Sambuc 	    uf_flags |= UF_SMARTCARD_REQUIRED;
622*ebfedea0SLionel Sambuc     }
623*ebfedea0SLionel Sambuc 
624*ebfedea0SLionel Sambuc     realmless_p = strdup(p);
625*ebfedea0SLionel Sambuc     if (realmless_p == NULL) {
626*ebfedea0SLionel Sambuc 	ret = ENOMEM;
627*ebfedea0SLionel Sambuc 	goto out;
628*ebfedea0SLionel Sambuc     }
629*ebfedea0SLionel Sambuc     s = strrchr(realmless_p, '@');
630*ebfedea0SLionel Sambuc     if (s)
631*ebfedea0SLionel Sambuc 	*s = '\0';
632*ebfedea0SLionel Sambuc 
633*ebfedea0SLionel Sambuc     if (fqdn) {
634*ebfedea0SLionel Sambuc 	/* create computer account */
635*ebfedea0SLionel Sambuc 	asprintf(&samname, "%s$", fqdn);
636*ebfedea0SLionel Sambuc 	if (samname == NULL) {
637*ebfedea0SLionel Sambuc 	    ret = ENOMEM;
638*ebfedea0SLionel Sambuc 	    goto out;
639*ebfedea0SLionel Sambuc 	}
640*ebfedea0SLionel Sambuc 	s = strchr(samname, '.');
641*ebfedea0SLionel Sambuc 	if (s) {
642*ebfedea0SLionel Sambuc 	    s[0] = '$';
643*ebfedea0SLionel Sambuc 	    s[1] = '\0';
644*ebfedea0SLionel Sambuc 	}
645*ebfedea0SLionel Sambuc 
646*ebfedea0SLionel Sambuc 	short_spn = strdup(p);
647*ebfedea0SLionel Sambuc 	if (short_spn == NULL) {
648*ebfedea0SLionel Sambuc 	    errno = ENOMEM;
649*ebfedea0SLionel Sambuc 	    goto out;
650*ebfedea0SLionel Sambuc 	}
651*ebfedea0SLionel Sambuc 	s = strchr(short_spn, '.');
652*ebfedea0SLionel Sambuc 	if (s) {
653*ebfedea0SLionel Sambuc 	    *s = '\0';
654*ebfedea0SLionel Sambuc 	} else {
655*ebfedea0SLionel Sambuc 	    free(short_spn);
656*ebfedea0SLionel Sambuc 	    short_spn = NULL;
657*ebfedea0SLionel Sambuc 	}
658*ebfedea0SLionel Sambuc 
659*ebfedea0SLionel Sambuc 	p_msrealm = strdup(p);
660*ebfedea0SLionel Sambuc 	if (p_msrealm == NULL) {
661*ebfedea0SLionel Sambuc 	    errno = ENOMEM;
662*ebfedea0SLionel Sambuc 	    goto out;
663*ebfedea0SLionel Sambuc 	}
664*ebfedea0SLionel Sambuc 	s = strrchr(p_msrealm, '@');
665*ebfedea0SLionel Sambuc 	if (s) {
666*ebfedea0SLionel Sambuc 	    *s = '/';
667*ebfedea0SLionel Sambuc 	} else {
668*ebfedea0SLionel Sambuc 	    free(p_msrealm);
669*ebfedea0SLionel Sambuc 	    p_msrealm = NULL;
670*ebfedea0SLionel Sambuc 	}
671*ebfedea0SLionel Sambuc 
672*ebfedea0SLionel Sambuc 	asprintf(&dn, "cn=%s, cn=Computers, %s", fqdn, CTX2BASE(context));
673*ebfedea0SLionel Sambuc 	if (dn == NULL) {
674*ebfedea0SLionel Sambuc 	    ret = ENOMEM;
675*ebfedea0SLionel Sambuc 	    goto out;
676*ebfedea0SLionel Sambuc 	}
677*ebfedea0SLionel Sambuc 
678*ebfedea0SLionel Sambuc 	a = &rattrs[0];
679*ebfedea0SLionel Sambuc 	a->mod_op = LDAP_MOD_ADD;
680*ebfedea0SLionel Sambuc 	a->mod_type = "objectClass";
681*ebfedea0SLionel Sambuc 	a->mod_values = ocvals_spn;
682*ebfedea0SLionel Sambuc 	a++;
683*ebfedea0SLionel Sambuc 
684*ebfedea0SLionel Sambuc 	a->mod_op = LDAP_MOD_ADD;
685*ebfedea0SLionel Sambuc 	a->mod_type = "userAccountControl";
686*ebfedea0SLionel Sambuc 	a->mod_values = useraccvals;
687*ebfedea0SLionel Sambuc 	asprintf(&useraccvals[0], "%d",
688*ebfedea0SLionel Sambuc 		 uf_flags |
689*ebfedea0SLionel Sambuc 		 UF_PASSWD_NOT_EXPIRE |
690*ebfedea0SLionel Sambuc 		 UF_WORKSTATION_TRUST_ACCOUNT);
691*ebfedea0SLionel Sambuc 	useraccvals[1] = NULL;
692*ebfedea0SLionel Sambuc 	a++;
693*ebfedea0SLionel Sambuc 
694*ebfedea0SLionel Sambuc 	a->mod_op = LDAP_MOD_ADD;
695*ebfedea0SLionel Sambuc 	a->mod_type = "sAMAccountName";
696*ebfedea0SLionel Sambuc 	a->mod_values = samvals;
697*ebfedea0SLionel Sambuc 	samvals[0] = samname;
698*ebfedea0SLionel Sambuc 	samvals[1] = NULL;
699*ebfedea0SLionel Sambuc 	a++;
700*ebfedea0SLionel Sambuc 
701*ebfedea0SLionel Sambuc 	a->mod_op = LDAP_MOD_ADD;
702*ebfedea0SLionel Sambuc 	a->mod_type = "dNSHostName";
703*ebfedea0SLionel Sambuc 	a->mod_values = dnsvals;
704*ebfedea0SLionel Sambuc 	dnsvals[0] = (char *)fqdn;
705*ebfedea0SLionel Sambuc 	dnsvals[1] = NULL;
706*ebfedea0SLionel Sambuc 	a++;
707*ebfedea0SLionel Sambuc 
708*ebfedea0SLionel Sambuc 	/* XXX  add even more spn's */
709*ebfedea0SLionel Sambuc 	a->mod_op = LDAP_MOD_ADD;
710*ebfedea0SLionel Sambuc 	a->mod_type = "servicePrincipalName";
711*ebfedea0SLionel Sambuc 	a->mod_values = spnvals;
712*ebfedea0SLionel Sambuc 	i = 0;
713*ebfedea0SLionel Sambuc 	spnvals[i++] = p;
714*ebfedea0SLionel Sambuc 	spnvals[i++] = realmless_p;
715*ebfedea0SLionel Sambuc 	if (short_spn)
716*ebfedea0SLionel Sambuc 	    spnvals[i++] = short_spn;
717*ebfedea0SLionel Sambuc 	if (p_msrealm)
718*ebfedea0SLionel Sambuc 	    spnvals[i++] = p_msrealm;
719*ebfedea0SLionel Sambuc 	spnvals[i++] = NULL;
720*ebfedea0SLionel Sambuc 	a++;
721*ebfedea0SLionel Sambuc 
722*ebfedea0SLionel Sambuc 	a->mod_op = LDAP_MOD_ADD;
723*ebfedea0SLionel Sambuc 	a->mod_type = "userPrincipalName";
724*ebfedea0SLionel Sambuc 	a->mod_values = upnvals;
725*ebfedea0SLionel Sambuc 	upnvals[0] = p;
726*ebfedea0SLionel Sambuc 	upnvals[1] = NULL;
727*ebfedea0SLionel Sambuc 	a++;
728*ebfedea0SLionel Sambuc 
729*ebfedea0SLionel Sambuc 	a->mod_op = LDAP_MOD_ADD;
730*ebfedea0SLionel Sambuc 	a->mod_type = "accountExpires";
731*ebfedea0SLionel Sambuc 	a->mod_values = tv;
732*ebfedea0SLionel Sambuc 	tv[0] = "9223372036854775807"; /* "never" */
733*ebfedea0SLionel Sambuc 	tv[1] = NULL;
734*ebfedea0SLionel Sambuc 	a++;
735*ebfedea0SLionel Sambuc 
736*ebfedea0SLionel Sambuc     } else {
737*ebfedea0SLionel Sambuc 	/* create user account */
738*ebfedea0SLionel Sambuc 
739*ebfedea0SLionel Sambuc 	a = &rattrs[0];
740*ebfedea0SLionel Sambuc 	a->mod_op = LDAP_MOD_ADD;
741*ebfedea0SLionel Sambuc 	a->mod_type = "userAccountControl";
742*ebfedea0SLionel Sambuc 	a->mod_values = useraccvals;
743*ebfedea0SLionel Sambuc 	asprintf(&useraccvals[0], "%d",
744*ebfedea0SLionel Sambuc 		 uf_flags |
745*ebfedea0SLionel Sambuc 		 UF_PASSWD_NOT_EXPIRE);
746*ebfedea0SLionel Sambuc 	useraccvals[1] = NULL;
747*ebfedea0SLionel Sambuc 	a++;
748*ebfedea0SLionel Sambuc 
749*ebfedea0SLionel Sambuc 	a->mod_op = LDAP_MOD_ADD;
750*ebfedea0SLionel Sambuc 	a->mod_type = "sAMAccountName";
751*ebfedea0SLionel Sambuc 	a->mod_values = samvals;
752*ebfedea0SLionel Sambuc 	samvals[0] = realmless_p;
753*ebfedea0SLionel Sambuc 	samvals[1] = NULL;
754*ebfedea0SLionel Sambuc 	a++;
755*ebfedea0SLionel Sambuc 
756*ebfedea0SLionel Sambuc 	a->mod_op = LDAP_MOD_ADD;
757*ebfedea0SLionel Sambuc 	a->mod_type = "userPrincipalName";
758*ebfedea0SLionel Sambuc 	a->mod_values = upnvals;
759*ebfedea0SLionel Sambuc 	upnvals[0] = p;
760*ebfedea0SLionel Sambuc 	upnvals[1] = NULL;
761*ebfedea0SLionel Sambuc 	a++;
762*ebfedea0SLionel Sambuc 
763*ebfedea0SLionel Sambuc 	a->mod_op = LDAP_MOD_ADD;
764*ebfedea0SLionel Sambuc 	a->mod_type = "accountExpires";
765*ebfedea0SLionel Sambuc 	a->mod_values = tv;
766*ebfedea0SLionel Sambuc 	tv[0] = "9223372036854775807"; /* "never" */
767*ebfedea0SLionel Sambuc 	tv[1] = NULL;
768*ebfedea0SLionel Sambuc 	a++;
769*ebfedea0SLionel Sambuc     }
770*ebfedea0SLionel Sambuc 
771*ebfedea0SLionel Sambuc     attrs[a - &rattrs[0]] = NULL;
772*ebfedea0SLionel Sambuc 
773*ebfedea0SLionel Sambuc     ret = ldap_add_s(CTX2LP(context), dn, attrs);
774*ebfedea0SLionel Sambuc 
775*ebfedea0SLionel Sambuc  out:
776*ebfedea0SLionel Sambuc     if (useraccvals[0])
777*ebfedea0SLionel Sambuc 	free(useraccvals[0]);
778*ebfedea0SLionel Sambuc     if (realmless_p)
779*ebfedea0SLionel Sambuc 	free(realmless_p);
780*ebfedea0SLionel Sambuc     if (samname)
781*ebfedea0SLionel Sambuc 	free(samname);
782*ebfedea0SLionel Sambuc     if (short_spn)
783*ebfedea0SLionel Sambuc 	free(short_spn);
784*ebfedea0SLionel Sambuc     if (p_msrealm)
785*ebfedea0SLionel Sambuc 	free(p_msrealm);
786*ebfedea0SLionel Sambuc     free(p);
787*ebfedea0SLionel Sambuc 
788*ebfedea0SLionel Sambuc     if (check_ldap(context, ret))
789*ebfedea0SLionel Sambuc 	return KADM5_RPC_ERROR;
790*ebfedea0SLionel Sambuc 
791*ebfedea0SLionel Sambuc     return 0;
792*ebfedea0SLionel Sambuc #else
793*ebfedea0SLionel Sambuc     krb5_set_error_message(context->context, KADM5_RPC_ERROR, "Function not implemented");
794*ebfedea0SLionel Sambuc     return KADM5_RPC_ERROR;
795*ebfedea0SLionel Sambuc #endif
796*ebfedea0SLionel Sambuc }
797*ebfedea0SLionel Sambuc 
798*ebfedea0SLionel Sambuc static kadm5_ret_t
799*ebfedea0SLionel Sambuc kadm5_ad_delete_principal(void *server_handle, krb5_principal principal)
800*ebfedea0SLionel Sambuc {
801*ebfedea0SLionel Sambuc     kadm5_ad_context *context = server_handle;
802*ebfedea0SLionel Sambuc #ifdef OPENLDAP
803*ebfedea0SLionel Sambuc     char *p, *dn = NULL;
804*ebfedea0SLionel Sambuc     const char *fqdn;
805*ebfedea0SLionel Sambuc     int ret;
806*ebfedea0SLionel Sambuc 
807*ebfedea0SLionel Sambuc     ret = ad_get_cred(context, NULL);
808*ebfedea0SLionel Sambuc     if (ret)
809*ebfedea0SLionel Sambuc 	return ret;
810*ebfedea0SLionel Sambuc 
811*ebfedea0SLionel Sambuc     ret = _kadm5_ad_connect(server_handle);
812*ebfedea0SLionel Sambuc     if (ret)
813*ebfedea0SLionel Sambuc 	return ret;
814*ebfedea0SLionel Sambuc 
815*ebfedea0SLionel Sambuc     fqdn = get_fqdn(context->context, principal);
816*ebfedea0SLionel Sambuc 
817*ebfedea0SLionel Sambuc     ret = krb5_unparse_name(context->context, principal, &p);
818*ebfedea0SLionel Sambuc     if (ret)
819*ebfedea0SLionel Sambuc 	return ret;
820*ebfedea0SLionel Sambuc 
821*ebfedea0SLionel Sambuc     if (ad_find_entry(context, fqdn, p, &dn) != 0) {
822*ebfedea0SLionel Sambuc 	free(p);
823*ebfedea0SLionel Sambuc 	return KADM5_UNK_PRINC;
824*ebfedea0SLionel Sambuc     }
825*ebfedea0SLionel Sambuc 
826*ebfedea0SLionel Sambuc     ret = ldap_delete_s(CTX2LP(context), dn);
827*ebfedea0SLionel Sambuc 
828*ebfedea0SLionel Sambuc     free(dn);
829*ebfedea0SLionel Sambuc     free(p);
830*ebfedea0SLionel Sambuc 
831*ebfedea0SLionel Sambuc     if (check_ldap(context, ret))
832*ebfedea0SLionel Sambuc 	return KADM5_RPC_ERROR;
833*ebfedea0SLionel Sambuc     return 0;
834*ebfedea0SLionel Sambuc #else
835*ebfedea0SLionel Sambuc     krb5_set_error_message(context->context, KADM5_RPC_ERROR, "Function not implemented");
836*ebfedea0SLionel Sambuc     return KADM5_RPC_ERROR;
837*ebfedea0SLionel Sambuc #endif
838*ebfedea0SLionel Sambuc }
839*ebfedea0SLionel Sambuc 
840*ebfedea0SLionel Sambuc static kadm5_ret_t
841*ebfedea0SLionel Sambuc kadm5_ad_destroy(void *server_handle)
842*ebfedea0SLionel Sambuc {
843*ebfedea0SLionel Sambuc     kadm5_ad_context *context = server_handle;
844*ebfedea0SLionel Sambuc 
845*ebfedea0SLionel Sambuc     if (context->ccache)
846*ebfedea0SLionel Sambuc 	krb5_cc_destroy(context->context, context->ccache);
847*ebfedea0SLionel Sambuc 
848*ebfedea0SLionel Sambuc #ifdef OPENLDAP
849*ebfedea0SLionel Sambuc     {
850*ebfedea0SLionel Sambuc 	LDAP *lp = CTX2LP(context);
851*ebfedea0SLionel Sambuc 	if (lp)
852*ebfedea0SLionel Sambuc 	    ldap_unbind(lp);
853*ebfedea0SLionel Sambuc 	if (context->base_dn)
854*ebfedea0SLionel Sambuc 	    free(context->base_dn);
855*ebfedea0SLionel Sambuc     }
856*ebfedea0SLionel Sambuc #endif
857*ebfedea0SLionel Sambuc     free(context->realm);
858*ebfedea0SLionel Sambuc     free(context->client_name);
859*ebfedea0SLionel Sambuc     krb5_free_principal(context->context, context->caller);
860*ebfedea0SLionel Sambuc     if(context->my_context)
861*ebfedea0SLionel Sambuc 	krb5_free_context(context->context);
862*ebfedea0SLionel Sambuc     return 0;
863*ebfedea0SLionel Sambuc }
864*ebfedea0SLionel Sambuc 
865*ebfedea0SLionel Sambuc static kadm5_ret_t
866*ebfedea0SLionel Sambuc kadm5_ad_flush(void *server_handle)
867*ebfedea0SLionel Sambuc {
868*ebfedea0SLionel Sambuc     kadm5_ad_context *context = server_handle;
869*ebfedea0SLionel Sambuc     krb5_set_error_message(context->context, KADM5_RPC_ERROR, "Function not implemented");
870*ebfedea0SLionel Sambuc     return KADM5_RPC_ERROR;
871*ebfedea0SLionel Sambuc }
872*ebfedea0SLionel Sambuc 
873*ebfedea0SLionel Sambuc static kadm5_ret_t
874*ebfedea0SLionel Sambuc kadm5_ad_get_principal(void *server_handle,
875*ebfedea0SLionel Sambuc 		       krb5_principal principal,
876*ebfedea0SLionel Sambuc 		       kadm5_principal_ent_t entry,
877*ebfedea0SLionel Sambuc 		       uint32_t mask)
878*ebfedea0SLionel Sambuc {
879*ebfedea0SLionel Sambuc     kadm5_ad_context *context = server_handle;
880*ebfedea0SLionel Sambuc #ifdef OPENLDAP
881*ebfedea0SLionel Sambuc     LDAPMessage *m, *m0;
882*ebfedea0SLionel Sambuc     char **attr = NULL;
883*ebfedea0SLionel Sambuc     int attrlen = 0;
884*ebfedea0SLionel Sambuc     char *filter, *p, *q, *u;
885*ebfedea0SLionel Sambuc     int ret;
886*ebfedea0SLionel Sambuc 
887*ebfedea0SLionel Sambuc     /*
888*ebfedea0SLionel Sambuc      * principal
889*ebfedea0SLionel Sambuc      * KADM5_PRINCIPAL | KADM5_KVNO | KADM5_ATTRIBUTES
890*ebfedea0SLionel Sambuc      */
891*ebfedea0SLionel Sambuc 
892*ebfedea0SLionel Sambuc     /*
893*ebfedea0SLionel Sambuc      * return 0 || KADM5_DUP;
894*ebfedea0SLionel Sambuc      */
895*ebfedea0SLionel Sambuc 
896*ebfedea0SLionel Sambuc     memset(entry, 0, sizeof(*entry));
897*ebfedea0SLionel Sambuc 
898*ebfedea0SLionel Sambuc     if (mask & KADM5_KVNO)
899*ebfedea0SLionel Sambuc 	laddattr(&attr, &attrlen, "msDS-KeyVersionNumber");
900*ebfedea0SLionel Sambuc 
901*ebfedea0SLionel Sambuc     if (mask & KADM5_PRINCIPAL) {
902*ebfedea0SLionel Sambuc 	laddattr(&attr, &attrlen, "userPrincipalName");
903*ebfedea0SLionel Sambuc 	laddattr(&attr, &attrlen, "servicePrincipalName");
904*ebfedea0SLionel Sambuc     }
905*ebfedea0SLionel Sambuc     laddattr(&attr, &attrlen, "objectClass");
906*ebfedea0SLionel Sambuc     laddattr(&attr, &attrlen, "lastLogon");
907*ebfedea0SLionel Sambuc     laddattr(&attr, &attrlen, "badPwdCount");
908*ebfedea0SLionel Sambuc     laddattr(&attr, &attrlen, "badPasswordTime");
909*ebfedea0SLionel Sambuc     laddattr(&attr, &attrlen, "pwdLastSet");
910*ebfedea0SLionel Sambuc     laddattr(&attr, &attrlen, "accountExpires");
911*ebfedea0SLionel Sambuc     laddattr(&attr, &attrlen, "userAccountControl");
912*ebfedea0SLionel Sambuc 
913*ebfedea0SLionel Sambuc     krb5_unparse_name_short(context->context, principal, &p);
914*ebfedea0SLionel Sambuc     krb5_unparse_name(context->context, principal, &u);
915*ebfedea0SLionel Sambuc 
916*ebfedea0SLionel Sambuc     /* replace @ in domain part with a / */
917*ebfedea0SLionel Sambuc     q = strrchr(p, '@');
918*ebfedea0SLionel Sambuc     if (q && (p != q && *(q - 1) != '\\'))
919*ebfedea0SLionel Sambuc 	*q = '/';
920*ebfedea0SLionel Sambuc 
921*ebfedea0SLionel Sambuc     asprintf(&filter,
922*ebfedea0SLionel Sambuc 	     "(|(userPrincipalName=%s)(servicePrincipalName=%s)(servicePrincipalName=%s))",
923*ebfedea0SLionel Sambuc 	     u, p, u);
924*ebfedea0SLionel Sambuc     free(p);
925*ebfedea0SLionel Sambuc     free(u);
926*ebfedea0SLionel Sambuc 
927*ebfedea0SLionel Sambuc     ret = ldap_search_s(CTX2LP(context), CTX2BASE(context),
928*ebfedea0SLionel Sambuc 			LDAP_SCOPE_SUBTREE,
929*ebfedea0SLionel Sambuc 			filter, attr, 0, &m);
930*ebfedea0SLionel Sambuc     free(attr);
931*ebfedea0SLionel Sambuc     if (check_ldap(context, ret))
932*ebfedea0SLionel Sambuc 	return KADM5_RPC_ERROR;
933*ebfedea0SLionel Sambuc 
934*ebfedea0SLionel Sambuc     if (ldap_count_entries(CTX2LP(context), m) > 0) {
935*ebfedea0SLionel Sambuc 	char **vals;
936*ebfedea0SLionel Sambuc 	m0 = ldap_first_entry(CTX2LP(context), m);
937*ebfedea0SLionel Sambuc 	if (m0 == NULL) {
938*ebfedea0SLionel Sambuc 	    ldap_msgfree(m);
939*ebfedea0SLionel Sambuc 	    goto fail;
940*ebfedea0SLionel Sambuc 	}
941*ebfedea0SLionel Sambuc #if 0
942*ebfedea0SLionel Sambuc 	vals = ldap_get_values(CTX2LP(context), m0, "servicePrincipalName");
943*ebfedea0SLionel Sambuc 	if (vals)
944*ebfedea0SLionel Sambuc 	    printf("servicePrincipalName %s\n", vals[0]);
945*ebfedea0SLionel Sambuc 	vals = ldap_get_values(CTX2LP(context), m0, "userPrincipalName");
946*ebfedea0SLionel Sambuc 	if (vals)
947*ebfedea0SLionel Sambuc 	    printf("userPrincipalName %s\n", vals[0]);
948*ebfedea0SLionel Sambuc 	vals = ldap_get_values(CTX2LP(context), m0, "userAccountControl");
949*ebfedea0SLionel Sambuc 	if (vals)
950*ebfedea0SLionel Sambuc 	    printf("userAccountControl %s\n", vals[0]);
951*ebfedea0SLionel Sambuc #endif
952*ebfedea0SLionel Sambuc 	entry->princ_expire_time = 0;
953*ebfedea0SLionel Sambuc 	if (mask & KADM5_PRINC_EXPIRE_TIME) {
954*ebfedea0SLionel Sambuc 	    vals = ldap_get_values(CTX2LP(context), m0, "accountExpires");
955*ebfedea0SLionel Sambuc 	    if (vals)
956*ebfedea0SLionel Sambuc 		entry->princ_expire_time = nt2unixtime(vals[0]);
957*ebfedea0SLionel Sambuc 	}
958*ebfedea0SLionel Sambuc 	entry->last_success = 0;
959*ebfedea0SLionel Sambuc 	if (mask & KADM5_LAST_SUCCESS) {
960*ebfedea0SLionel Sambuc 	    vals = ldap_get_values(CTX2LP(context), m0, "lastLogon");
961*ebfedea0SLionel Sambuc 	    if (vals)
962*ebfedea0SLionel Sambuc 		entry->last_success = nt2unixtime(vals[0]);
963*ebfedea0SLionel Sambuc 	}
964*ebfedea0SLionel Sambuc 	if (mask & KADM5_LAST_FAILED) {
965*ebfedea0SLionel Sambuc 	    vals = ldap_get_values(CTX2LP(context), m0, "badPasswordTime");
966*ebfedea0SLionel Sambuc 	    if (vals)
967*ebfedea0SLionel Sambuc 		entry->last_failed = nt2unixtime(vals[0]);
968*ebfedea0SLionel Sambuc 	}
969*ebfedea0SLionel Sambuc 	if (mask & KADM5_LAST_PWD_CHANGE) {
970*ebfedea0SLionel Sambuc 	    vals = ldap_get_values(CTX2LP(context), m0, "pwdLastSet");
971*ebfedea0SLionel Sambuc 	    if (vals)
972*ebfedea0SLionel Sambuc 		entry->last_pwd_change = nt2unixtime(vals[0]);
973*ebfedea0SLionel Sambuc 	}
974*ebfedea0SLionel Sambuc 	if (mask & KADM5_FAIL_AUTH_COUNT) {
975*ebfedea0SLionel Sambuc 	    vals = ldap_get_values(CTX2LP(context), m0, "badPwdCount");
976*ebfedea0SLionel Sambuc 	    if (vals)
977*ebfedea0SLionel Sambuc 		entry->fail_auth_count = atoi(vals[0]);
978*ebfedea0SLionel Sambuc 	}
979*ebfedea0SLionel Sambuc  	if (mask & KADM5_ATTRIBUTES) {
980*ebfedea0SLionel Sambuc 	    vals = ldap_get_values(CTX2LP(context), m0, "userAccountControl");
981*ebfedea0SLionel Sambuc 	    if (vals) {
982*ebfedea0SLionel Sambuc 		uint32_t i;
983*ebfedea0SLionel Sambuc 		i = atoi(vals[0]);
984*ebfedea0SLionel Sambuc 		if (i & (UF_ACCOUNTDISABLE|UF_LOCKOUT))
985*ebfedea0SLionel Sambuc 		    entry->attributes |= KRB5_KDB_DISALLOW_ALL_TIX;
986*ebfedea0SLionel Sambuc 		if ((i & UF_DONT_REQUIRE_PREAUTH) == 0)
987*ebfedea0SLionel Sambuc 		    entry->attributes |= KRB5_KDB_REQUIRES_PRE_AUTH;
988*ebfedea0SLionel Sambuc 		if (i & UF_SMARTCARD_REQUIRED)
989*ebfedea0SLionel Sambuc 		    entry->attributes |= KRB5_KDB_REQUIRES_HW_AUTH;
990*ebfedea0SLionel Sambuc 		if ((i & UF_WORKSTATION_TRUST_ACCOUNT) == 0)
991*ebfedea0SLionel Sambuc 		    entry->attributes |= KRB5_KDB_DISALLOW_SVR;
992*ebfedea0SLionel Sambuc 	    }
993*ebfedea0SLionel Sambuc 	}
994*ebfedea0SLionel Sambuc 	if (mask & KADM5_KVNO) {
995*ebfedea0SLionel Sambuc 	    vals = ldap_get_values(CTX2LP(context), m0,
996*ebfedea0SLionel Sambuc 				   "msDS-KeyVersionNumber");
997*ebfedea0SLionel Sambuc 	    if (vals)
998*ebfedea0SLionel Sambuc 		entry->kvno = atoi(vals[0]);
999*ebfedea0SLionel Sambuc 	    else
1000*ebfedea0SLionel Sambuc 		entry->kvno = 0;
1001*ebfedea0SLionel Sambuc 	}
1002*ebfedea0SLionel Sambuc 	ldap_msgfree(m);
1003*ebfedea0SLionel Sambuc     } else {
1004*ebfedea0SLionel Sambuc 	return KADM5_UNK_PRINC;
1005*ebfedea0SLionel Sambuc     }
1006*ebfedea0SLionel Sambuc 
1007*ebfedea0SLionel Sambuc     if (mask & KADM5_PRINCIPAL)
1008*ebfedea0SLionel Sambuc 	krb5_copy_principal(context->context, principal, &entry->principal);
1009*ebfedea0SLionel Sambuc 
1010*ebfedea0SLionel Sambuc     return 0;
1011*ebfedea0SLionel Sambuc  fail:
1012*ebfedea0SLionel Sambuc     return KADM5_RPC_ERROR;
1013*ebfedea0SLionel Sambuc #else
1014*ebfedea0SLionel Sambuc     krb5_set_error_message(context->context, KADM5_RPC_ERROR, "Function not implemented");
1015*ebfedea0SLionel Sambuc     return KADM5_RPC_ERROR;
1016*ebfedea0SLionel Sambuc #endif
1017*ebfedea0SLionel Sambuc }
1018*ebfedea0SLionel Sambuc 
1019*ebfedea0SLionel Sambuc static kadm5_ret_t
1020*ebfedea0SLionel Sambuc kadm5_ad_get_principals(void *server_handle,
1021*ebfedea0SLionel Sambuc 			const char *expression,
1022*ebfedea0SLionel Sambuc 			char ***principals,
1023*ebfedea0SLionel Sambuc 			int *count)
1024*ebfedea0SLionel Sambuc {
1025*ebfedea0SLionel Sambuc     kadm5_ad_context *context = server_handle;
1026*ebfedea0SLionel Sambuc 
1027*ebfedea0SLionel Sambuc     /*
1028*ebfedea0SLionel Sambuc      * KADM5_PRINCIPAL | KADM5_KVNO | KADM5_ATTRIBUTES
1029*ebfedea0SLionel Sambuc      */
1030*ebfedea0SLionel Sambuc 
1031*ebfedea0SLionel Sambuc #ifdef OPENLDAP
1032*ebfedea0SLionel Sambuc     kadm5_ret_t ret;
1033*ebfedea0SLionel Sambuc 
1034*ebfedea0SLionel Sambuc     ret = ad_get_cred(context, NULL);
1035*ebfedea0SLionel Sambuc     if (ret)
1036*ebfedea0SLionel Sambuc 	return ret;
1037*ebfedea0SLionel Sambuc 
1038*ebfedea0SLionel Sambuc     ret = _kadm5_ad_connect(server_handle);
1039*ebfedea0SLionel Sambuc     if (ret)
1040*ebfedea0SLionel Sambuc 	return ret;
1041*ebfedea0SLionel Sambuc 
1042*ebfedea0SLionel Sambuc     krb5_set_error_message(context->context, KADM5_RPC_ERROR, "Function not implemented");
1043*ebfedea0SLionel Sambuc     return KADM5_RPC_ERROR;
1044*ebfedea0SLionel Sambuc #else
1045*ebfedea0SLionel Sambuc     krb5_set_error_message(context->context, KADM5_RPC_ERROR, "Function not implemented");
1046*ebfedea0SLionel Sambuc     return KADM5_RPC_ERROR;
1047*ebfedea0SLionel Sambuc #endif
1048*ebfedea0SLionel Sambuc }
1049*ebfedea0SLionel Sambuc 
1050*ebfedea0SLionel Sambuc static kadm5_ret_t
1051*ebfedea0SLionel Sambuc kadm5_ad_get_privs(void *server_handle, uint32_t*privs)
1052*ebfedea0SLionel Sambuc {
1053*ebfedea0SLionel Sambuc     kadm5_ad_context *context = server_handle;
1054*ebfedea0SLionel Sambuc     krb5_set_error_message(context->context, KADM5_RPC_ERROR, "Function not implemented");
1055*ebfedea0SLionel Sambuc     return KADM5_RPC_ERROR;
1056*ebfedea0SLionel Sambuc }
1057*ebfedea0SLionel Sambuc 
1058*ebfedea0SLionel Sambuc static kadm5_ret_t
1059*ebfedea0SLionel Sambuc kadm5_ad_modify_principal(void *server_handle,
1060*ebfedea0SLionel Sambuc 			  kadm5_principal_ent_t entry,
1061*ebfedea0SLionel Sambuc 			  uint32_t mask)
1062*ebfedea0SLionel Sambuc {
1063*ebfedea0SLionel Sambuc     kadm5_ad_context *context = server_handle;
1064*ebfedea0SLionel Sambuc 
1065*ebfedea0SLionel Sambuc     /*
1066*ebfedea0SLionel Sambuc      * KADM5_ATTRIBUTES
1067*ebfedea0SLionel Sambuc      * KRB5_KDB_DISALLOW_ALL_TIX (| KADM5_KVNO)
1068*ebfedea0SLionel Sambuc      */
1069*ebfedea0SLionel Sambuc 
1070*ebfedea0SLionel Sambuc #ifdef OPENLDAP
1071*ebfedea0SLionel Sambuc     LDAPMessage *m = NULL, *m0;
1072*ebfedea0SLionel Sambuc     kadm5_ret_t ret;
1073*ebfedea0SLionel Sambuc     char **attr = NULL;
1074*ebfedea0SLionel Sambuc     int attrlen = 0;
1075*ebfedea0SLionel Sambuc     char *p = NULL, *s = NULL, *q;
1076*ebfedea0SLionel Sambuc     char **vals;
1077*ebfedea0SLionel Sambuc     LDAPMod *attrs[4], rattrs[3], *a;
1078*ebfedea0SLionel Sambuc     char *uaf[2] = { NULL, NULL };
1079*ebfedea0SLionel Sambuc     char *kvno[2] = { NULL, NULL };
1080*ebfedea0SLionel Sambuc     char *tv[2] = { NULL, NULL };
1081*ebfedea0SLionel Sambuc     char *filter, *dn;
1082*ebfedea0SLionel Sambuc     int i;
1083*ebfedea0SLionel Sambuc 
1084*ebfedea0SLionel Sambuc     for (i = 0; i < sizeof(rattrs)/sizeof(rattrs[0]); i++)
1085*ebfedea0SLionel Sambuc 	attrs[i] = &rattrs[i];
1086*ebfedea0SLionel Sambuc     attrs[i] = NULL;
1087*ebfedea0SLionel Sambuc     a = &rattrs[0];
1088*ebfedea0SLionel Sambuc 
1089*ebfedea0SLionel Sambuc     ret = _kadm5_ad_connect(server_handle);
1090*ebfedea0SLionel Sambuc     if (ret)
1091*ebfedea0SLionel Sambuc 	return ret;
1092*ebfedea0SLionel Sambuc 
1093*ebfedea0SLionel Sambuc     if (mask & KADM5_KVNO)
1094*ebfedea0SLionel Sambuc 	laddattr(&attr, &attrlen, "msDS-KeyVersionNumber");
1095*ebfedea0SLionel Sambuc     if (mask & KADM5_PRINC_EXPIRE_TIME)
1096*ebfedea0SLionel Sambuc 	laddattr(&attr, &attrlen, "accountExpires");
1097*ebfedea0SLionel Sambuc     if (mask & KADM5_ATTRIBUTES)
1098*ebfedea0SLionel Sambuc 	laddattr(&attr, &attrlen, "userAccountControl");
1099*ebfedea0SLionel Sambuc     laddattr(&attr, &attrlen, "distinguishedName");
1100*ebfedea0SLionel Sambuc 
1101*ebfedea0SLionel Sambuc     krb5_unparse_name(context->context, entry->principal, &p);
1102*ebfedea0SLionel Sambuc 
1103*ebfedea0SLionel Sambuc     s = strdup(p);
1104*ebfedea0SLionel Sambuc 
1105*ebfedea0SLionel Sambuc     q = strrchr(s, '@');
1106*ebfedea0SLionel Sambuc     if (q && (p != q && *(q - 1) != '\\'))
1107*ebfedea0SLionel Sambuc 	*q = '\0';
1108*ebfedea0SLionel Sambuc 
1109*ebfedea0SLionel Sambuc     asprintf(&filter,
1110*ebfedea0SLionel Sambuc 	     "(|(userPrincipalName=%s)(servicePrincipalName=%s))",
1111*ebfedea0SLionel Sambuc 	     s, s);
1112*ebfedea0SLionel Sambuc     free(p);
1113*ebfedea0SLionel Sambuc     free(s);
1114*ebfedea0SLionel Sambuc 
1115*ebfedea0SLionel Sambuc     ret = ldap_search_s(CTX2LP(context), CTX2BASE(context),
1116*ebfedea0SLionel Sambuc 			LDAP_SCOPE_SUBTREE,
1117*ebfedea0SLionel Sambuc 			filter, attr, 0, &m);
1118*ebfedea0SLionel Sambuc     free(attr);
1119*ebfedea0SLionel Sambuc     free(filter);
1120*ebfedea0SLionel Sambuc     if (check_ldap(context, ret))
1121*ebfedea0SLionel Sambuc 	return KADM5_RPC_ERROR;
1122*ebfedea0SLionel Sambuc 
1123*ebfedea0SLionel Sambuc     if (ldap_count_entries(CTX2LP(context), m) <= 0) {
1124*ebfedea0SLionel Sambuc 	ret = KADM5_RPC_ERROR;
1125*ebfedea0SLionel Sambuc 	goto out;
1126*ebfedea0SLionel Sambuc     }
1127*ebfedea0SLionel Sambuc 
1128*ebfedea0SLionel Sambuc     m0 = ldap_first_entry(CTX2LP(context), m);
1129*ebfedea0SLionel Sambuc 
1130*ebfedea0SLionel Sambuc     if (mask & KADM5_ATTRIBUTES) {
1131*ebfedea0SLionel Sambuc 	int32_t i;
1132*ebfedea0SLionel Sambuc 
1133*ebfedea0SLionel Sambuc 	vals = ldap_get_values(CTX2LP(context), m0, "userAccountControl");
1134*ebfedea0SLionel Sambuc 	if (vals == NULL) {
1135*ebfedea0SLionel Sambuc 	    ret = KADM5_RPC_ERROR;
1136*ebfedea0SLionel Sambuc 	    goto out;
1137*ebfedea0SLionel Sambuc 	}
1138*ebfedea0SLionel Sambuc 
1139*ebfedea0SLionel Sambuc 	i = atoi(vals[0]);
1140*ebfedea0SLionel Sambuc 	if (i == 0)
1141*ebfedea0SLionel Sambuc 	    return KADM5_RPC_ERROR;
1142*ebfedea0SLionel Sambuc 
1143*ebfedea0SLionel Sambuc 	if (entry->attributes & KRB5_KDB_DISALLOW_ALL_TIX)
1144*ebfedea0SLionel Sambuc 	    i |= (UF_ACCOUNTDISABLE|UF_LOCKOUT);
1145*ebfedea0SLionel Sambuc 	else
1146*ebfedea0SLionel Sambuc 	    i &= ~(UF_ACCOUNTDISABLE|UF_LOCKOUT);
1147*ebfedea0SLionel Sambuc 	if (entry->attributes & KRB5_KDB_REQUIRES_PRE_AUTH)
1148*ebfedea0SLionel Sambuc 	    i &= ~UF_DONT_REQUIRE_PREAUTH;
1149*ebfedea0SLionel Sambuc 	else
1150*ebfedea0SLionel Sambuc 	    i |= UF_DONT_REQUIRE_PREAUTH;
1151*ebfedea0SLionel Sambuc 	if (entry->attributes & KRB5_KDB_REQUIRES_HW_AUTH)
1152*ebfedea0SLionel Sambuc 	    i |= UF_SMARTCARD_REQUIRED;
1153*ebfedea0SLionel Sambuc 	else
1154*ebfedea0SLionel Sambuc 	    i &= UF_SMARTCARD_REQUIRED;
1155*ebfedea0SLionel Sambuc 	if (entry->attributes & KRB5_KDB_DISALLOW_SVR)
1156*ebfedea0SLionel Sambuc 	    i &= ~UF_WORKSTATION_TRUST_ACCOUNT;
1157*ebfedea0SLionel Sambuc 	else
1158*ebfedea0SLionel Sambuc 	    i |= UF_WORKSTATION_TRUST_ACCOUNT;
1159*ebfedea0SLionel Sambuc 
1160*ebfedea0SLionel Sambuc 	asprintf(&uaf[0], "%d", i);
1161*ebfedea0SLionel Sambuc 
1162*ebfedea0SLionel Sambuc 	a->mod_op = LDAP_MOD_REPLACE;
1163*ebfedea0SLionel Sambuc 	a->mod_type = "userAccountControl";
1164*ebfedea0SLionel Sambuc 	a->mod_values = uaf;
1165*ebfedea0SLionel Sambuc 	a++;
1166*ebfedea0SLionel Sambuc     }
1167*ebfedea0SLionel Sambuc 
1168*ebfedea0SLionel Sambuc     if (mask & KADM5_KVNO) {
1169*ebfedea0SLionel Sambuc 	vals = ldap_get_values(CTX2LP(context), m0, "msDS-KeyVersionNumber");
1170*ebfedea0SLionel Sambuc 	if (vals == NULL) {
1171*ebfedea0SLionel Sambuc 	    entry->kvno = 0;
1172*ebfedea0SLionel Sambuc 	} else {
1173*ebfedea0SLionel Sambuc 	    asprintf(&kvno[0], "%d", entry->kvno);
1174*ebfedea0SLionel Sambuc 
1175*ebfedea0SLionel Sambuc 	    a->mod_op = LDAP_MOD_REPLACE;
1176*ebfedea0SLionel Sambuc 	    a->mod_type = "msDS-KeyVersionNumber";
1177*ebfedea0SLionel Sambuc 	    a->mod_values = kvno;
1178*ebfedea0SLionel Sambuc 	    a++;
1179*ebfedea0SLionel Sambuc 	}
1180*ebfedea0SLionel Sambuc     }
1181*ebfedea0SLionel Sambuc 
1182*ebfedea0SLionel Sambuc     if (mask & KADM5_PRINC_EXPIRE_TIME) {
1183*ebfedea0SLionel Sambuc 	long long wt;
1184*ebfedea0SLionel Sambuc 	vals = ldap_get_values(CTX2LP(context), m0, "accountExpires");
1185*ebfedea0SLionel Sambuc 	if (vals == NULL) {
1186*ebfedea0SLionel Sambuc 	    ret = KADM5_RPC_ERROR;
1187*ebfedea0SLionel Sambuc 	    goto out;
1188*ebfedea0SLionel Sambuc 	}
1189*ebfedea0SLionel Sambuc 
1190*ebfedea0SLionel Sambuc 	wt = unix2nttime(entry->princ_expire_time);
1191*ebfedea0SLionel Sambuc 
1192*ebfedea0SLionel Sambuc 	asprintf(&tv[0], "%llu", wt);
1193*ebfedea0SLionel Sambuc 
1194*ebfedea0SLionel Sambuc 	a->mod_op = LDAP_MOD_REPLACE;
1195*ebfedea0SLionel Sambuc 	a->mod_type = "accountExpires";
1196*ebfedea0SLionel Sambuc 	a->mod_values = tv;
1197*ebfedea0SLionel Sambuc 	a++;
1198*ebfedea0SLionel Sambuc     }
1199*ebfedea0SLionel Sambuc 
1200*ebfedea0SLionel Sambuc     vals = ldap_get_values(CTX2LP(context), m0, "distinguishedName");
1201*ebfedea0SLionel Sambuc     if (vals == NULL) {
1202*ebfedea0SLionel Sambuc 	ret = KADM5_RPC_ERROR;
1203*ebfedea0SLionel Sambuc 	goto out;
1204*ebfedea0SLionel Sambuc     }
1205*ebfedea0SLionel Sambuc     dn = vals[0];
1206*ebfedea0SLionel Sambuc 
1207*ebfedea0SLionel Sambuc     attrs[a - &rattrs[0]] = NULL;
1208*ebfedea0SLionel Sambuc 
1209*ebfedea0SLionel Sambuc     ret = ldap_modify_s(CTX2LP(context), dn, attrs);
1210*ebfedea0SLionel Sambuc     if (check_ldap(context, ret))
1211*ebfedea0SLionel Sambuc 	return KADM5_RPC_ERROR;
1212*ebfedea0SLionel Sambuc 
1213*ebfedea0SLionel Sambuc  out:
1214*ebfedea0SLionel Sambuc     if (m)
1215*ebfedea0SLionel Sambuc 	ldap_msgfree(m);
1216*ebfedea0SLionel Sambuc     if (uaf[0])
1217*ebfedea0SLionel Sambuc 	free(uaf[0]);
1218*ebfedea0SLionel Sambuc     if (kvno[0])
1219*ebfedea0SLionel Sambuc 	free(kvno[0]);
1220*ebfedea0SLionel Sambuc     if (tv[0])
1221*ebfedea0SLionel Sambuc 	free(tv[0]);
1222*ebfedea0SLionel Sambuc     return ret;
1223*ebfedea0SLionel Sambuc #else
1224*ebfedea0SLionel Sambuc     krb5_set_error_message(context->context, KADM5_RPC_ERROR, "Function not implemented");
1225*ebfedea0SLionel Sambuc     return KADM5_RPC_ERROR;
1226*ebfedea0SLionel Sambuc #endif
1227*ebfedea0SLionel Sambuc }
1228*ebfedea0SLionel Sambuc 
1229*ebfedea0SLionel Sambuc static kadm5_ret_t
1230*ebfedea0SLionel Sambuc kadm5_ad_randkey_principal(void *server_handle,
1231*ebfedea0SLionel Sambuc 			   krb5_principal principal,
1232*ebfedea0SLionel Sambuc 			   krb5_keyblock **keys,
1233*ebfedea0SLionel Sambuc 			   int *n_keys)
1234*ebfedea0SLionel Sambuc {
1235*ebfedea0SLionel Sambuc     kadm5_ad_context *context = server_handle;
1236*ebfedea0SLionel Sambuc 
1237*ebfedea0SLionel Sambuc     /*
1238*ebfedea0SLionel Sambuc      * random key
1239*ebfedea0SLionel Sambuc      */
1240*ebfedea0SLionel Sambuc 
1241*ebfedea0SLionel Sambuc #ifdef OPENLDAP
1242*ebfedea0SLionel Sambuc     krb5_data result_code_string, result_string;
1243*ebfedea0SLionel Sambuc     int result_code, plen;
1244*ebfedea0SLionel Sambuc     kadm5_ret_t ret;
1245*ebfedea0SLionel Sambuc     char *password;
1246*ebfedea0SLionel Sambuc 
1247*ebfedea0SLionel Sambuc     *keys = NULL;
1248*ebfedea0SLionel Sambuc     *n_keys = 0;
1249*ebfedea0SLionel Sambuc 
1250*ebfedea0SLionel Sambuc     {
1251*ebfedea0SLionel Sambuc 	char p[64];
1252*ebfedea0SLionel Sambuc 	krb5_generate_random_block(p, sizeof(p));
1253*ebfedea0SLionel Sambuc 	plen = base64_encode(p, sizeof(p), &password);
1254*ebfedea0SLionel Sambuc 	if (plen < 0)
1255*ebfedea0SLionel Sambuc 	    return ENOMEM;
1256*ebfedea0SLionel Sambuc     }
1257*ebfedea0SLionel Sambuc 
1258*ebfedea0SLionel Sambuc     ret = ad_get_cred(context, NULL);
1259*ebfedea0SLionel Sambuc     if (ret) {
1260*ebfedea0SLionel Sambuc 	free(password);
1261*ebfedea0SLionel Sambuc 	return ret;
1262*ebfedea0SLionel Sambuc     }
1263*ebfedea0SLionel Sambuc 
1264*ebfedea0SLionel Sambuc     krb5_data_zero (&result_code_string);
1265*ebfedea0SLionel Sambuc     krb5_data_zero (&result_string);
1266*ebfedea0SLionel Sambuc 
1267*ebfedea0SLionel Sambuc     ret = krb5_set_password_using_ccache (context->context,
1268*ebfedea0SLionel Sambuc 					  context->ccache,
1269*ebfedea0SLionel Sambuc 					  password,
1270*ebfedea0SLionel Sambuc 					  principal,
1271*ebfedea0SLionel Sambuc 					  &result_code,
1272*ebfedea0SLionel Sambuc 					  &result_code_string,
1273*ebfedea0SLionel Sambuc 					  &result_string);
1274*ebfedea0SLionel Sambuc 
1275*ebfedea0SLionel Sambuc     krb5_data_free (&result_code_string);
1276*ebfedea0SLionel Sambuc     krb5_data_free (&result_string);
1277*ebfedea0SLionel Sambuc 
1278*ebfedea0SLionel Sambuc     if (ret == 0) {
1279*ebfedea0SLionel Sambuc 
1280*ebfedea0SLionel Sambuc 	*keys = malloc(sizeof(**keys) * 1);
1281*ebfedea0SLionel Sambuc 	if (*keys == NULL) {
1282*ebfedea0SLionel Sambuc 	    ret = ENOMEM;
1283*ebfedea0SLionel Sambuc 	    goto out;
1284*ebfedea0SLionel Sambuc 	}
1285*ebfedea0SLionel Sambuc 	*n_keys = 1;
1286*ebfedea0SLionel Sambuc 
1287*ebfedea0SLionel Sambuc 	ret = krb5_string_to_key(context->context,
1288*ebfedea0SLionel Sambuc 				 ENCTYPE_ARCFOUR_HMAC_MD5,
1289*ebfedea0SLionel Sambuc 				 password,
1290*ebfedea0SLionel Sambuc 				 principal,
1291*ebfedea0SLionel Sambuc 				 &(*keys)[0]);
1292*ebfedea0SLionel Sambuc 	memset(password, 0, sizeof(password));
1293*ebfedea0SLionel Sambuc 	if (ret) {
1294*ebfedea0SLionel Sambuc 	    free(*keys);
1295*ebfedea0SLionel Sambuc 	    *keys = NULL;
1296*ebfedea0SLionel Sambuc 	    *n_keys = 0;
1297*ebfedea0SLionel Sambuc 	    goto out;
1298*ebfedea0SLionel Sambuc 	}
1299*ebfedea0SLionel Sambuc     }
1300*ebfedea0SLionel Sambuc     memset(password, 0, plen);
1301*ebfedea0SLionel Sambuc     free(password);
1302*ebfedea0SLionel Sambuc  out:
1303*ebfedea0SLionel Sambuc     return ret;
1304*ebfedea0SLionel Sambuc #else
1305*ebfedea0SLionel Sambuc     *keys = NULL;
1306*ebfedea0SLionel Sambuc     *n_keys = 0;
1307*ebfedea0SLionel Sambuc 
1308*ebfedea0SLionel Sambuc     krb5_set_error_message(context->context, KADM5_RPC_ERROR, "Function not implemented");
1309*ebfedea0SLionel Sambuc     return KADM5_RPC_ERROR;
1310*ebfedea0SLionel Sambuc #endif
1311*ebfedea0SLionel Sambuc }
1312*ebfedea0SLionel Sambuc 
1313*ebfedea0SLionel Sambuc static kadm5_ret_t
1314*ebfedea0SLionel Sambuc kadm5_ad_rename_principal(void *server_handle,
1315*ebfedea0SLionel Sambuc 			  krb5_principal from,
1316*ebfedea0SLionel Sambuc 			  krb5_principal to)
1317*ebfedea0SLionel Sambuc {
1318*ebfedea0SLionel Sambuc     kadm5_ad_context *context = server_handle;
1319*ebfedea0SLionel Sambuc     krb5_set_error_message(context->context, KADM5_RPC_ERROR, "Function not implemented");
1320*ebfedea0SLionel Sambuc     return KADM5_RPC_ERROR;
1321*ebfedea0SLionel Sambuc }
1322*ebfedea0SLionel Sambuc 
1323*ebfedea0SLionel Sambuc static kadm5_ret_t
1324*ebfedea0SLionel Sambuc kadm5_ad_chpass_principal_with_key(void *server_handle,
1325*ebfedea0SLionel Sambuc 				   krb5_principal princ,
1326*ebfedea0SLionel Sambuc 				   int n_key_data,
1327*ebfedea0SLionel Sambuc 				   krb5_key_data *key_data)
1328*ebfedea0SLionel Sambuc {
1329*ebfedea0SLionel Sambuc     kadm5_ad_context *context = server_handle;
1330*ebfedea0SLionel Sambuc     krb5_set_error_message(context->context, KADM5_RPC_ERROR, "Function not implemented");
1331*ebfedea0SLionel Sambuc     return KADM5_RPC_ERROR;
1332*ebfedea0SLionel Sambuc }
1333*ebfedea0SLionel Sambuc 
1334*ebfedea0SLionel Sambuc static void
1335*ebfedea0SLionel Sambuc set_funcs(kadm5_ad_context *c)
1336*ebfedea0SLionel Sambuc {
1337*ebfedea0SLionel Sambuc #define SET(C, F) (C)->funcs.F = kadm5_ad_ ## F
1338*ebfedea0SLionel Sambuc     SET(c, chpass_principal);
1339*ebfedea0SLionel Sambuc     SET(c, chpass_principal_with_key);
1340*ebfedea0SLionel Sambuc     SET(c, create_principal);
1341*ebfedea0SLionel Sambuc     SET(c, delete_principal);
1342*ebfedea0SLionel Sambuc     SET(c, destroy);
1343*ebfedea0SLionel Sambuc     SET(c, flush);
1344*ebfedea0SLionel Sambuc     SET(c, get_principal);
1345*ebfedea0SLionel Sambuc     SET(c, get_principals);
1346*ebfedea0SLionel Sambuc     SET(c, get_privs);
1347*ebfedea0SLionel Sambuc     SET(c, modify_principal);
1348*ebfedea0SLionel Sambuc     SET(c, randkey_principal);
1349*ebfedea0SLionel Sambuc     SET(c, rename_principal);
1350*ebfedea0SLionel Sambuc }
1351*ebfedea0SLionel Sambuc 
1352*ebfedea0SLionel Sambuc kadm5_ret_t
1353*ebfedea0SLionel Sambuc kadm5_ad_init_with_password_ctx(krb5_context context,
1354*ebfedea0SLionel Sambuc 				const char *client_name,
1355*ebfedea0SLionel Sambuc 				const char *password,
1356*ebfedea0SLionel Sambuc 				const char *service_name,
1357*ebfedea0SLionel Sambuc 				kadm5_config_params *realm_params,
1358*ebfedea0SLionel Sambuc 				unsigned long struct_version,
1359*ebfedea0SLionel Sambuc 				unsigned long api_version,
1360*ebfedea0SLionel Sambuc 				void **server_handle)
1361*ebfedea0SLionel Sambuc {
1362*ebfedea0SLionel Sambuc     kadm5_ret_t ret;
1363*ebfedea0SLionel Sambuc     kadm5_ad_context *ctx;
1364*ebfedea0SLionel Sambuc 
1365*ebfedea0SLionel Sambuc     ctx = malloc(sizeof(*ctx));
1366*ebfedea0SLionel Sambuc     if(ctx == NULL)
1367*ebfedea0SLionel Sambuc 	return ENOMEM;
1368*ebfedea0SLionel Sambuc     memset(ctx, 0, sizeof(*ctx));
1369*ebfedea0SLionel Sambuc     set_funcs(ctx);
1370*ebfedea0SLionel Sambuc 
1371*ebfedea0SLionel Sambuc     ctx->context = context;
1372*ebfedea0SLionel Sambuc     krb5_add_et_list (context, initialize_kadm5_error_table_r);
1373*ebfedea0SLionel Sambuc 
1374*ebfedea0SLionel Sambuc     ret = krb5_parse_name(ctx->context, client_name, &ctx->caller);
1375*ebfedea0SLionel Sambuc     if(ret) {
1376*ebfedea0SLionel Sambuc 	free(ctx);
1377*ebfedea0SLionel Sambuc 	return ret;
1378*ebfedea0SLionel Sambuc     }
1379*ebfedea0SLionel Sambuc 
1380*ebfedea0SLionel Sambuc     if(realm_params->mask & KADM5_CONFIG_REALM) {
1381*ebfedea0SLionel Sambuc 	ret = 0;
1382*ebfedea0SLionel Sambuc 	ctx->realm = strdup(realm_params->realm);
1383*ebfedea0SLionel Sambuc 	if (ctx->realm == NULL)
1384*ebfedea0SLionel Sambuc 	    ret = ENOMEM;
1385*ebfedea0SLionel Sambuc     } else
1386*ebfedea0SLionel Sambuc 	ret = krb5_get_default_realm(ctx->context, &ctx->realm);
1387*ebfedea0SLionel Sambuc     if (ret) {
1388*ebfedea0SLionel Sambuc 	free(ctx);
1389*ebfedea0SLionel Sambuc 	return ret;
1390*ebfedea0SLionel Sambuc     }
1391*ebfedea0SLionel Sambuc 
1392*ebfedea0SLionel Sambuc     ctx->client_name = strdup(client_name);
1393*ebfedea0SLionel Sambuc 
1394*ebfedea0SLionel Sambuc     if(password != NULL && *password != '\0')
1395*ebfedea0SLionel Sambuc 	ret = ad_get_cred(ctx, password);
1396*ebfedea0SLionel Sambuc     else
1397*ebfedea0SLionel Sambuc 	ret = ad_get_cred(ctx, NULL);
1398*ebfedea0SLionel Sambuc     if(ret) {
1399*ebfedea0SLionel Sambuc 	kadm5_ad_destroy(ctx);
1400*ebfedea0SLionel Sambuc 	return ret;
1401*ebfedea0SLionel Sambuc     }
1402*ebfedea0SLionel Sambuc 
1403*ebfedea0SLionel Sambuc #ifdef OPENLDAP
1404*ebfedea0SLionel Sambuc     ret = _kadm5_ad_connect(ctx);
1405*ebfedea0SLionel Sambuc     if (ret) {
1406*ebfedea0SLionel Sambuc 	kadm5_ad_destroy(ctx);
1407*ebfedea0SLionel Sambuc 	return ret;
1408*ebfedea0SLionel Sambuc     }
1409*ebfedea0SLionel Sambuc #endif
1410*ebfedea0SLionel Sambuc 
1411*ebfedea0SLionel Sambuc     *server_handle = ctx;
1412*ebfedea0SLionel Sambuc     return 0;
1413*ebfedea0SLionel Sambuc }
1414*ebfedea0SLionel Sambuc 
1415*ebfedea0SLionel Sambuc kadm5_ret_t
1416*ebfedea0SLionel Sambuc kadm5_ad_init_with_password(const char *client_name,
1417*ebfedea0SLionel Sambuc 			    const char *password,
1418*ebfedea0SLionel Sambuc 			    const char *service_name,
1419*ebfedea0SLionel Sambuc 			    kadm5_config_params *realm_params,
1420*ebfedea0SLionel Sambuc 			    unsigned long struct_version,
1421*ebfedea0SLionel Sambuc 			    unsigned long api_version,
1422*ebfedea0SLionel Sambuc 			    void **server_handle)
1423*ebfedea0SLionel Sambuc {
1424*ebfedea0SLionel Sambuc     krb5_context context;
1425*ebfedea0SLionel Sambuc     kadm5_ret_t ret;
1426*ebfedea0SLionel Sambuc     kadm5_ad_context *ctx;
1427*ebfedea0SLionel Sambuc 
1428*ebfedea0SLionel Sambuc     ret = krb5_init_context(&context);
1429*ebfedea0SLionel Sambuc     if (ret)
1430*ebfedea0SLionel Sambuc 	return ret;
1431*ebfedea0SLionel Sambuc     ret = kadm5_ad_init_with_password_ctx(context,
1432*ebfedea0SLionel Sambuc 					  client_name,
1433*ebfedea0SLionel Sambuc 					  password,
1434*ebfedea0SLionel Sambuc 					  service_name,
1435*ebfedea0SLionel Sambuc 					  realm_params,
1436*ebfedea0SLionel Sambuc 					  struct_version,
1437*ebfedea0SLionel Sambuc 					  api_version,
1438*ebfedea0SLionel Sambuc 					  server_handle);
1439*ebfedea0SLionel Sambuc     if(ret) {
1440*ebfedea0SLionel Sambuc 	krb5_free_context(context);
1441*ebfedea0SLionel Sambuc 	return ret;
1442*ebfedea0SLionel Sambuc     }
1443*ebfedea0SLionel Sambuc     ctx = *server_handle;
1444*ebfedea0SLionel Sambuc     ctx->my_context = 1;
1445*ebfedea0SLionel Sambuc     return 0;
1446*ebfedea0SLionel Sambuc }
1447