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