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