]> andersk Git - moira.git/blame - incremental/winad/winad.c
Include object ids in args for incremental programs.
[moira.git] / incremental / winad / winad.c
CommitLineData
5d0a7127 1/* $Header$
984c91b7 2/* test parameters for creating a user account - done
bcf1ed58 3 * users 10 10 a_chen 31275 sh cmd Lastname Firstname Middlename 0 950000000 STAFF a_chen 31275 sh cmd Lastname Firstname Middlename 2 950000000 STAFF
4 * users 10 10 a_chen 31275 sh cmd Lastname Firstname Middlename 2 950000000 STAFF a_chen 31275 sh cmd Lastname Firstname Middlename 1 950000000 STAFF
984c91b7 5 * login, unix_uid, shell, winconsoleshell, last, first, middle, status, clearid, type
5d0a7127 6 *
9db0b148 7 * test parameters for deactivating/deleting a user account - done
f75f605a 8 * users 10 10 a_chen 31275 sh cmd Lastname Firstname Middlename 1 950000000 STAFF a_chen 31275 sh cmd Lastname Firstname Middlename 3 950000000 STAFF
9 * users 10 10 a_chen 31275 sh cmd Lastname Firstname Middlename 2 950000000 STAFF a_chen 31275 sh cmd Lastname Firstname Middlename 3 950000000 STAFF
984c91b7 10 * login, unix_uid, shell, winconsoleshell, last, first, middle, status, clearid, type
11 * comment: clearid is the MIT ID
cd9e6b16 12 *
984c91b7 13 * test parameters for reactivating a user account - done
14 * users 10 10 testacc 31275 sh cmd Lastname Firstname Middlename 3 950000000 STAFF testacc 31275 sh cmd Lastname Firstname Middlename 2 950000000 STAFF
15 * login, unix_uid, shell, winconsoleshell, last, first, middle, status, clearid, type
cd9e6b16 16 *
984c91b7 17 * test parameters for updating user account info - done
18 * users 10 10 testacc 31275 sh cmd Lastname Firstname Middlename 2 950000000 STAFF testacc 31275 sh cmd newLastname Firstname Middlename 2 950000000 STAFF
19 * users 10 10 6_d0006 950 sh cmd Lastname Firstname Middlename 1 900012345 STAFF 6_d0006 950 sh cmd Lastname Firstname Middlename 1 950012345 STAFF
20 * login, unix_uid, shell, winconsoleshell, last, first, middle, status, clearid, type
21 * currently, if the unix_id doesn't change, only the U_UID or U_MITID fields will be updated
78af4e6e 22 *
984c91b7 23 * test parameters for changing user name - testing
f75f605a 24 * users 10 10 a_chen 31275 sh cmd Lastname Firstname Middlename 2 950000000 STAFF testacc1 31275 sh cmd Lastname Firstname Middlename 2 950000000 STAFF
984c91b7 25 * users 10 10 testacc 31275 sh cmd Lastname Firstname Middlename 1 950000000 STAFF testacc1 31275 sh cmd Lastname Firstname Middlename 1 950000000 STAFF
26 * login, unix_uid, shell, winconsoleshell, last, first, middle, status, clearid, type
cd9e6b16 27 *
984c91b7 28 * test parameters for add member to group/list - done
29 * imembers 0 10 pismere-team USER dtanner 1 1 0 1 1 -1 1
984c91b7 30 * list_name, user_type, name, active, publicflg, hidden, maillist, grouplist, gid
cd9e6b16 31 *
984c91b7 32 * test parameters for remove member from group/list - done
33 * imembers 10 0 pismere-team USER dtanner 1 1 0 1 1 -1 1
984c91b7 34 * list_name, user_type, name, active, publicflg, hidden, maillist, grouplist, gid
cd9e6b16 35 *
9db0b148 36 * test parameters for creating and/or populating a group/list - done
984c91b7 37 * list 0 10 pismere-team 1 1 0 1 0 -1 USER 95260 description
38 * name, active, publicflg, hidden, maillist, grouplist, gid, acl_type, acl_id, description
9db0b148 39 *
40 * test parameters for deleting a group/list - done
984c91b7 41 * list 10 0 pismere-team 1 1 0 1 0 -1 USER 95260 description
42 * name, active, publicflg, hidden, maillist, grouplist, gid, acl_type, acl_id, description
9db0b148 43 *
984c91b7 44 * test parameters for renaming a group/list - done
45 * list 10 10 adtestlist 1 1 0 1 0 -1 USER 95260 description pismere-team 1 1 0 1 1 -1 USER 95260 description
46 * list 10 10 pismere-team 1 1 0 1 1 -1 USER 95260 description adtestlist1 1 1 0 1 0 -1 USER 95260 description
47 * name, active, publicflg, hidden, maillist, grouplist, gid, acl_type, acl_id, description
f75f605a 48 *
49 * test parameters for adding a file system - done
50 * filesys 0 11 addusr5 AFS ATHENA.MIT.EDU /afs/athena.mit.edu/user/a/d/addusr5 /mit/addusr5 w UserLocker addusr5 wheel 1 HOMEDIR
51 *
52 * test parameters for deleting a file system - done
53 * filesys 11 0 addusr8 AFS ATHENA.MIT.EDU /afs/athena.mit.edu/user/a/d/addusr8 /mit/addusr8 w none dtanner wheel 1 HOMEDIR
cd9e6b16 54*/
5d0a7127 55#include <mit-copyright.h>
56#ifdef _WIN32
57#include <windows.h>
58#include <stdlib.h>
59#include <malloc.h>
60#include <lmaccess.h>
61#endif
f78c7eaf 62#include <hesiod.h>
cd9e6b16 63#include <string.h>
5d0a7127 64#include <ldap.h>
65#include <stdio.h>
66#include <moira.h>
67#include <moira_site.h>
cd9e6b16 68#include <mrclient.h>
5d0a7127 69#include <krb5.h>
70#include <krb.h>
71#include <gsssasl.h>
72#include <gssldap.h>
cd9e6b16 73#include "kpasswd.h"
74
75#ifdef _WIN32
76#ifndef ECONNABORTED
77#define ECONNABORTED WSAECONNABORTED
78#endif
79#ifndef ECONNREFUSED
80#define ECONNREFUSED WSAECONNREFUSED
81#endif
82#ifndef EHOSTUNREACH
83#define EHOSTUNREACH WSAEHOSTUNREACH
84#endif
85#define krb5_xfree free
0d958b3c 86#define F_OK 0
87#define sleep(A) Sleep(A * 1000);
cd9e6b16 88#endif /* _WIN32 */
5d0a7127 89
90#ifndef _WIN32
f78c7eaf 91#include <sys/types.h>
92#include <netinet/in.h>
93#include <arpa/nameser.h>
94#include <resolv.h>
5d0a7127 95#include <sys/utsname.h>
0d958b3c 96#include <unistd.h>
5d0a7127 97
f75f605a 98#define WINADCFG "/moira/winad/winad.cfg"
f78c7eaf 99#define strnicmp(A,B,C) strncasecmp(A,B,C)
cd9e6b16 100#define UCHAR unsigned char
101
5d0a7127 102#define UF_SCRIPT 0x0001
103#define UF_ACCOUNTDISABLE 0x0002
104#define UF_HOMEDIR_REQUIRED 0x0008
105#define UF_LOCKOUT 0x0010
106#define UF_PASSWD_NOTREQD 0x0020
107#define UF_PASSWD_CANT_CHANGE 0x0040
cd9e6b16 108#define UF_DONT_EXPIRE_PASSWD 0x10000
5d0a7127 109
110#define UF_TEMP_DUPLICATE_ACCOUNT 0x0100
111#define UF_NORMAL_ACCOUNT 0x0200
112#define UF_INTERDOMAIN_TRUST_ACCOUNT 0x0800
113#define UF_WORKSTATION_TRUST_ACCOUNT 0x1000
114#define UF_SERVER_TRUST_ACCOUNT 0x2000
115
116#ifndef BYTE
117#define BYTE unsigned char
118#endif
119typedef unsigned int DWORD;
120typedef unsigned long ULONG;
121
122typedef struct _GUID
123{
124 unsigned long Data1;
125 unsigned short Data2;
126 unsigned short Data3;
127 unsigned char Data4[8];
128} GUID;
129
130typedef struct _SID_IDENTIFIER_AUTHORITY {
131 BYTE Value[6];
132} SID_IDENTIFIER_AUTHORITY, *PSID_IDENTIFIER_AUTHORITY;
133
134typedef struct _SID {
135 BYTE Revision;
136 BYTE SubAuthorityCount;
137 SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
138 DWORD SubAuthority[512];
139} SID;
140#endif/*!WIN32*/
141
f75f605a 142#ifndef WINADCFG
143#define WINADCFG "winad.cfg"
144#endif
145
f78c7eaf 146#define AFS "/afs/"
147#define WINAFS "\\\\afs\\all\\"
148
cd9e6b16 149#define ADS_GROUP_TYPE_GLOBAL_GROUP 0x00000002
f78c7eaf 150#define ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP 0x00000004
151#define ADS_GROUP_TYPE_LOCAL_GROUP 0x00000004
152#define ADS_GROUP_TYPE_UNIVERSAL_GROUP 0x00000008
153#define ADS_GROUP_TYPE_SECURITY_ENABLED 0x80000000
cd9e6b16 154
155#define QUERY_VERSION -1
156#define PRIMARY_REALM "ATHENA.MIT.EDU"
157
5d0a7127 158#define SUBSTITUTE 1
159#define REPLACE 2
160
cd9e6b16 161#define USERS 0
162#define GROUPS 1
163
5d0a7127 164#define MEMBER_ADD 1
165#define MEMBER_REMOVE 2
166#define MEMBER_CHANGE_NAME 3
167#define MEMBER_ACTIVATE 4
168#define MEMBER_DEACTIVATE 5
cd9e6b16 169#define MEMBER_CREATE 6
5d0a7127 170
f78c7eaf 171#define MOIRA_ALL 0x0
172#define MOIRA_USERS 0x1
173#define MOIRA_KERBEROS 0x2
174#define MOIRA_STRINGS 0x4
175#define MOIRA_LISTS 0x8
176
5d0a7127 177typedef struct lk_entry {
178 int op;
179 int length;
180 int ber_value;
181 char *dn;
182 char *attribute;
183 char *value;
184 char *member;
185 char *type;
186 char *list;
187 struct lk_entry *next;
188} LK_ENTRY;
189
0d958b3c 190#define STOP_FILE "/moira/winad/nowinad"
191#define file_exists(file) (access((file), F_OK) == 0)
192
5d0a7127 193#define LDAP_BERVAL struct berval
cd9e6b16 194#define MAX_SERVER_NAMES 32
195
196#define ADD_ATTR(t, v, o) \
197 mods[n] = malloc(sizeof(LDAPMod)); \
198 mods[n]->mod_op = o; \
199 mods[n]->mod_type = t; \
200 mods[n++]->mod_values = v
5d0a7127 201
202LK_ENTRY *member_base = NULL;
cd9e6b16 203LK_ENTRY *sid_base = NULL;
204LK_ENTRY **sid_ptr = NULL;
0d958b3c 205static char tbl_buf[1024];
f78c7eaf 206char kerberos_ou[] = "OU=kerberos, OU=moira";
207char contact_ou[] = "OU=strings, OU=moira";
208char user_ou[] = "OU=users, OU=moira";
209char group_ou_distribution[] = "OU=mail, OU=lists, OU=moira";
210char group_ou_root[] = "OU=lists, OU=moira";
211char group_ou_security[] = "OU=group, OU=lists, OU=moira";
212char group_ou_neither[] = "OU=special, OU=lists, OU=moira";
213char group_ou_both[] = "OU=mail, OU=group, OU=lists, OU=moira";
5d0a7127 214char *whoami;
cd9e6b16 215char ldap_domain[256];
cd9e6b16 216int mr_connections = 0;
78af4e6e 217int callback_rc;
f75f605a 218int UserReactivate = 0;
f78c7eaf 219char default_server[256];
bfb6f0ad 220static char tbl_buf[1024];
cd9e6b16 221
f78c7eaf 222extern int set_password(char *user, char *password, char *domain);
cd9e6b16 223
f78c7eaf 224void AfsToWinAfs(char* path, char* winPath);
225int ad_connect(LDAP **ldap_handle, char *ldap_domain, char *dn_path,
226 char *Win2kPassword, char *Win2kUser, char *default_server,
227 int connect_to_kdc);
228void ad_kdc_disconnect();
0d958b3c 229void check_winad(void);
f75f605a 230int filesys_process(LDAP *ldap_handle, char *dn_path, char *fs_name,
231 char *fs_type, char *fs_pack, int operation);
232int get_group_membership(char *group_membership, char *group_ou,
233 int *security_flag, char **av);
234int process_lists(int ac, char **av, void *ptr);
cd9e6b16 235int user_create(int ac, char **av, void *ptr);
f75f605a 236int user_change_status(LDAP *ldap_handle, char *dn_path, char *user_name, int operation);
cd9e6b16 237int user_delete(LDAP *ldap_handle, char *dn_path, char *u_name);
f75f605a 238int user_rename(LDAP *ldap_handle, char *dn_path, char *before_user_name,
239 char *user_name, char *Uid, char *MitId, int State);
240int user_update(LDAP *ldap_handle, char *dn_path, char *user_name,
241 char *uid, char *MitId);
cd9e6b16 242int contact_create(LDAP *ld, char *bind_path, char *user, char *group_ou);
cd9e6b16 243int group_create(int ac, char **av, void *ptr);
f75f605a 244int group_delete(LDAP *ldap_handle, char *dn_path,
245 char *group_name, char *group_membership);
246int group_rename(LDAP *ldap_handle, char *dn_path,
247 char *before_group_name, char *before_group_membership,
5a775f54 248 char *before_group_ou, int before_security_flag, char *before_desc,
f75f605a 249 char *after_group_name, char *after_group_membership,
5a775f54 250 char *after_group_ou, int after_security_flag, char *after_desc);
cd9e6b16 251int member_list_build(int ac, char **av, void *ptr);
f75f605a 252int member_add(LDAP *ldap_handle, char *dn_path, char *group_name,
253 char *group_ou, char *group_membership,
254 char *user_name, char *pUserOu);
78af4e6e 255int member_remove(LDAP *ldap_handle, char *dn_path, char *group_name,
f75f605a 256 char *group_ou, char *group_membership, char *user_name,
257 char *pUserOu);
cd9e6b16 258int sid_update(LDAP *ldap_handle, char *dn_path);
259int check_string(char *s);
260void convert_b_to_a(char *string, UCHAR *binary, int length);
261int mr_connect_cl(char *server, char *client, int version, int auth);
262
f78c7eaf 263void do_filesys(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
264 char **before, int beforec, char **after, int afterc);
265void do_list(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
266 char **before, int beforec, char **after, int afterc);
267void do_user(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
cd9e6b16 268 char **before, int beforec, char **after, int afterc);
5d0a7127 269void do_member(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
cd9e6b16 270 char **before, int beforec, char **after, int afterc);
271int linklist_create_entry(char *attribute, char *value,
272 LK_ENTRY **linklist_entry);
5d0a7127 273int linklist_build(LDAP *ldap_handle, char *dn_path, char *search_exp,
cd9e6b16 274 char **attr_array, LK_ENTRY **linklist_base,
275 int *linklist_count);
5d0a7127 276void linklist_free(LK_ENTRY *linklist_base);
cd9e6b16 277
278int retrieve_attributes(LDAP *ldap_handle, LDAPMessage *ldap_entry,
279 char *distinguished_name, LK_ENTRY **linklist_current);
280int retrieve_entries(LDAP *ldap_handle, LDAPMessage *ldap_entry,
281 LK_ENTRY **linklist_base, int *linklist_count);
282int retrieve_values(LDAP *ldap_handle, LDAPMessage *ldap_entry,
283 char *Attribute, char *distinguished_name,
284 LK_ENTRY **linklist_current);
285
286int construct_newvalues(LK_ENTRY *linklist_base, int modvalue_count,
287 char *oldValue, char *newValue,
288 char ***modvalues, int type);
289void free_values(char **modvalues);
290
291int convert_domain_to_dn(char *domain, char **bind_path);
5d0a7127 292void get_distinguished_name(LDAP *ldap_handle, LDAPMessage *ldap_entry,
cd9e6b16 293 char *distinguished_name);
5d0a7127 294int moira_disconnect(void);
295int moira_connect(void);
296void print_to_screen(const char *fmt, ...);
5d0a7127 297
298int main(int argc, char **argv)
299{
cd9e6b16 300 unsigned long rc;
301 int beforec;
302 int afterc;
cd9e6b16 303 int i;
cd9e6b16 304 char *table;
305 char **before;
306 char **after;
cd9e6b16 307 LDAP *ldap_handle;
5d0a7127 308 FILE *fptr;
f78c7eaf 309 char dn_path[256];
cd9e6b16 310
5d0a7127 311 whoami = ((whoami = (char *)strrchr(argv[0], '/')) ? whoami+1 : argv[0]);
cd9e6b16 312
313 if (argc < 4)
314 {
315 com_err(whoami, 0, "%s", "argc < 4");
316 exit(1);
317 }
318 beforec = atoi(argv[2]);
319 afterc = atoi(argv[3]);
320
321 if (argc < (4 + beforec + afterc))
322 {
323 com_err(whoami, 0, "%s", "argc < (4 + breforec + afterc)");
324 exit(1);
325 }
326
327 table = argv[1];
328 before = &argv[4];
329 after = &argv[4 + beforec];
330
bfb6f0ad 331 for (i = 1; i < argc; i++)
0d958b3c 332 {
bfb6f0ad 333 strcat(tbl_buf, argv[i]);
334 strcat(tbl_buf, " ");
0d958b3c 335 }
bfb6f0ad 336 com_err(whoami, 0, "%s", tbl_buf);
337
0d958b3c 338 check_winad();
f75f605a 339
cd9e6b16 340 memset(ldap_domain, '\0', sizeof(ldap_domain));
f75f605a 341 if ((fptr = fopen(WINADCFG, "r")) != NULL)
5d0a7127 342 {
cd9e6b16 343 fread(ldap_domain, sizeof(char), sizeof(ldap_domain), fptr);
5d0a7127 344 fclose(fptr);
345 }
cd9e6b16 346 if (strlen(ldap_domain) == 0)
9db0b148 347 strcpy(ldap_domain, "win.mit.edu");
5d0a7127 348 initialize_sms_error_table();
349 initialize_krb_error_table();
cd9e6b16 350
f78c7eaf 351 memset(default_server, '\0', sizeof(default_server));
352 memset(dn_path, '\0', sizeof(dn_path));
353 if (ad_connect(&ldap_handle, ldap_domain, dn_path, "", "", default_server, 1))
cd9e6b16 354 {
f75f605a 355 com_err(whoami, 0, "cannot connect to any server in domain %s", ldap_domain);
cd9e6b16 356 exit(1);
357 }
cd9e6b16 358
9db0b148 359 for (i = 0; i < (int)strlen(table); i++)
360 table[i] = tolower(table[i]);
5d0a7127 361 if (!strcmp(table, "users"))
f78c7eaf 362 do_user(ldap_handle, dn_path, ldap_domain, before, beforec, after,
363 afterc);
5d0a7127 364 else if (!strcmp(table, "list"))
cd9e6b16 365 do_list(ldap_handle, dn_path, ldap_domain, before, beforec, after,
366 afterc);
5d0a7127 367 else if (!strcmp(table, "imembers"))
cd9e6b16 368 do_member(ldap_handle, dn_path, ldap_domain, before, beforec, after,
369 afterc);
cd9e6b16 370 else if (!strcmp(table, "filesys"))
f78c7eaf 371 do_filesys(ldap_handle, dn_path, ldap_domain, before, beforec, after,
372 afterc);
373/*
cd9e6b16 374 else if (!strcmp(table, "quota"))
375 do_quota(before, beforec, after, afterc);
376*/
f78c7eaf 377
378 ad_kdc_disconnect();
5d0a7127 379 rc = ldap_unbind_s(ldap_handle);
5d0a7127 380 exit(0);
381}
382
f78c7eaf 383void do_filesys(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
384 char **before, int beforec, char **after, int afterc)
385{
386 long rc;
387 char *av[3];
388 char *call_args[7];
389 int acreate;
390 int atype;
391 int bcreate;
392 int btype;
f75f605a 393 int abort_flag;
f78c7eaf 394
f75f605a 395 abort_flag = 0;
f78c7eaf 396
397 if (afterc < FS_CREATE)
398 atype = acreate = 0;
399 else
400 {
401 atype = !strcmp(after[FS_TYPE], "AFS");
402 acreate = atoi(after[FS_CREATE]);
403 }
404
405 if (beforec < FS_CREATE)
406 {
407 if (acreate == 0 || atype == 0)
408 goto cleanup;
409 com_err(whoami, 0, "Processing filesys %s", after[FS_NAME]);
f75f605a 410 abort_flag = 0;
411 while (1)
412 {
413 if ((rc = filesys_process(ldap_handle, dn_path, after[FS_NAME],
414 after[FS_TYPE], after[FS_PACK], LDAP_MOD_ADD)) != LDAP_NO_SUCH_OBJECT)
415 {
416 if (rc != LDAP_SUCCESS)
417 com_err(whoami, 0, "Couldn't process filesys %s", after[FS_NAME]);
418 break;
419 }
420 if (abort_flag == 1)
421 break;
422 sleep(1);
423 abort_flag = 1;
424 if (rc = moira_connect())
425 {
426 critical_alert("AD incremental",
427 "Error contacting Moira server : %s",
428 error_message(rc));
429 return;
430 }
431 av[0] = after[FS_NAME];
432 call_args[0] = (char *)ldap_handle;
433 call_args[1] = dn_path;
434 call_args[2] = (char *)MEMBER_ACTIVATE;
435 call_args[3] = NULL;
436 sid_base = NULL;
437 sid_ptr = &sid_base;
5b8457c5 438 callback_rc = 0;
f75f605a 439 if (rc = mr_query("get_user_account_by_login", 1, av, user_create,
440 call_args))
441 {
442 moira_disconnect();
443 com_err(whoami, 0, "Couldn't process filesys %s", after[FS_NAME]);
444 break;
445 }
5b8457c5 446 if (callback_rc)
447 {
448 moira_disconnect();
449 com_err(whoami, 0, "Couldn't process filesys %s", after[FS_NAME]);
450 break;
451 }
f75f605a 452 if (sid_base != NULL)
453 {
454 sid_update(ldap_handle, dn_path);
455 linklist_free(sid_base);
456 sid_base = NULL;
457 }
458 moira_disconnect();
459 }
f78c7eaf 460 goto cleanup;
461 }
462
463 btype = !strcmp(before[FS_TYPE], "AFS");
464 bcreate = atoi(before[FS_CREATE]);
465 if (afterc < FS_CREATE)
466 {
467 if (btype && bcreate)
468 {
f75f605a 469 if (rc = filesys_process(ldap_handle, dn_path, before[FS_NAME],
470 before[FS_TYPE], before[FS_PACK], LDAP_MOD_DELETE))
f78c7eaf 471 {
f75f605a 472 com_err(whoami, 0, "Couldn't delete filesys %s", before[FS_NAME]);
f78c7eaf 473 }
474 }
f75f605a 475 return;
f78c7eaf 476 }
477
478 if (!acreate)
f75f605a 479 return;
f78c7eaf 480
481 if (!atype && !btype)
482 {
483 if (strcmp(before[FS_TYPE], "ERR") || strcmp(after[FS_TYPE], "ERR"))
484 {
f75f605a 485 com_err(whoami, 0, "Filesystem %s or %s is not AFS",
486 before[FS_NAME], after[FS_NAME]);
487 return;
f78c7eaf 488 }
489 }
490 com_err(whoami, 0, "Processing filesys %s", after[FS_NAME]);
f75f605a 491 abort_flag = 0;
492 while (1)
493 {
494 if ((rc = filesys_process(ldap_handle, dn_path, after[FS_NAME],
495 after[FS_TYPE], after[FS_PACK], LDAP_MOD_ADD)) != LDAP_NO_SUCH_OBJECT)
496 {
497 if (rc != LDAP_SUCCESS)
498 com_err(whoami, 0, "Couldn't process filesys %s", after[FS_NAME]);
499 break;
500 }
501 if (abort_flag == 1)
502 break;
503 sleep(1);
504 abort_flag = 1;
505 if (rc = moira_connect())
506 {
507 critical_alert("AD incremental",
508 "Error contacting Moira server : %s",
509 error_message(rc));
510 return;
511 }
512 av[0] = after[FS_NAME];
513 call_args[0] = (char *)ldap_handle;
514 call_args[1] = dn_path;
515 call_args[2] = (char *)MEMBER_ACTIVATE;
516 call_args[3] = NULL;
517 sid_base = NULL;
518 sid_ptr = &sid_base;
5b8457c5 519 callback_rc = 0;
f75f605a 520 if (rc = mr_query("get_user_account_by_login", 1, av, user_create,
521 call_args))
522 {
523 moira_disconnect();
524 com_err(whoami, 0, "Couldn't process filesys %s", after[FS_NAME]);
525 break;
526 }
5b8457c5 527 if (callback_rc)
528 {
529 moira_disconnect();
530 com_err(whoami, 0, "Couldn't process filesys %s", after[FS_NAME]);
531 break;
532 }
f75f605a 533 if (sid_base != NULL)
534 {
535 sid_update(ldap_handle, dn_path);
536 linklist_free(sid_base);
537 sid_base = NULL;
538 }
539 moira_disconnect();
540 }
541
f78c7eaf 542cleanup:
f78c7eaf 543 return;
544}
cd9e6b16 545void do_list(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
546 char **before, int beforec, char **after, int afterc)
5d0a7127 547{
f75f605a 548 int agid;
549 int bgid;
550 int ahide;
551 int bhide;
552 int apublic;
553 int bpublic;
554 int bgroup;
555 int agroup;
556 int amaillist;
557 int bmaillist;
558 int bstatus;
559 int astatus;
560 long rc;
561 char *av[3];
562 char *call_args[7];
563 char group_membership[1];
564 int security_flag;
565 char group_ou[256];
566 char before_group_membership[1];
567 int before_security_flag;
568 char before_group_ou[256];
569 char *pUserOu;
570 LK_ENTRY *ptr = NULL;
9db0b148 571
572 if (beforec == 0 && afterc == 0)
573 return;
574
984c91b7 575 astatus = bstatus = 0;
9db0b148 576 ahide = bhide = 0;
577 apublic = bpublic = 0;
984c91b7 578 amaillist = bmaillist = 0;
f75f605a 579 agid = 0;
580 bgid = 0;
581
582 if (beforec > L_GID && atoi(before[L_ACTIVE]))
583 {
584 bgid = atoi(before[L_GID]);
585 bstatus = atoi(before[L_ACTIVE]);
586 bhide = atoi(before[L_HIDDEN]);
587 bpublic = atoi(before[L_PUBLIC]);
588 bmaillist = atoi(before[L_MAILLIST]);
589 bgroup = atoi(before[L_GROUP]);
590 before_security_flag = 0;
591 memset(before_group_ou, '\0', sizeof(before_group_ou));
592 memset(before_group_membership, '\0', sizeof(before_group_membership));
593 get_group_membership(before_group_membership, before_group_ou, &before_security_flag, before);
594 }
595 if (afterc > L_GID && atoi(after[L_ACTIVE]))
596 {
597 agid = atoi(after[L_GID]);
598 astatus = atoi(after[L_ACTIVE]);
599 ahide = atoi(after[L_HIDDEN]);
600 apublic = atoi(after[L_PUBLIC]);
601 amaillist = atoi(after[L_MAILLIST]);
602 agroup = atoi(after[L_GROUP]);
603 security_flag = 0;
604 memset(group_ou, '\0', sizeof(group_ou));
605 memset(group_membership, '\0', sizeof(group_membership));
606 get_group_membership(group_membership, group_ou, &security_flag, after);
607 }
608 if (agid == 0 && bgid == 0)
609 return;
cd9e6b16 610
f75f605a 611 if (agid && bgid)
cd9e6b16 612 {
5a775f54 613 if ((strcmp(after[L_NAME], before[L_NAME])) ||
614 ((!strcmp(after[L_NAME], before[L_NAME])) &&
615 (strcmp(before_group_ou, group_ou))))
f75f605a 616 {
617 if (astatus && bstatus)
618 {
619 com_err(whoami, 0, "Changing list name from %s to %s",
620 before[L_NAME], after[L_NAME]);
621 if ((strlen(before_group_ou) == 0) || (strlen(before_group_membership) == 0) ||
622 (strlen(group_ou) == 0) || (strlen(group_membership) == 0))
623 {
624 com_err(whoami, 0, "%s", "couldn't find the group OU's");
625 return;
626 }
627 if ((rc = group_rename(ldap_handle, dn_path,
628 before[L_NAME], before_group_membership,
5a775f54 629 before_group_ou, before_security_flag, before[9],
f75f605a 630 after[L_NAME], group_membership,
5a775f54 631 group_ou, security_flag, after[9])) != LDAP_NO_SUCH_OBJECT)
f75f605a 632 {
633 if (rc != LDAP_SUCCESS)
634 com_err(whoami, 0, "Could not change list name from %s to %s",
635 before[L_NAME],
636 after[L_NAME]);
637 return;
638 }
639 bgid = 0;
640 }
641 if (!agid)
642 return;
643 }
644 else
645 bgid = 0;
cd9e6b16 646 }
647
f75f605a 648 if (bgid)
984c91b7 649 {
f75f605a 650 if ((strlen(before_group_ou) == 0) || (strlen(before_group_membership) == 0))
984c91b7 651 {
f75f605a 652 com_err(whoami, 0, "couldn't find the group OU for group %s", before[L_NAME]);
653 return;
654 }
984c91b7 655 com_err(whoami, 0, "Deleting group %s", before[L_NAME]);
f75f605a 656 rc = group_delete(ldap_handle, dn_path, before[L_NAME], before_group_membership);
657 return;
5d0a7127 658 }
f75f605a 659 if (agid)
5d0a7127 660 {
984c91b7 661 com_err(whoami, 0, "Creating group %s", after[L_NAME]);
cd9e6b16 662
f75f605a 663 if (rc = moira_connect())
664 {
665 critical_alert("AD incremental",
666 "Error contacting Moira server : %s",
667 error_message(rc));
668 return;
669 }
670
984c91b7 671 av[0] = after[L_NAME];
cd9e6b16 672 call_args[0] = (char *)ldap_handle;
673 call_args[1] = dn_path;
984c91b7 674 call_args[2] = after[L_NAME];
f75f605a 675 call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
cd9e6b16 676 call_args[4] = NULL;
677 sid_base = NULL;
678 sid_ptr = &sid_base;
5b8457c5 679 callback_rc = 0;
78af4e6e 680 if (rc = mr_query("get_list_info", 1, av, group_create, call_args))
cd9e6b16 681 {
f75f605a 682 moira_disconnect();
683 com_err(whoami, 0, "Couldn't create list %s : %s", after[L_NAME], error_message(rc));
684 return;
bfb6f0ad 685 }
5b8457c5 686 if (callback_rc)
687 {
688 moira_disconnect();
689 com_err(whoami, 0, "Couldn't create list %s", after[L_NAME]);
690 return;
691 }
692
cd9e6b16 693 if (sid_base != NULL)
694 {
695 sid_update(ldap_handle, dn_path);
696 linklist_free(sid_base);
f78c7eaf 697 sid_base = NULL;
cd9e6b16 698 }
699
d888e4a5 700 sleep(1);
f75f605a 701 com_err(whoami, 0, "Populating group %s", after[L_NAME]);
702 av[0] = after[L_NAME];
703 call_args[0] = (char *)ldap_handle;
704 call_args[1] = dn_path;
705 call_args[2] = after[L_NAME];
706 call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
707 call_args[4] = NULL;
78af4e6e 708 member_base = NULL;
f75f605a 709 if (rc = mr_query("get_end_members_of_list", 1, av,
710 member_list_build, call_args))
cd9e6b16 711 {
f75f605a 712 moira_disconnect();
713 com_err(whoami, 0, "Couldn't populate list %s : %s",
714 after[L_NAME], error_message(rc));
715 return;
cd9e6b16 716 }
f75f605a 717 if (member_base != NULL)
cd9e6b16 718 {
f75f605a 719 ptr = member_base;
720 while (ptr != NULL)
721 {
722 if (!strcasecmp(ptr->type, "LIST"))
723 {
724 ptr = ptr->next;
725 continue;
726 }
727 pUserOu = user_ou;
728 if (!strcasecmp(ptr->type, "STRING"))
729 {
730 if (contact_create(ldap_handle, dn_path, ptr->member, contact_ou))
731 return;
732 pUserOu = contact_ou;
733 }
734 else if (!strcasecmp(ptr->type, "KERBEROS"))
735 {
736 if (contact_create(ldap_handle, dn_path, ptr->member, kerberos_ou))
737 return;
738 pUserOu = kerberos_ou;
739 }
740 rc = member_add(ldap_handle, dn_path, after[L_NAME],
741 group_ou, group_membership, ptr->member, pUserOu);
742 ptr = ptr->next;
743 }
744 linklist_free(member_base);
745 member_base = NULL;
cd9e6b16 746 }
f75f605a 747 moira_disconnect();
5d0a7127 748 }
f75f605a 749
750 return;
5d0a7127 751}
752
f75f605a 753#define LM_EXTRA_ACTIVE (LM_END)
754#define LM_EXTRA_PUBLIC (LM_END+1)
755#define LM_EXTRA_HIDDEN (LM_END+2)
756#define LM_EXTRA_MAILLIST (LM_END+3)
757#define LM_EXTRA_GROUP (LM_END+4)
758#define LM_EXTRA_GID (LM_END+5)
759#define LM_EXTRA_END (LM_END+6)
984c91b7 760
5d0a7127 761void do_member(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
cd9e6b16 762 char **before, int beforec, char **after, int afterc)
5d0a7127 763{
cd9e6b16 764 char group_name[128];
765 char user_name[128];
9db0b148 766 char user_type[128];
cd9e6b16 767 int rc;
f75f605a 768 char group_membership[1];
769 int security_flag;
770 char group_ou[256];
771 char *args[16];
772 char **ptr;
773 char *pUserOu;
774
775 pUserOu = NULL;
776 ptr = NULL;
5d0a7127 777 if (afterc)
778 {
f75f605a 779 if (afterc < LM_EXTRA_END)
780 return;
984c91b7 781 if (!atoi(after[LM_EXTRA_ACTIVE]))
cd9e6b16 782 return;
f75f605a 783 ptr = after;
984c91b7 784 strcpy(user_name, after[LM_MEMBER]);
785 strcpy(group_name, after[LM_LIST]);
786 strcpy(user_type, after[LM_TYPE]);
9db0b148 787
5d0a7127 788 }
789 else if (beforec)
790 {
f75f605a 791 if (beforec < LM_EXTRA_END)
792 return;
984c91b7 793 if (!atoi(before[LM_EXTRA_ACTIVE]))
9db0b148 794 return;
f75f605a 795 ptr = before;
984c91b7 796 strcpy(user_name, before[LM_MEMBER]);
797 strcpy(group_name, before[LM_LIST]);
798 strcpy(user_type, before[LM_TYPE]);
5d0a7127 799 }
cd9e6b16 800
f75f605a 801 if (ptr == NULL)
802 return;
803
804 args[L_NAME] = ptr[LM_LIST];
805 args[L_ACTIVE] = ptr[LM_EXTRA_ACTIVE];
806 args[L_PUBLIC] = ptr[LM_EXTRA_PUBLIC];
807 args[L_HIDDEN] = ptr[LM_EXTRA_HIDDEN];
808 args[L_MAILLIST] = ptr[LM_EXTRA_MAILLIST];
809 args[L_GROUP] = ptr[LM_EXTRA_GROUP];
810 args[L_GID] = ptr[LM_EXTRA_GID];
811
812 security_flag = 0;
813 memset(group_ou, '\0', sizeof(group_ou));
814 get_group_membership(group_membership, group_ou, &security_flag, args);
815 if (strlen(group_ou) == 0)
cd9e6b16 816 {
f75f605a 817 com_err(whoami, 0, "couldn't find the group OU for group %s", group_name);
cd9e6b16 818 return;
819 }
f75f605a 820
821 rc = 0;
822 if (beforec)
823 {
824 if (!strcasecmp(ptr[LM_TYPE], "LIST"))
825 return;
826
827 com_err(whoami, 0, "Removing user %s from list %s", user_name, group_name);
828 pUserOu = user_ou;
829 if (!strcasecmp(ptr[LM_TYPE], "STRING"))
cd9e6b16 830 {
f75f605a 831 if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], contact_ou))
832 return;
833 pUserOu = contact_ou;
834 }
835 else if (!strcasecmp(ptr[LM_TYPE], "KERBEROS"))
836 {
837 if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], kerberos_ou))
838 return;
839 pUserOu = kerberos_ou;
840 }
841 rc = member_remove(ldap_handle, dn_path, group_name,
842 group_ou, group_membership, ptr[LM_MEMBER], pUserOu);
843 }
844 else
845 {
846 if (!strcasecmp(ptr[LM_TYPE], "LIST"))
847 return;
bfb6f0ad 848
f75f605a 849 com_err(whoami, 0, "Adding user %s to list %s", user_name, group_name);
850 pUserOu = user_ou;
851 if (!strcasecmp(ptr[LM_TYPE], "STRING"))
852 {
853 if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], contact_ou))
854 return;
855 pUserOu = contact_ou;
856 }
857 else if (!strcasecmp(ptr[LM_TYPE], "KERBEROS"))
858 {
859 if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], kerberos_ou))
860 return;
861 pUserOu = kerberos_ou;
cd9e6b16 862 }
f75f605a 863 rc = member_add(ldap_handle, dn_path, group_name,
864 group_ou, group_membership, ptr[LM_MEMBER], pUserOu);
cd9e6b16 865 }
866 if (rc)
867 {
868 if (afterc)
f75f605a 869 com_err(whoami, 0, "Couldn't add %s to group %s", user_name, group_name);
cd9e6b16 870 else
f75f605a 871 com_err(whoami, 0, "Couldn't remove %s to group %s", user_name, group_name);
872 }
873 return;
5d0a7127 874}
875
cd9e6b16 876
f78c7eaf 877void do_user(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
878 char **before, int beforec, char **after,
cd9e6b16 879 int afterc)
5d0a7127 880{
984c91b7 881 int rc;
882 char *av[2];
883 char *call_args[6];
884 int astate;
885 int bstate;
886
5b8457c5 887 if ((beforec == 0) && (afterc == 0))
984c91b7 888 return;
889
890 astate = 0;
891 bstate = 0;
892 if (afterc > U_STATE)
893 astate = atoi(after[U_STATE]);
894 if (beforec > U_STATE)
895 bstate = atoi(before[U_STATE]);
896
897 if (astate == 2)
898 astate = 1;
899 if (bstate == 2)
900 bstate = 1;
901
902 if ((bstate == 0) && (astate == 0))
903 return;
cd9e6b16 904
984c91b7 905 if (astate == bstate)
78af4e6e 906 {
984c91b7 907 if (!strcmp(before[U_NAME], after[U_NAME]))
78af4e6e 908 {
984c91b7 909 com_err(whoami, 0, "Updating user %s info", before[U_NAME]);
f75f605a 910 rc = user_update(ldap_handle, dn_path, before[U_NAME],
911 before[U_UID], before[U_MITID]);
912 return;
78af4e6e 913 }
bcf1ed58 914 else
cd9e6b16 915 {
bcf1ed58 916 com_err(whoami, 0, "Changing user %s to %s", before[U_NAME],
917 after[U_NAME]);
f75f605a 918 if ((rc = user_rename(ldap_handle, dn_path, before[U_NAME],
919 after[U_NAME], after[U_UID], after[U_MITID],
920 atoi(after[U_STATE]))) != LDAP_NO_SUCH_OBJECT)
78af4e6e 921 {
f75f605a 922 if (rc != LDAP_SUCCESS)
bcf1ed58 923 {
f75f605a 924 com_err(whoami, 0, "Could not change user %s to %s : %s",
925 before[U_NAME],
926 after[U_NAME], error_message(rc));
bcf1ed58 927 }
f75f605a 928 return;
78af4e6e 929 }
cd9e6b16 930 }
984c91b7 931 bstate = 0;
5d0a7127 932 }
f75f605a 933
984c91b7 934 if (bstate == 1)
5d0a7127 935 {
984c91b7 936 com_err(whoami, 0, "Deactivate user %s in the AD", before[U_NAME]);
f75f605a 937
938 if ((rc = user_change_status(ldap_handle, dn_path, before[U_NAME],
939 MEMBER_DEACTIVATE)) != LDAP_SUCCESS)
cd9e6b16 940 {
f75f605a 941 com_err(whoami, 0, "Couldn't deactivate user %s in the AD", before[U_NAME]);
cd9e6b16 942 }
f75f605a 943 return;
5d0a7127 944 }
f75f605a 945
984c91b7 946 if (astate == 1)
5d0a7127 947 {
f75f605a 948 if (rc = moira_connect())
949 {
950 critical_alert("AD incremental",
951 "Error connection to Moira : %s",
952 error_message(rc));
953 return;
954 }
955 com_err(whoami, 0, "Creating/Reactivating user %s", after[U_NAME]);
5d0a7127 956
984c91b7 957 av[0] = after[U_NAME];
cd9e6b16 958 call_args[0] = (char *)ldap_handle;
959 call_args[1] = dn_path;
9db0b148 960 call_args[2] = (char *)MEMBER_ACTIVATE;
961 call_args[3] = NULL;
cd9e6b16 962 sid_base = NULL;
963 sid_ptr = &sid_base;
f75f605a 964 UserReactivate = 0;
5b8457c5 965 callback_rc = 0;
cd9e6b16 966 if (rc = mr_query("get_user_account_by_login", 1, av, user_create,
967 call_args))
968 {
f75f605a 969 moira_disconnect();
970 com_err(whoami, 0, "Couldn't create/activate user %s : %s",
971 after[U_NAME], error_message(rc));
972 return;
cd9e6b16 973 }
5b8457c5 974 if (callback_rc)
975 {
976 moira_disconnect();
977 com_err(whoami, 0, "Couldn't create/activate user %s", after[U_NAME]);
978 return;
979 }
f75f605a 980 sleep(1);
cd9e6b16 981 if (sid_base != NULL)
982 {
983 sid_update(ldap_handle, dn_path);
984 linklist_free(sid_base);
985 }
f75f605a 986 if (UserReactivate)
987 {
988 av[0] = "ruser";
989 av[1] = after[U_NAME];
990 call_args[0] = (char *)ldap_handle;
991 call_args[1] = dn_path;
992 call_args[2] = after[U_NAME];
993 call_args[3] = user_ou;
994 rc = mr_query("get_lists_of_member", 2, av, process_lists,
995 call_args);
996 if (rc && rc != MR_NO_MATCH)
997 {
998 com_err(whoami, 0, "Couldn't retrieve membership of user %s: %s",
999 after[U_NAME], error_message(rc));
1000 }
1001 }
1002 moira_disconnect();
cd9e6b16 1003 }
f75f605a 1004
1005 return;
5d0a7127 1006}
1007
1008int construct_newvalues(LK_ENTRY *linklist_base, int modvalue_count,
cd9e6b16 1009 char *oldValue, char *newValue,
1010 char ***modvalues, int type)
5d0a7127 1011{
cd9e6b16 1012 LK_ENTRY *linklist_ptr;
1013 int i;
1014 char *cPtr;
5d0a7127 1015
cd9e6b16 1016 if (((*modvalues) = calloc(1, (modvalue_count + 1) * sizeof(char *)))
1017 == NULL)
1018 {
1019 return(1);
1020 }
5d0a7127 1021 for (i = 0; i < (modvalue_count + 1); i++)
cd9e6b16 1022 (*modvalues)[i] = NULL;
5d0a7127 1023 if (modvalue_count != 0)
1024 {
1025 linklist_ptr = linklist_base;
1026 for (i = 0; i < modvalue_count; i++)
cd9e6b16 1027 {
1028 if ((oldValue != NULL) && (newValue != NULL))
1029 {
1030 if ((cPtr = (char *)strstr(linklist_ptr->value, oldValue))
1031 != (char *)NULL)
1032 {
1033 if (type == REPLACE)
1034 {
1035 if (((*modvalues)[i] = calloc(1, strlen(newValue) + 1))
1036 == NULL)
1037 return(1);
1038 memset((*modvalues)[i], '\0', strlen(newValue) + 1);
1039 strcpy((*modvalues)[i], newValue);
1040 }
1041 else
1042 {
1043 if (((*modvalues)[i] = calloc(1,
1044 (int)(cPtr - linklist_ptr->value) +
1045 (linklist_ptr->length - strlen(oldValue)) +
1046 strlen(newValue) + 1)) == NULL)
1047 return(1);
1048 memset((*modvalues)[i], '\0',
1049 (int)(cPtr - linklist_ptr->value) +
1050 (linklist_ptr->length - strlen(oldValue)) +
1051 strlen(newValue) + 1);
1052 memcpy((*modvalues)[i], linklist_ptr->value,
1053 (int)(cPtr - linklist_ptr->value));
1054 strcat((*modvalues)[i], newValue);
1055 strcat((*modvalues)[i],
1056 &linklist_ptr->value[(int)(cPtr - linklist_ptr->value) + strlen(oldValue)]);
1057 }
1058 }
1059 else
1060 {
1061 (*modvalues)[i] = calloc(1, linklist_ptr->length + 1);
1062 memset((*modvalues)[i], '\0', linklist_ptr->length + 1);
1063 memcpy((*modvalues)[i], linklist_ptr->value,
1064 linklist_ptr->length);
1065 }
1066 }
1067 else
1068 {
1069 (*modvalues)[i] = calloc(1, linklist_ptr->length + 1);
1070 memset((*modvalues)[i], '\0', linklist_ptr->length + 1);
1071 memcpy((*modvalues)[i], linklist_ptr->value,
1072 linklist_ptr->length);
1073 }
1074 linklist_ptr = linklist_ptr->next;
1075 }
1076 (*modvalues)[i] = NULL;
5d0a7127 1077 }
1078 return(0);
1079}
1080
cd9e6b16 1081
5d0a7127 1082int linklist_build(LDAP *ldap_handle, char *dn_path, char *search_exp,
cd9e6b16 1083 char **attr_array, LK_ENTRY **linklist_base,
1084 int *linklist_count)
5d0a7127 1085{
cd9e6b16 1086 ULONG rc;
5d0a7127 1087 LDAPMessage *ldap_entry;
cd9e6b16 1088
1089 rc = 0;
5d0a7127 1090 ldap_entry = NULL;
1091 (*linklist_base) = NULL;
1092 (*linklist_count) = 0;
1093 if ((rc = ldap_search_s(ldap_handle, dn_path, LDAP_SCOPE_SUBTREE,
cd9e6b16 1094 search_exp, attr_array, 0, &ldap_entry))
5d0a7127 1095 != LDAP_SUCCESS)
1096 return(0);
cd9e6b16 1097 rc = retrieve_entries(ldap_handle, ldap_entry, linklist_base, linklist_count);
1098
5d0a7127 1099 ldap_msgfree(ldap_entry);
1100 return(rc);
1101}
1102
cd9e6b16 1103
5d0a7127 1104int retrieve_entries(LDAP *ldap_handle, LDAPMessage *ldap_entry,
cd9e6b16 1105 LK_ENTRY **linklist_base, int *linklist_count)
5d0a7127 1106{
cd9e6b16 1107 char distinguished_name[1024];
1108 LK_ENTRY *linklist_ptr;
1109 int rc;
1110
5d0a7127 1111 if ((ldap_entry = ldap_first_entry(ldap_handle, ldap_entry)) == NULL)
1112 return(0);
cd9e6b16 1113
1114 memset(distinguished_name, '\0', sizeof(distinguished_name));
1115 get_distinguished_name(ldap_handle, ldap_entry, distinguished_name);
1116
1117 if ((rc = retrieve_attributes(ldap_handle, ldap_entry, distinguished_name,
1118 linklist_base)) != 0)
5d0a7127 1119 return(rc);
cd9e6b16 1120
5d0a7127 1121 while ((ldap_entry = ldap_next_entry(ldap_handle, ldap_entry)) != NULL)
1122 {
cd9e6b16 1123 memset(distinguished_name, '\0', sizeof(distinguished_name));
1124 get_distinguished_name(ldap_handle, ldap_entry, distinguished_name);
1125
1126 if ((rc = retrieve_attributes(ldap_handle, ldap_entry, distinguished_name,
1127 linklist_base)) != 0)
1128 return(rc);
5d0a7127 1129 }
cd9e6b16 1130
5d0a7127 1131 linklist_ptr = (*linklist_base);
1132 (*linklist_count) = 0;
1133 while (linklist_ptr != NULL)
1134 {
1135 ++(*linklist_count);
1136 linklist_ptr = linklist_ptr->next;
1137 }
1138 return(0);
1139}
1140
1141int retrieve_attributes(LDAP *ldap_handle, LDAPMessage *ldap_entry,
cd9e6b16 1142 char *distinguished_name, LK_ENTRY **linklist_current)
5d0a7127 1143{
cd9e6b16 1144 char *Attribute;
1145 BerElement *ptr;
1146
5d0a7127 1147 ptr = NULL;
cd9e6b16 1148 if ((Attribute = ldap_first_attribute(ldap_handle, ldap_entry, &ptr)) != NULL)
5d0a7127 1149 {
cd9e6b16 1150 retrieve_values(ldap_handle, ldap_entry, Attribute, distinguished_name,
1151 linklist_current);
5d0a7127 1152 ldap_memfree(Attribute);
cd9e6b16 1153 while ((Attribute = ldap_next_attribute(ldap_handle, ldap_entry,
1154 ptr)) != NULL)
1155 {
1156 retrieve_values(ldap_handle, ldap_entry, Attribute,
1157 distinguished_name, linklist_current);
1158 ldap_memfree(Attribute);
1159 }
5d0a7127 1160 }
cd9e6b16 1161 ldap_ber_free(ptr, 0);
5d0a7127 1162 return(0);
1163}
1164
cd9e6b16 1165int retrieve_values(LDAP *ldap_handle, LDAPMessage *ldap_entry,
1166 char *Attribute, char *distinguished_name,
1167 LK_ENTRY **linklist_current)
5d0a7127 1168{
cd9e6b16 1169 char **str_value;
1170 char temp[256];
1171 void **Ptr;
1172 int use_bervalue;
1173 LK_ENTRY *linklist_previous;
5d0a7127 1174 LDAP_BERVAL **ber_value;
cd9e6b16 1175 DWORD ber_length;
5d0a7127 1176#ifdef LDAP_DEBUG
cd9e6b16 1177 SID *sid;
1178 GUID *guid;
1179 int i;
1180 int intValue;
1181 DWORD *subauth;
1182 SID_IDENTIFIER_AUTHORITY *sid_auth;
1183 unsigned char *subauth_count;
1184#endif /*LDAP_BEGUG*/
5d0a7127 1185
1186 use_bervalue = 0;
1187 memset(temp, '\0', sizeof(temp));
1188 if ((!strcmp(Attribute, "objectSid")) ||
1189 (!strcmp(Attribute, "objectGUID")))
1190 use_bervalue = 1;
cd9e6b16 1191
5d0a7127 1192 if (use_bervalue)
1193 {
1194 ber_value = ldap_get_values_len(ldap_handle, ldap_entry, Attribute);
1195 Ptr = (void **)ber_value;
1196 str_value = NULL;
cd9e6b16 1197 }
5d0a7127 1198 else
1199 {
1200 str_value = ldap_get_values(ldap_handle, ldap_entry, Attribute);
1201 Ptr = (void **)str_value;
1202 ber_value = NULL;
1203 }
1204 if (Ptr != NULL)
1205 {
1206 for (; *Ptr; Ptr++)
cd9e6b16 1207 {
1208 if ((linklist_previous = calloc(1, sizeof(LK_ENTRY))) == NULL)
1209 return(1);
1210 memset(linklist_previous, '\0', sizeof(LK_ENTRY));
1211 linklist_previous->next = (*linklist_current);
1212 (*linklist_current) = linklist_previous;
1213
1214 if (((*linklist_current)->attribute = calloc(1,
1215 strlen(Attribute) + 1)) == NULL)
1216 return(1);
1217 memset((*linklist_current)->attribute, '\0', strlen(Attribute) + 1);
1218 strcpy((*linklist_current)->attribute, Attribute);
1219 if (use_bervalue)
1220 {
1221 ber_length = (*(LDAP_BERVAL **)Ptr)->bv_len;
1222 if (((*linklist_current)->value = calloc(1, ber_length)) == NULL)
1223 return(1);
1224 memset((*linklist_current)->value, '\0', ber_length);
1225 memcpy((*linklist_current)->value, (*(LDAP_BERVAL **)Ptr)->bv_val,
1226 ber_length);
1227 (*linklist_current)->length = ber_length;
1228 }
1229 else
1230 {
1231 if (((*linklist_current)->value = calloc(1,
1232 strlen(*Ptr) + 1)) == NULL)
1233 return(1);
1234 memset((*linklist_current)->value, '\0', strlen(*Ptr) + 1);
1235 (*linklist_current)->length = strlen(*Ptr);
1236 strcpy((*linklist_current)->value, *Ptr);
1237 }
1238 (*linklist_current)->ber_value = use_bervalue;
1239 if (((*linklist_current)->dn = calloc(1,
1240 strlen(distinguished_name) + 1)) == NULL)
1241 return(1);
1242 memset((*linklist_current)->dn, '\0', strlen(distinguished_name) + 1);
1243 strcpy((*linklist_current)->dn, distinguished_name);
1244
5d0a7127 1245#ifdef LDAP_DEBUG
cd9e6b16 1246 if (!strcmp(Attribute, "objectGUID"))
1247 {
1248 guid = (GUID *)((*linklist_current)->value);
1249 sprintf(temp, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
1250 guid->Data1, guid->Data2, guid->Data3,
1251 guid->Data4[0], guid->Data4[1], guid->Data4[2],
1252 guid->Data4[3], guid->Data4[4], guid->Data4[5],
1253 guid->Data4[6], guid->Data4[7]);
1254 print_to_screen(" %20s : {%s}\n", Attribute, temp);
1255 }
1256 else if (!strcmp(Attribute, "objectSid"))
1257 {
1258 sid = (SID *)((*(LDAP_BERVAL **)Ptr)->bv_val);
5d0a7127 1259#ifdef _WIN32
cd9e6b16 1260 print_to_screen(" Revision = %d\n", sid->Revision);
1261 print_to_screen(" SID Identifier Authority:\n");
1262 sid_auth = &sid->IdentifierAuthority;
1263 if (sid_auth->Value[0])
1264 print_to_screen(" SECURITY_NULL_SID_AUTHORITY\n");
1265 else if (sid_auth->Value[1])
1266 print_to_screen(" SECURITY_WORLD_SID_AUTHORITY\n");
1267 else if (sid_auth->Value[2])
1268 print_to_screen(" SECURITY_LOCAL_SID_AUTHORITY\n");
1269 else if (sid_auth->Value[3])
1270 print_to_screen(" SECURITY_CREATOR_SID_AUTHORITY\n");
1271 else if (sid_auth->Value[5])
1272 print_to_screen(" SECURITY_NT_AUTHORITY\n");
1273 else
1274 print_to_screen(" UNKNOWN SID AUTHORITY\n");
1275 subauth_count = GetSidSubAuthorityCount(sid);
1276 print_to_screen(" SidSubAuthorityCount = %d\n",
1277 *subauth_count);
1278 print_to_screen(" SidSubAuthority:\n");
1279 for (i = 0; i < *subauth_count; i++)
1280 {
1281 if ((subauth = GetSidSubAuthority(sid, i)) != NULL)
1282 print_to_screen(" %u\n", *subauth);
1283 }
5d0a7127 1284#endif
cd9e6b16 1285 }
1286 else if ((!memcmp(Attribute, "userAccountControl",
1287 strlen("userAccountControl"))) ||
1288 (!memcmp(Attribute, "sAMAccountType",
1289 strlen("sAmAccountType"))))
1290 {
1291 intValue = atoi(*Ptr);
1292 print_to_screen(" %20s : %ld\n",Attribute, intValue);
1293 if (!memcmp(Attribute, "userAccountControl",
1294 strlen("userAccountControl")))
1295 {
1296 if (intValue & UF_ACCOUNTDISABLE)
1297 print_to_screen(" %20s : %s\n",
1298 "", "Account disabled");
1299 else
1300 print_to_screen(" %20s : %s\n",
1301 "", "Account active");
1302 if (intValue & UF_HOMEDIR_REQUIRED)
1303 print_to_screen(" %20s : %s\n",
1304 "", "Home directory required");
1305 if (intValue & UF_LOCKOUT)
1306 print_to_screen(" %20s : %s\n",
1307 "", "Account locked out");
1308 if (intValue & UF_PASSWD_NOTREQD)
1309 print_to_screen(" %20s : %s\n",
1310 "", "No password required");
1311 if (intValue & UF_PASSWD_CANT_CHANGE)
1312 print_to_screen(" %20s : %s\n",
1313 "", "Cannot change password");
1314 if (intValue & UF_TEMP_DUPLICATE_ACCOUNT)
1315 print_to_screen(" %20s : %s\n",
1316 "", "Temp duplicate account");
1317 if (intValue & UF_NORMAL_ACCOUNT)
1318 print_to_screen(" %20s : %s\n",
1319 "", "Normal account");
1320 if (intValue & UF_INTERDOMAIN_TRUST_ACCOUNT)
1321 print_to_screen(" %20s : %s\n",
1322 "", "Interdomain trust account");
1323 if (intValue & UF_WORKSTATION_TRUST_ACCOUNT)
1324 print_to_screen(" %20s : %s\n",
1325 "", "Workstation trust account");
1326 if (intValue & UF_SERVER_TRUST_ACCOUNT)
1327 print_to_screen(" %20s : %s\n",
1328 "", "Server trust account");
1329 }
1330 }
1331 else
1332 {
1333 print_to_screen(" %20s : %s\n",Attribute, *Ptr);
1334 }
5d0a7127 1335#endif /*LDAP_DEBUG*/
cd9e6b16 1336 }
5d0a7127 1337 if (str_value != NULL)
cd9e6b16 1338 ldap_value_free(str_value);
5d0a7127 1339 if (ber_value != NULL)
cd9e6b16 1340 ldap_value_free_len(ber_value);
5d0a7127 1341 }
1342 (*linklist_current) = linklist_previous;
1343 return(0);
1344}
1345
5d0a7127 1346int moira_connect(void)
1347{
cd9e6b16 1348 long rc;
1349 char HostName[64];
1350
5d0a7127 1351 if (!mr_connections++)
1352 {
1353#ifdef _WIN32
1354 memset(HostName, '\0', sizeof(HostName));
1355 strcpy(HostName, "ttsp");
cd9e6b16 1356 rc = mr_connect_cl(HostName, "winad.incr", QUERY_VERSION, 1);
1357/*det
5d0a7127 1358 rc = mr_connect(HostName);
cd9e6b16 1359*/
5d0a7127 1360#else
1361 struct utsname uts;
1362 uname(&uts);
cd9e6b16 1363 rc = mr_connect_cl(uts.nodename, "winad.incr", QUERY_VERSION, 1);
1364/*
5d0a7127 1365 rc = mr_connect(uts.nodename);
cd9e6b16 1366*/
5d0a7127 1367#endif /*WIN32*/
cd9e6b16 1368/*det
5d0a7127 1369 if (!rc)
cd9e6b16 1370 rc = mr_auth("winad.incr");
1371*/
5d0a7127 1372 return rc;
1373 }
1374 return 0;
1375}
1376
0d958b3c 1377void check_winad(void)
1378{
1379 int i;
1380
1381 for (i = 0; file_exists(STOP_FILE); i++)
1382 {
1383 if (i > 30)
1384 {
f75f605a 1385 critical_alert("AD incremental",
f78c7eaf 1386 "WINAD incremental failed (%s exists): %s",
1387 STOP_FILE, tbl_buf);
1388 exit(1);
1389 }
0d958b3c 1390 sleep(60);
1391 }
1392}
1393
5d0a7127 1394int moira_disconnect(void)
1395{
5d0a7127 1396
cd9e6b16 1397 if (!--mr_connections)
5d0a7127 1398 {
cd9e6b16 1399 mr_disconnect();
5d0a7127 1400 }
cd9e6b16 1401 return 0;
5d0a7127 1402}
1403
5d0a7127 1404void get_distinguished_name(LDAP *ldap_handle, LDAPMessage *ldap_entry,
cd9e6b16 1405 char *distinguished_name)
5d0a7127 1406{
cd9e6b16 1407 char *CName;
1408
5d0a7127 1409 CName = ldap_get_dn(ldap_handle, ldap_entry);
1410 if (CName == NULL)
1411 return;
1412 strcpy(distinguished_name, CName);
1413 ldap_memfree(CName);
1414}
1415
1416int linklist_create_entry(char *attribute, char *value,
cd9e6b16 1417 LK_ENTRY **linklist_entry)
5d0a7127 1418{
1419 (*linklist_entry) = calloc(1, sizeof(LK_ENTRY));
1420 if (!(*linklist_entry))
1421 {
1422 return(1);
1423 }
1424 memset((*linklist_entry), '\0', sizeof(LK_ENTRY));
1425 (*linklist_entry)->attribute = calloc(1, strlen(attribute) + 1);
1426 memset((*linklist_entry)->attribute, '\0', strlen(attribute) + 1);
1427 strcpy((*linklist_entry)->attribute, attribute);
1428 (*linklist_entry)->value = calloc(1, strlen(value) + 1);
1429 memset((*linklist_entry)->value, '\0', strlen(value) + 1);
1430 strcpy((*linklist_entry)->value, value);
1431 (*linklist_entry)->length = strlen(value);
1432 (*linklist_entry)->next = NULL;
1433 return(0);
1434}
1435
1436void print_to_screen(const char *fmt, ...)
1437{
1438 va_list pvar;
cd9e6b16 1439
5d0a7127 1440 va_start(pvar, fmt);
1441 vfprintf(stderr, fmt, pvar);
1442 fflush(stderr);
1443 va_end(pvar);
1444}
cd9e6b16 1445
1446int get_group_membership(char *group_membership, char *group_ou,
1447 int *security_flag, char **av)
1448{
1449 int maillist_flag;
1450 int group_flag;
1451
1452 maillist_flag = atoi(av[L_MAILLIST]);
1453 group_flag = atoi(av[L_GROUP]);
1454 if (security_flag != NULL)
1455 (*security_flag) = 0;
1456
1457 if ((maillist_flag) && (group_flag))
1458 {
1459 if (group_membership != NULL)
1460 group_membership[0] = 'B';
1461 if (security_flag != NULL)
1462 (*security_flag) = 1;
1463 if (group_ou != NULL)
1464 strcpy(group_ou, group_ou_both);
1465 }
1466 else if ((!maillist_flag) && (group_flag))
1467 {
1468 if (group_membership != NULL)
1469 group_membership[0] = 'S';
1470 if (security_flag != NULL)
1471 (*security_flag) = 1;
1472 if (group_ou != NULL)
1473 strcpy(group_ou, group_ou_security);
1474 }
1475 else if ((maillist_flag) && (!group_flag))
1476 {
1477 if (group_membership != NULL)
1478 group_membership[0] = 'D';
1479 if (group_ou != NULL)
1480 strcpy(group_ou, group_ou_distribution);
1481 }
1482 else
1483 {
1484 if (group_membership != NULL)
1485 group_membership[0] = 'N';
1486 if (group_ou != NULL)
1487 strcpy(group_ou, group_ou_neither);
1488 }
1489 return(0);
1490}
1491
f75f605a 1492int group_rename(LDAP *ldap_handle, char *dn_path,
1493 char *before_group_name, char *before_group_membership,
5a775f54 1494 char *before_group_ou, int before_security_flag, char *before_desc,
f75f605a 1495 char *after_group_name, char *after_group_membership,
5a775f54 1496 char *after_group_ou, int after_security_flag, char *after_desc)
9db0b148 1497{
1498 LDAPMod *mods[20];
1499 char old_dn[512];
1500 char new_dn[512];
78af4e6e 1501 char new_dn_path[512];
78af4e6e 1502 char sam_name[256];
9db0b148 1503 char filter_exp[4096];
1504 char *attr_array[3];
1505 char *name_v[] = {NULL, NULL};
5a775f54 1506 char *desc_v[] = {NULL, NULL};
78af4e6e 1507 char *samAccountName_v[] = {NULL, NULL};
c76c595a 1508 char *groupTypeControl_v[] = {NULL, NULL};
1509 u_int groupTypeControl = ADS_GROUP_TYPE_GLOBAL_GROUP;
1510 char groupTypeControlStr[80];
9db0b148 1511 int n;
1512 int i;
1513 int rc;
9db0b148 1514 LK_ENTRY *group_base;
1515 int group_count;
9db0b148 1516
f75f605a 1517 if (!check_string(before_group_name))
78af4e6e 1518 {
f75f605a 1519 com_err(whoami, 0, "invalid LDAP list name %s", before_group_name);
1520 return(-1);
78af4e6e 1521 }
f75f605a 1522 if (!check_string(after_group_name))
78af4e6e 1523 {
f75f605a 1524 com_err(whoami, 0, "invalid LDAP list name %s", after_group_name);
1525 return(-1);
78af4e6e 1526 }
1527
f75f605a 1528 sprintf(filter_exp, "(sAMAccountName=%s_zZx%c)", before_group_name, before_group_membership[0]);
9db0b148 1529 attr_array[0] = "distinguishedName";
1530 attr_array[1] = NULL;
f75f605a 1531 if ((rc = linklist_build(ldap_handle, dn_path, filter_exp, attr_array,
9db0b148 1532 &group_base, &group_count)) != 0)
1533 {
f75f605a 1534 com_err(whoami, 0, "LDAP server unable to get list %s dn : %s",
1535 after_group_name, ldap_err2string(rc));
1536 return(rc);
9db0b148 1537 }
1538 if (group_count != 1)
1539 {
f75f605a 1540 com_err(whoami, 0, "LDAP server unable to find list %s in AD",
1541 after_group_name);
78af4e6e 1542 callback_rc = LDAP_NO_SUCH_OBJECT;
f75f605a 1543 return(-1);
9db0b148 1544 }
1545 strcpy(old_dn, group_base->value);
1546 linklist_free(group_base);
1547 group_base = NULL;
1548 group_count = 0;
1549
f75f605a 1550 sprintf(new_dn_path, "%s,%s", after_group_ou, dn_path);
1551 sprintf(new_dn, "cn=%s", after_group_name);
1552 if ((rc = ldap_rename_s(ldap_handle, old_dn, new_dn, new_dn_path,
78af4e6e 1553 TRUE, NULL, NULL)) != LDAP_SUCCESS)
1554 {
f75f605a 1555 com_err(whoami, 0, "Couldn't rename list from %s to %s : %s",
1556 after_group_name, after_group_name, ldap_err2string(rc));
1557 return(rc);
78af4e6e 1558 }
9db0b148 1559
5a775f54 1560 sprintf(sam_name, "%s_zZx%c", after_group_name, after_group_membership[0]);
f75f605a 1561 name_v[0] = after_group_name;
78af4e6e 1562 samAccountName_v[0] = sam_name;
5a775f54 1563 desc_v[0] = after_desc;
c76c595a 1564 if (after_security_flag)
1565 groupTypeControl |= ADS_GROUP_TYPE_SECURITY_ENABLED;
1566 sprintf(groupTypeControlStr, "%ld", groupTypeControl);
1567 groupTypeControl_v[0] = groupTypeControlStr;
9db0b148 1568 n = 0;
5a775f54 1569 ADD_ATTR("samAccountName", samAccountName_v, LDAP_MOD_REPLACE);
9db0b148 1570 ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
5a775f54 1571 if (strlen(after_desc) == 0)
1572 desc_v[0] = NULL;
1573 ADD_ATTR("description", desc_v, LDAP_MOD_REPLACE);
c76c595a 1574 ADD_ATTR("groupType", groupTypeControl_v, LDAP_MOD_REPLACE);
9db0b148 1575 mods[n] = NULL;
f75f605a 1576 sprintf(new_dn, "cn=%s,%s,%s", after_group_name, after_group_ou, dn_path);
1577 if ((rc = ldap_modify_s(ldap_handle, new_dn, mods)) != LDAP_SUCCESS)
78af4e6e 1578 {
f75f605a 1579 com_err(whoami, 0, "After renaming, couldn't modify list data for %s : %s",
1580 after_group_name, ldap_err2string(rc));
78af4e6e 1581 }
9db0b148 1582 for (i = 0; i < n; i++)
1583 free(mods[i]);
f75f605a 1584 return(rc);
9db0b148 1585}
1586
cd9e6b16 1587int group_create(int ac, char **av, void *ptr)
1588{
1589 LDAPMod *mods[20];
5b8457c5 1590 LK_ENTRY *group_base;
cd9e6b16 1591 char new_dn[256];
1592 char group_ou[256];
1593 char new_group_name[256];
1594 char sam_group_name[256];
1595 char cn_group_name[256];
1596 char *cn_v[] = {NULL, NULL};
1597 char *objectClass_v[] = {"top", "group", NULL};
1598 char info[256];
1599 char *samAccountName_v[] = {NULL, NULL};
1600 char *managedBy_v[] = {NULL, NULL};
1601 char *altSecurityIdentities_v[] = {NULL, NULL};
1602 char *name_v[] = {NULL, NULL};
1603 char *desc_v[] = {NULL, NULL};
1604 char *info_v[] = {NULL, NULL};
1605 char *groupTypeControl_v[] = {NULL, NULL};
1606 char groupTypeControlStr[80];
1607 char group_membership[1];
1608 int i;
1609 int security_flag;
1610 u_int groupTypeControl = ADS_GROUP_TYPE_GLOBAL_GROUP;
1611 int n;
1612 int rc;
5b8457c5 1613 int group_count;
cd9e6b16 1614 char filter_exp[256];
1615 char *attr_array[3];
1616 char **call_args;
1617
1618 call_args = ptr;
1619
1620 if (!atoi(av[L_ACTIVE]))
f75f605a 1621 return(1);
cd9e6b16 1622 if (!check_string(av[L_NAME]))
78af4e6e 1623 {
f75f605a 1624 com_err(whoami, 0, "invalid LDAP list name %s", av[L_NAME]);
1625 return(1);
78af4e6e 1626 }
f75f605a 1627
cd9e6b16 1628 memset(group_ou, 0, sizeof(group_ou));
1629 memset(group_membership, 0, sizeof(group_membership));
1630 security_flag = 0;
1631 get_group_membership(group_membership, group_ou, &security_flag, av);
cd9e6b16 1632
1633 if (security_flag)
1634 groupTypeControl |= ADS_GROUP_TYPE_SECURITY_ENABLED;
1635 sprintf(groupTypeControlStr, "%ld", groupTypeControl);
1636 groupTypeControl_v[0] = groupTypeControlStr;
1637
1638 strcpy(new_group_name, av[L_NAME]);
cd9e6b16 1639 strcpy(cn_group_name, av[L_NAME]);
5b8457c5 1640 sprintf(sam_group_name, "%s_zZx%c", av[L_NAME], group_membership[0]);
cd9e6b16 1641
1642 samAccountName_v[0] = sam_group_name;
1643 name_v[0] = new_group_name;
9db0b148 1644 cn_v[0] = new_group_name;
cd9e6b16 1645
9db0b148 1646 sprintf(new_dn, "cn=%s,%s,%s", new_group_name, group_ou, call_args[1]);
cd9e6b16 1647 n = 0;
1648 ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
1649 ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
1650 ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
1651 ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
1652 ADD_ATTR("name", name_v, LDAP_MOD_ADD);
1653 if (strlen(av[L_DESC]) != 0)
1654 {
1655 desc_v[0] = av[L_DESC];
1656 ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
1657 }
1658 ADD_ATTR("groupType", groupTypeControl_v, LDAP_MOD_ADD);
78af4e6e 1659 if (strlen(av[L_ACE_NAME]) != 0)
cd9e6b16 1660 {
1661 sprintf(info, "The Administrator of this list is the LIST: %s", av[L_ACE_NAME]);
1662 info_v[0] = info;
1663 ADD_ATTR("info", info_v, LDAP_MOD_ADD);
1664 }
1665 mods[n] = NULL;
1666
1667 rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
1668
1669 for (i = 0; i < n; i++)
1670 free(mods[i]);
1671 if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
78af4e6e 1672 {
f75f605a 1673 com_err(whoami, 0, "Unable to create list %s in AD : %s",
1674 av[L_NAME], ldap_err2string(rc));
5b8457c5 1675 callback_rc = rc;
f75f605a 1676 return(rc);
78af4e6e 1677 }
5a775f54 1678 if (rc == LDAP_ALREADY_EXISTS)
1679 {
1680 n = 0;
1681 desc_v[0] = av[L_DESC];
1682 if (strlen(av[L_DESC]) == 0)
1683 desc_v[0] = NULL;
1684 ADD_ATTR("description", desc_v, LDAP_MOD_REPLACE);
1685 mods[n] = NULL;
1686 rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
1687 for (i = 0; i < n; i++)
1688 free(mods[i]);
1689 }
cd9e6b16 1690 sprintf(filter_exp, "(sAMAccountName=%s)", sam_group_name);
1691 attr_array[0] = "objectSid";
1692 attr_array[1] = NULL;
5b8457c5 1693 group_count = 0;
1694 group_base = NULL;
cd9e6b16 1695 if ((rc = linklist_build((LDAP *)call_args[0], call_args[1], filter_exp, attr_array,
5b8457c5 1696 &group_base, &group_count)) == LDAP_SUCCESS)
cd9e6b16 1697 {
5b8457c5 1698 if (group_count == 1)
cd9e6b16 1699 {
5b8457c5 1700 (*sid_ptr) = group_base;
cd9e6b16 1701 (*sid_ptr)->member = strdup(av[L_NAME]);
1702 (*sid_ptr)->type = (char *)GROUPS;
1703 sid_ptr = &(*sid_ptr)->next;
1704 }
5b8457c5 1705 else
1706 {
1707 if (group_base != NULL)
1708 linklist_free(group_base);
1709 }
cd9e6b16 1710 }
5b8457c5 1711 else
1712 {
1713 if (group_base != NULL)
1714 linklist_free(group_base);
1715 }
1716 return(LDAP_SUCCESS);
cd9e6b16 1717}
1718
f75f605a 1719int group_delete(LDAP *ldap_handle, char *dn_path, char *group_name, char *group_membership)
cd9e6b16 1720{
1721 LK_ENTRY *group_base;
cd9e6b16 1722 char *attr_array[3];
1723 char filter_exp[1024];
cd9e6b16 1724 char sam_group_name[256];
f75f605a 1725 char temp[512];
cd9e6b16 1726 int group_count;
1727 int rc;
1728
f75f605a 1729 if (!check_string(group_name))
78af4e6e 1730 {
f75f605a 1731 com_err(whoami, 0, "invalid LDAP list name %s", group_name);
1732 return(-1);
78af4e6e 1733 }
f75f605a 1734 rc = 1;
cd9e6b16 1735 group_count = 0;
1736 group_base = NULL;
1737 attr_array[0] = "distinguishedName";
1738 attr_array[1] = NULL;
78af4e6e 1739 strcpy(sam_group_name, group_name);
cd9e6b16 1740 sprintf(temp, "%s,%s", group_ou_root, dn_path);
f75f605a 1741 sprintf(filter_exp, "(sAMAccountName=%s_zZx%c)", group_name, group_membership[0]);
cd9e6b16 1742 if (linklist_build(ldap_handle, temp, filter_exp, attr_array,
1743 &group_base, &group_count) != 0)
f75f605a 1744 return(-1);
cd9e6b16 1745 if (group_count == 1)
78af4e6e 1746 {
1747 if ((rc = ldap_delete_s(ldap_handle, group_base->value)) != LDAP_SUCCESS)
1748 {
f75f605a 1749 linklist_free(group_base);
1750 com_err(whoami, 0, "Unable to delete list %s from AD : %s",
1751 group_name, ldap_err2string(rc));
1752 return(-1);
78af4e6e 1753 }
f75f605a 1754 linklist_free(group_base);
78af4e6e 1755 }
1756 else
1757 {
f75f605a 1758 linklist_free(group_base);
1759 com_err(whoami, 0, "Unable to find list %s in AD.", group_name);
1760 return(-1);
78af4e6e 1761 }
f75f605a 1762
78af4e6e 1763 return(0);
cd9e6b16 1764}
1765
f75f605a 1766int process_lists(int ac, char **av, void *ptr)
cd9e6b16 1767{
f75f605a 1768 int rc;
1769 int security_flag;
1770 char group_ou[256];
1771 char group_membership[2];
1772 char **call_args;
cd9e6b16 1773
1774 call_args = ptr;
1775
f75f605a 1776 security_flag = 0;
1777 memset(group_ou, '\0', sizeof(group_ou));
1778 memset(group_membership, '\0', sizeof(group_membership));
1779 get_group_membership(group_membership, group_ou, &security_flag, av);
1780 rc = member_add((LDAP *)call_args[0], (char *)call_args[1], av[L_NAME],
1781 group_ou, group_membership, call_args[2], (char *)call_args[3]);
1782 if (rc)
cd9e6b16 1783 {
f75f605a 1784 com_err(whoami, 0, "Couldn't add %s to group %s", call_args[2], av[L_NAME]);
cd9e6b16 1785 }
cd9e6b16 1786 return(0);
1787}
1788
1789int member_list_build(int ac, char **av, void *ptr)
1790{
1791 LK_ENTRY *linklist;
78af4e6e 1792 char temp[1024];
cd9e6b16 1793 char **call_args;
1794
1795 call_args = ptr;
1796
1797 strcpy(temp, av[ACE_NAME]);
1798 if (!check_string(temp))
1799 return(0);
f78c7eaf 1800 if (!strcmp(av[ACE_TYPE], "USER"))
cd9e6b16 1801 {
f75f605a 1802 if (!((int)call_args[3] & MOIRA_USERS))
f78c7eaf 1803 return(0);
1804 }
1805 else if (!strcmp(av[ACE_TYPE], "STRING"))
1806 {
f75f605a 1807 if (!((int)call_args[3] & MOIRA_STRINGS))
f78c7eaf 1808 return(0);
1809 if (contact_create((LDAP *)call_args[0], call_args[1], temp, contact_ou))
1810 return(0);
cd9e6b16 1811 }
1812 else if (!strcmp(av[ACE_TYPE], "LIST"))
1813 {
f75f605a 1814 if (!((int)call_args[3] & MOIRA_LISTS))
f78c7eaf 1815 return(0);
cd9e6b16 1816 }
f78c7eaf 1817 else if (!strcmp(av[ACE_TYPE], "KERBEROS"))
cd9e6b16 1818 {
f75f605a 1819 if (!((int)call_args[3] & MOIRA_KERBEROS))
f78c7eaf 1820 return(0);
1821 if (contact_create((LDAP *)call_args[0], call_args[1], temp, kerberos_ou))
1822 return(0);
cd9e6b16 1823 }
f78c7eaf 1824 else
1825 return(0);
1826
cd9e6b16 1827 linklist = member_base;
1828 while (linklist)
1829 {
1830 if (!strcasecmp(temp, linklist->member))
1831 return(0);
1832 linklist = linklist->next;
1833 }
1834 linklist = calloc(1, sizeof(LK_ENTRY));
1835 linklist->op = 1;
1836 linklist->dn = NULL;
1837 linklist->list = calloc(1, strlen(call_args[2]) + 1);
1838 strcpy(linklist->list, call_args[2]);
1839 linklist->type = calloc(1, strlen(av[ACE_TYPE]) + 1);
1840 strcpy(linklist->type, av[ACE_TYPE]);
1841 linklist->member = calloc(1, strlen(temp) + 1);
1842 strcpy(linklist->member, temp);
1843 linklist->next = member_base;
1844 member_base = linklist;
1845 return(0);
1846}
1847
78af4e6e 1848int member_remove(LDAP *ldap_handle, char *dn_path, char *group_name,
f75f605a 1849 char *group_ou, char *group_membership, char *user_name,
1850 char *UserOu)
78af4e6e 1851{
1852 char distinguished_name[1024];
f75f605a 1853 char *modvalues[2];
78af4e6e 1854 char filter_exp[4096];
1855 char *attr_array[3];
1856 char temp[256];
1857 int group_count;
1858 int i;
1859 int n;
1860 LDAPMod *mods[20];
1861 LK_ENTRY *group_base;
1862 ULONG rc;
1863
1864 if (!check_string(group_name))
f75f605a 1865 return(1);
78af4e6e 1866 strcpy(temp, group_name);
f75f605a 1867 sprintf(filter_exp, "(sAMAccountName=%s_zZx%c)", group_name, group_membership[0]);
78af4e6e 1868 attr_array[0] = "distinguishedName";
1869 attr_array[1] = NULL;
1870 if ((rc = linklist_build(ldap_handle, dn_path, filter_exp, attr_array,
1871 &group_base, &group_count)) != 0)
1872 {
f75f605a 1873 com_err(whoami, 0, "LDAP server unable to get list %s info : %s",
1874 group_name, ldap_err2string(rc));
78af4e6e 1875 goto cleanup;
1876 }
1877 if (group_count != 1)
1878 {
f75f605a 1879 com_err(whoami, 0, "LDAP server unable to find list %s in AD",
1880 group_name);
1881 linklist_free(group_base);
1882 group_base = NULL;
1883 group_count = 0;
78af4e6e 1884 goto cleanup;
1885 }
1886 strcpy(distinguished_name, group_base->value);
1887 linklist_free(group_base);
1888 group_base = NULL;
1889 group_count = 0;
78af4e6e 1890
f75f605a 1891 sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
1892 modvalues[0] = temp;
1893 modvalues[1] = NULL;
1894
1895 n = 0;
1896 ADD_ATTR("member", modvalues, LDAP_MOD_DELETE);
1897 mods[n] = NULL;
1898 rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
1899 for (i = 0; i < n; i++)
1900 free(mods[i]);
1901 if (rc != LDAP_SUCCESS)
78af4e6e 1902 {
f75f605a 1903 com_err(whoami, 0, "LDAP server unable to modify list %s members : %s",
1904 group_name, ldap_err2string(rc));
1905 goto cleanup;
78af4e6e 1906 }
1907
1908cleanup:
78af4e6e 1909 return(rc);
1910}
1911
f75f605a 1912int member_add(LDAP *ldap_handle, char *dn_path, char *group_name,
1913 char *group_ou, char *group_membership, char *user_name, char *UserOu)
cd9e6b16 1914{
1915 char distinguished_name[1024];
f75f605a 1916 char *modvalues[2];
cd9e6b16 1917 char filter_exp[4096];
1918 char *attr_array[3];
1919 char temp[256];
cd9e6b16 1920 int group_count;
cd9e6b16 1921 int n;
f75f605a 1922 int i;
cd9e6b16 1923 LDAPMod *mods[20];
1924 LK_ENTRY *group_base;
cd9e6b16 1925 ULONG rc;
1926
1927 rc = 0;
1928 group_base = NULL;
1929 group_count = 0;
cd9e6b16 1930
1931 if (!check_string(group_name))
f75f605a 1932 return(-1);
1933
cd9e6b16 1934 strcpy(temp, group_name);
f75f605a 1935 sprintf(filter_exp, "(sAMAccountName=%s_zZx%c)", group_name, group_membership[0]);
cd9e6b16 1936 attr_array[0] = "distinguishedName";
1937 attr_array[1] = NULL;
1938 if ((rc = linklist_build(ldap_handle, dn_path, filter_exp, attr_array,
1939 &group_base, &group_count)) != 0)
1940 {
f75f605a 1941 com_err(whoami, 0, "LDAP server unable to get list %s info : %s",
1942 group_name, ldap_err2string(rc));
1943 return(-1);
cd9e6b16 1944 }
1945 if (group_count != 1)
1946 {
f75f605a 1947 linklist_free(group_base);
1948 group_base = NULL;
1949 group_count = 0;
1950 com_err(whoami, 0, "LDAP server unable to find list %s in AD",
1951 group_name);
1952 return(-1);
cd9e6b16 1953 }
f75f605a 1954
cd9e6b16 1955 strcpy(distinguished_name, group_base->value);
1956 linklist_free(group_base);
1957 group_base = NULL;
1958 group_count = 0;
1959
f75f605a 1960 sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
1961 modvalues[0] = temp;
1962 modvalues[1] = NULL;
cd9e6b16 1963
f75f605a 1964 n = 0;
1965 ADD_ATTR("member", modvalues, LDAP_MOD_ADD);
1966 mods[n] = NULL;
1967 rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
1968 if (rc == LDAP_ALREADY_EXISTS)
1969 rc = LDAP_SUCCESS;
1970 for (i = 0; i < n; i++)
1971 free(mods[i]);
1972 if (rc != LDAP_SUCCESS)
cd9e6b16 1973 {
f75f605a 1974 com_err(whoami, 0, "LDAP server unable to modify list %s members in AD : %s",
1975 group_name, ldap_err2string(rc));
cd9e6b16 1976 }
1977
f75f605a 1978 return(rc);
cd9e6b16 1979}
1980
1981int contact_create(LDAP *ld, char *bind_path, char *user, char *group_ou)
1982{
1983 LDAPMod *mods[20];
1984 char new_dn[256];
1985 char cn_user_name[256];
1986 char contact_name[256];
f78c7eaf 1987 char *email_v[] = {NULL, NULL};
cd9e6b16 1988 char *cn_v[] = {NULL, NULL};
1989 char *contact_v[] = {NULL, NULL};
1990 char *objectClass_v[] = {"top", "person",
1991 "organizationalPerson",
1992 "contact", NULL};
1993 char *name_v[] = {NULL, NULL};
1994 char *desc_v[] = {NULL, NULL};
1995 int n;
1996 int rc;
1997 int i;
1998
1999 if (!check_string(user))
78af4e6e 2000 {
f75f605a 2001 com_err(whoami, 0, "invalid LDAP name %s", user);
2002 return(-1);
78af4e6e 2003 }
cd9e6b16 2004 strcpy(contact_name, user);
2005 sprintf(cn_user_name,"CN=%s,%s,%s", contact_name, group_ou, bind_path);
2006 cn_v[0] = cn_user_name;
2007 contact_v[0] = contact_name;
2008 name_v[0] = user;
2009 desc_v[0] = "Auto account created by Moira";
f78c7eaf 2010 email_v[0] = user;
cd9e6b16 2011
2012 strcpy(new_dn, cn_user_name);
2013 n = 0;
2014 ADD_ATTR("cn", contact_v, LDAP_MOD_ADD);
2015 ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2016 ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2017 ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2018 ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
f78c7eaf 2019 if (!strcmp(group_ou, contact_ou))
2020 {
2021 ADD_ATTR("mail", email_v, LDAP_MOD_ADD);
2022 }
cd9e6b16 2023 mods[n] = NULL;
2024
2025 rc = ldap_add_ext_s(ld, new_dn, mods, NULL, NULL);
2026 for (i = 0; i < n; i++)
2027 free(mods[i]);
f78c7eaf 2028 if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2029 {
2030 n = 0;
2031 ADD_ATTR("cn", contact_v, LDAP_MOD_ADD);
2032 ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2033 ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2034 ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2035 ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2036 mods[n] = NULL;
2037 rc = ldap_add_ext_s(ld, new_dn, mods, NULL, NULL);
2038 for (i = 0; i < n; i++)
2039 free(mods[i]);
2040 }
cd9e6b16 2041 if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
78af4e6e 2042 {
f75f605a 2043 com_err(whoami, 0, "could not create contact %s : %s",
2044 user, ldap_err2string(rc));
2045 return(-1);
78af4e6e 2046 }
2047 return(0);
2048}
2049
f75f605a 2050int user_update(LDAP *ldap_handle, char *dn_path, char *user_name,
2051 char *Uid, char *MitId)
78af4e6e 2052{
2053 LDAPMod *mods[20];
2054 LK_ENTRY *group_base;
2055 int group_count;
2056 char distinguished_name[256];
78af4e6e 2057 char *uid_v[] = {NULL, NULL};
2058 char *mitid_v[] = {NULL, NULL};
f78c7eaf 2059 char *homedir_v[] = {NULL, NULL};
2060 char *winProfile_v[] = {NULL, NULL};
2061 char *drives_v[] = {NULL, NULL};
78af4e6e 2062 int n;
2063 int rc;
2064 int i;
78af4e6e 2065 char filter_exp[256];
2066 char *attr_array[3];
f78c7eaf 2067 char **hp;
2068 char path[256];
2069 char winPath[256];
2070 char winProfile[256];
78af4e6e 2071
f75f605a 2072 if (!check_string(user_name))
78af4e6e 2073 {
f75f605a 2074 com_err(whoami, 0, "invalid LDAP user name %s", user_name);
2075 return(-1);
78af4e6e 2076 }
2077
78af4e6e 2078 group_count = 0;
2079 group_base = NULL;
f75f605a 2080 sprintf(filter_exp, "(sAMAccountName=%s)", user_name);
78af4e6e 2081 attr_array[0] = "cn";
2082 attr_array[1] = NULL;
f75f605a 2083 if ((rc = linklist_build(ldap_handle, dn_path, filter_exp, attr_array,
78af4e6e 2084 &group_base, &group_count)) != 0)
2085 {
f75f605a 2086 com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
2087 user_name, ldap_err2string(rc));
2088 return(rc);
78af4e6e 2089 }
2090
2091 if (group_count != 1)
2092 {
f75f605a 2093 com_err(whoami, 0, "LDAP server unable to find user %s in AD",
2094 user_name);
2095 linklist_free(group_base);
2096 return(LDAP_NO_SUCH_OBJECT);
78af4e6e 2097 }
2098 strcpy(distinguished_name, group_base->dn);
2099
f75f605a 2100 linklist_free(group_base);
2101 group_count = 0;
78af4e6e 2102 n = 0;
f75f605a 2103 if (strlen(Uid) != 0)
78af4e6e 2104 {
f75f605a 2105 uid_v[0] = Uid;
78af4e6e 2106 ADD_ATTR("uid", uid_v, LDAP_MOD_REPLACE);
2107 ADD_ATTR("uidNumber", uid_v, LDAP_MOD_REPLACE);
2108 }
f75f605a 2109 if (strlen(MitId) != 0)
78af4e6e 2110 {
f75f605a 2111 mitid_v[0] = MitId;
78af4e6e 2112 ADD_ATTR("employeeID", mitid_v, LDAP_MOD_REPLACE);
2113 }
f78c7eaf 2114 if ((hp = hes_resolve(user_name, "filsys")) != NULL)
2115 {
2116 memset(path, 0, sizeof(path));
2117 memset(winPath, 0, sizeof(winPath));
2118 sscanf(hp[0], "%*s %s", path);
2119 if (strlen(path) && strnicmp(path, AFS, strlen(AFS)) == 0)
2120 {
2121 AfsToWinAfs(path, winPath);
2122 homedir_v[0] = winPath;
2123 ADD_ATTR("homeDirectory", homedir_v, LDAP_MOD_REPLACE);
2124 strcpy(winProfile, winPath);
2125 strcat(winProfile, "\\.winprofile");
2126 winProfile_v[0] = winProfile;
2127 ADD_ATTR("profilePath", winProfile_v, LDAP_MOD_REPLACE);
2128 drives_v[0] = "H:";
2129 ADD_ATTR("homeDrive", drives_v, LDAP_MOD_REPLACE);
2130 }
2131 }
78af4e6e 2132 mods[n] = NULL;
2133 if (n != 0)
2134 {
f75f605a 2135 if ((rc = ldap_modify_s(ldap_handle, distinguished_name, mods)) != LDAP_SUCCESS)
78af4e6e 2136 {
f75f605a 2137 com_err(whoami, 0, "Couldn't modify user data for %s : %s",
2138 user_name, ldap_err2string(rc));
78af4e6e 2139 }
2140 for (i = 0; i < n; i++)
2141 free(mods[i]);
2142 }
f78c7eaf 2143 if (hp != NULL)
2144 {
2145 i = 0;
2146 while (hp[i])
2147 {
2148 free(hp[i]);
2149 i++;
2150 }
2151 }
78af4e6e 2152
f75f605a 2153 return(rc);
cd9e6b16 2154}
2155
f75f605a 2156int user_rename(LDAP *ldap_handle, char *dn_path, char *before_user_name,
2157 char *user_name, char *Uid, char *MitId, int State)
9db0b148 2158{
2159 LDAPMod *mods[20];
2160 char new_dn[256];
2161 char old_dn[256];
9db0b148 2162 char upn[256];
2163 char temp[128];
2164 char *userPrincipalName_v[] = {NULL, NULL};
2165 char *altSecurityIdentities_v[] = {NULL, NULL};
2166 char *name_v[] = {NULL, NULL};
78af4e6e 2167 char *samAccountName_v[] = {NULL, NULL};
2168 char *uid_v[] = {NULL, NULL};
2169 char *mitid_v[] = {NULL, NULL};
9db0b148 2170 int n;
2171 int rc;
2172 int i;
9db0b148 2173
f75f605a 2174 if ((State != US_REGISTERED) && (State != US_NO_PASSWD) && (State != US_ENROLL_NOT_ALLOWED))
2175 return(-1);
9db0b148 2176
f75f605a 2177 if (!check_string(before_user_name))
78af4e6e 2178 {
f75f605a 2179 com_err(whoami, 0, "invalid LDAP user name %s", before_user_name);
2180 return(-1);
78af4e6e 2181 }
f75f605a 2182 if (!check_string(user_name))
78af4e6e 2183 {
f75f605a 2184 com_err(whoami, 0, "invalid LDAP user name %s", user_name);
2185 return(-1);
78af4e6e 2186 }
9db0b148 2187
f75f605a 2188 strcpy(user_name, user_name);
2189 sprintf(old_dn, "cn=%s,%s,%s", before_user_name, user_ou, dn_path);
9db0b148 2190 sprintf(new_dn, "cn=%s", user_name);
f75f605a 2191 if ((rc = ldap_rename_s(ldap_handle, old_dn, new_dn, NULL, TRUE,
9db0b148 2192 NULL, NULL)) != LDAP_SUCCESS)
2193 {
f75f605a 2194 if (rc != LDAP_NO_SUCH_OBJECT)
2195 com_err(whoami, 0, "Couldn't rename user from %s to %s : %s",
2196 before_user_name, user_name, ldap_err2string(rc));
2197 return(rc);
9db0b148 2198 }
2199
2200 name_v[0] = user_name;
2201 sprintf(upn, "%s@%s", user_name, ldap_domain);
2202 userPrincipalName_v[0] = upn;
2203 sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
2204 altSecurityIdentities_v[0] = temp;
78af4e6e 2205 samAccountName_v[0] = user_name;
9db0b148 2206
2207 n = 0;
2208 ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_REPLACE);
2209 ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_REPLACE);
2210 ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
78af4e6e 2211 ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_REPLACE);
f75f605a 2212 if (strlen(Uid) != 0)
78af4e6e 2213 {
f75f605a 2214 uid_v[0] = Uid;
78af4e6e 2215 ADD_ATTR("uid", uid_v, LDAP_MOD_REPLACE);
2216 ADD_ATTR("uidNumber", uid_v, LDAP_MOD_REPLACE);
2217 }
f75f605a 2218 if (strlen(MitId) != 0)
78af4e6e 2219 {
f75f605a 2220 mitid_v[0] = MitId;
78af4e6e 2221 ADD_ATTR("employeeID", mitid_v, LDAP_MOD_REPLACE);
2222 }
9db0b148 2223 mods[n] = NULL;
f75f605a 2224 sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, dn_path);
2225 if ((rc = ldap_modify_s(ldap_handle, new_dn, mods)) != LDAP_SUCCESS)
9db0b148 2226 {
f75f605a 2227 com_err(whoami, 0, "After renaming, couldn't modify user data for %s : %s",
2228 user_name, ldap_err2string(rc));
9db0b148 2229 }
2230 for (i = 0; i < n; i++)
2231 free(mods[i]);
f75f605a 2232 return(rc);
9db0b148 2233}
2234
f75f605a 2235int filesys_process(LDAP *ldap_handle, char *dn_path, char *fs_name,
2236 char *fs_type, char *fs_pack, int operation)
f78c7eaf 2237{
2238 char distinguished_name[256];
2239 char winPath[256];
2240 char winProfile[256];
f78c7eaf 2241 char filter_exp[256];
2242 char *attr_array[3];
2243 char *homedir_v[] = {NULL, NULL};
2244 char *winProfile_v[] = {NULL, NULL};
2245 char *drives_v[] = {NULL, NULL};
f78c7eaf 2246 int group_count;
2247 int n;
2248 int rc;
2249 int i;
f78c7eaf 2250 LDAPMod *mods[20];
2251 LK_ENTRY *group_base;
2252
f75f605a 2253 if (!check_string(fs_name))
f78c7eaf 2254 {
f75f605a 2255 com_err(whoami, 0, "invalid filesys name %s", fs_name);
2256 return(-1);
f78c7eaf 2257 }
2258
f75f605a 2259 if (strcmp(fs_type, "AFS"))
f78c7eaf 2260 {
f75f605a 2261 com_err(whoami, 0, "invalid filesys type %s", fs_type);
2262 return(-1);
f78c7eaf 2263 }
2264
f78c7eaf 2265 group_count = 0;
2266 group_base = NULL;
f75f605a 2267 sprintf(filter_exp, "(sAMAccountName=%s)", fs_name);
f78c7eaf 2268 attr_array[0] = "cn";
2269 attr_array[1] = NULL;
f75f605a 2270 if ((rc = linklist_build(ldap_handle, dn_path, filter_exp, attr_array,
f78c7eaf 2271 &group_base, &group_count)) != 0)
2272 {
f75f605a 2273 com_err(whoami, 0, "LDAP server couldn't process filesys %s : %s",
2274 fs_name, ldap_err2string(rc));
2275 return(rc);
f78c7eaf 2276 }
2277
2278 if (group_count != 1)
2279 {
f75f605a 2280 linklist_free(group_base);
2281 com_err(whoami, 0, "LDAP server unable to find user %s in AD",
2282 fs_name);
2283 return(LDAP_NO_SUCH_OBJECT);
f78c7eaf 2284 }
2285 strcpy(distinguished_name, group_base->dn);
f75f605a 2286 linklist_free(group_base);
2287 group_count = 0;
f78c7eaf 2288
2289 n = 0;
2290 if (operation == LDAP_MOD_ADD)
2291 {
2292 memset(winPath, 0, sizeof(winPath));
f75f605a 2293 AfsToWinAfs(fs_pack, winPath);
f78c7eaf 2294 homedir_v[0] = winPath;
2295 drives_v[0] = "H:";
2296 memset(winProfile, 0, sizeof(winProfile));
2297 strcpy(winProfile, winPath);
2298 strcat(winProfile, "\\.winprofile");
2299 winProfile_v[0] = winProfile;
2300 }
2301 else
2302 {
2303 homedir_v[0] = NULL;
2304 drives_v[0] = NULL;
2305 winProfile_v[0] = NULL;
2306 }
2307 ADD_ATTR("profilePath", winProfile_v, operation);
2308 ADD_ATTR("homeDrive", drives_v, operation);
2309 ADD_ATTR("homeDirectory", homedir_v, operation);
2310 mods[n] = NULL;
2311
f75f605a 2312 rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
f78c7eaf 2313 if (rc != LDAP_SUCCESS)
2314 {
f75f605a 2315 com_err(whoami, 0, "Couldn't modify user data for filesys %s : %s",
2316 fs_name, ldap_err2string(rc));
f78c7eaf 2317 }
2318 for (i = 0; i < n; i++)
2319 free(mods[i]);
2320
f75f605a 2321 return(rc);
f78c7eaf 2322}
2323
cd9e6b16 2324int user_create(int ac, char **av, void *ptr)
2325{
5b8457c5 2326 LK_ENTRY *group_base;
cd9e6b16 2327 LDAPMod *mods[20];
2328 char new_dn[256];
2329 char user_name[256];
9db0b148 2330 char sam_name[256];
5b8457c5 2331 char upn[256];
cd9e6b16 2332 char *cn_v[] = {NULL, NULL};
2333 char *objectClass_v[] = {"top", "person",
2334 "organizationalPerson",
2335 "user", NULL};
2336
2337 char *samAccountName_v[] = {NULL, NULL};
2338 char *altSecurityIdentities_v[] = {NULL, NULL};
2339 char *name_v[] = {NULL, NULL};
2340 char *desc_v[] = {NULL, NULL};
cd9e6b16 2341 char *userPrincipalName_v[] = {NULL, NULL};
2342 char *userAccountControl_v[] = {NULL, NULL};
78af4e6e 2343 char *uid_v[] = {NULL, NULL};
2344 char *mitid_v[] = {NULL, NULL};
cd9e6b16 2345 char userAccountControlStr[80];
2346 char temp[128];
2347 u_int userAccountControl = UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD | UF_PASSWD_CANT_CHANGE;
2348 int n;
2349 int rc;
2350 int i;
5b8457c5 2351 int group_count;
cd9e6b16 2352 char filter_exp[256];
2353 char *attr_array[3];
2354 char **call_args;
2355
2356 call_args = ptr;
2357
cd9e6b16 2358 if ((atoi(av[U_STATE]) != US_REGISTERED) && (atoi(av[U_STATE]) != US_NO_PASSWD) &&
2359 (atoi(av[U_STATE]) != US_ENROLL_NOT_ALLOWED))
5b8457c5 2360 {
2361 callback_rc = -1;
2362 return(-1);
2363 }
cd9e6b16 2364 if (!strncmp(av[U_NAME], "#", 1))
5b8457c5 2365 {
2366 callback_rc = -1;
2367 return(-1);
2368 }
78af4e6e 2369 if (!check_string(av[U_NAME]))
2370 {
5b8457c5 2371 callback_rc = -1;
f75f605a 2372 com_err(whoami, 0, "invalid LDAP user name %s", av[U_NAME]);
5b8457c5 2373 return(-1);
78af4e6e 2374 }
9db0b148 2375
cd9e6b16 2376 strcpy(user_name, av[U_NAME]);
2377 sprintf(upn, "%s@%s", user_name, ldap_domain);
78af4e6e 2378 sprintf(sam_name, "%s", av[U_NAME]);
9db0b148 2379 samAccountName_v[0] = sam_name;
cd9e6b16 2380 if (atoi(av[U_STATE]) == US_DELETED)
2381 userAccountControl |= UF_ACCOUNTDISABLE;
2382 sprintf(userAccountControlStr, "%ld", userAccountControl);
2383 userAccountControl_v[0] = userAccountControlStr;
2384 userPrincipalName_v[0] = upn;
2385
2386 cn_v[0] = user_name;
2387 name_v[0] = user_name;
2388 desc_v[0] = "Auto account created by Moira";
2389 sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
2390 altSecurityIdentities_v[0] = temp;
2391 sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, call_args[1]);
2392
2393 n = 0;
2394 ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
2395 ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2396 ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
2397 ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_ADD);
2398 ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_ADD);
2399 ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2400 ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2401 ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2402 ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_ADD);
78af4e6e 2403 if (strlen(av[U_UID]) != 0)
2404 {
2405 uid_v[0] = av[U_UID];
2406 ADD_ATTR("uid", uid_v, LDAP_MOD_ADD);
2407 ADD_ATTR("uidNumber", uid_v, LDAP_MOD_ADD);
2408 }
2409 if (strlen(av[U_MITID]) != 0)
2410 mitid_v[0] = av[U_MITID];
2411 else
2412 mitid_v[0] = "none";
2413 ADD_ATTR("employeeID", mitid_v, LDAP_MOD_ADD);
cd9e6b16 2414 mods[n] = NULL;
2415
2416 rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
78af4e6e 2417 for (i = 0; i < n; i++)
2418 free(mods[i]);
5b8457c5 2419 if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2420 {
2421 com_err(whoami, 0, "could not create user %s : %s",
2422 user_name, ldap_err2string(rc));
2423 callback_rc = rc;
2424 return(rc);
2425 }
9db0b148 2426 if (rc == LDAP_ALREADY_EXISTS)
2427 {
f75f605a 2428 UserReactivate = 1;
2429 rc = user_change_status((LDAP *)call_args[0], call_args[1], av[U_NAME], MEMBER_ACTIVATE);
78af4e6e 2430 return(0);
9db0b148 2431 }
cd9e6b16 2432 if (rc == LDAP_SUCCESS)
2433 {
f78c7eaf 2434 if ((rc = set_password(sam_name, "", ldap_domain)) != 0)
cd9e6b16 2435 {
f75f605a 2436 com_err(whoami, 0, "Couldn't set password for user %s : %ld",
2437 user_name, rc);
cd9e6b16 2438 }
2439 }
78af4e6e 2440 sprintf(filter_exp, "(sAMAccountName=%s)", av[U_NAME]);
cd9e6b16 2441 attr_array[0] = "objectSid";
2442 attr_array[1] = NULL;
5b8457c5 2443 group_count = 0;
2444 group_base = NULL;
cd9e6b16 2445 if ((rc = linklist_build((LDAP *)call_args[0], call_args[1], filter_exp, attr_array,
5b8457c5 2446 &group_base, &group_count)) == LDAP_SUCCESS)
cd9e6b16 2447 {
5b8457c5 2448 if (group_count == 1)
cd9e6b16 2449 {
5b8457c5 2450 (*sid_ptr) = group_base;
2451 (*sid_ptr)->member = strdup(av[L_NAME]);
2452 (*sid_ptr)->type = (char *)GROUPS;
cd9e6b16 2453 sid_ptr = &(*sid_ptr)->next;
2454 }
5b8457c5 2455 else
2456 {
2457 if (group_base != NULL)
2458 linklist_free(group_base);
2459 }
2460 }
2461 else
2462 {
2463 if (group_base != NULL)
2464 linklist_free(group_base);
cd9e6b16 2465 }
78af4e6e 2466 return(0);
cd9e6b16 2467}
2468
f75f605a 2469int user_change_status(LDAP *ldap_handle, char *dn_path, char *user_name, int operation)
cd9e6b16 2470{
2471 char filter_exp[1024];
2472 char *attr_array[3];
2473 char temp[256];
2474 char distinguished_name[1024];
cd9e6b16 2475 char **modvalues;
2476 LDAPMod *mods[20];
2477 LK_ENTRY *group_base;
2478 int group_count;
2479 int rc;
2480 int i;
2481 int n;
2482 ULONG ulongValue;
2483
f75f605a 2484 if (!check_string(user_name))
78af4e6e 2485 {
f75f605a 2486 com_err(whoami, 0, "invalid LDAP user name %s", user_name);
2487 return(-1);
78af4e6e 2488 }
f75f605a 2489
cd9e6b16 2490 group_count = 0;
2491 group_base = NULL;
f75f605a 2492 sprintf(filter_exp, "(sAMAccountName=%s)", user_name);
cd9e6b16 2493 attr_array[0] = "UserAccountControl";
2494 attr_array[1] = NULL;
f75f605a 2495 if ((rc = linklist_build(ldap_handle, dn_path, filter_exp, attr_array,
cd9e6b16 2496 &group_base, &group_count)) != 0)
2497 {
f75f605a 2498 com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
2499 user_name, ldap_err2string(rc));
2500 return(rc);
cd9e6b16 2501 }
2502
78af4e6e 2503 if (group_count != 1)
cd9e6b16 2504 {
f75f605a 2505 linklist_free(group_base);
2506 com_err(whoami, 0, "LDAP server unable to find user %s in AD",
2507 user_name);
2508 return(LDAP_NO_SUCH_OBJECT);
cd9e6b16 2509 }
2510
2511 strcpy(distinguished_name, group_base->dn);
2512 ulongValue = atoi((*group_base).value);
2513 if (operation == MEMBER_DEACTIVATE)
2514 ulongValue |= UF_ACCOUNTDISABLE;
2515 else
2516 ulongValue &= ~UF_ACCOUNTDISABLE;
2517 sprintf(temp, "%ld", ulongValue);
2518 if ((rc = construct_newvalues(group_base, group_count, (*group_base).value,
2519 temp, &modvalues, REPLACE)) == 1)
f75f605a 2520 goto cleanup;
cd9e6b16 2521 linklist_free(group_base);
2522 group_base = NULL;
2523 group_count = 0;
2524 n = 0;
2525 ADD_ATTR("UserAccountControl", modvalues, LDAP_MOD_REPLACE);
2526 mods[n] = NULL;
f75f605a 2527 rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
cd9e6b16 2528 for (i = 0; i < n; i++)
2529 free(mods[i]);
2530 free_values(modvalues);
2531 if (rc != LDAP_SUCCESS)
2532 {
f75f605a 2533 com_err(whoami, 0, "LDAP server could not change status of user %s : %s",
2534 user_name, ldap_err2string(rc));
cd9e6b16 2535 }
2536cleanup:
f75f605a 2537 return(rc);
cd9e6b16 2538}
2539
2540int user_delete(LDAP *ldap_handle, char *dn_path, char *u_name)
2541{
2542 char filter_exp[1024];
2543 char *attr_array[3];
2544 char distinguished_name[1024];
2545 char user_name[512];
2546 LK_ENTRY *group_base;
2547 int group_count;
2548 int rc;
2549
2550 if (!check_string(u_name))
2551 return(0);
2552 strcpy(user_name, u_name);
2553 group_count = 0;
2554 group_base = NULL;
2555 sprintf(filter_exp, "(sAMAccountName=%s)", user_name);
2556 attr_array[0] = "name";
2557 attr_array[1] = NULL;
2558 if ((rc = linklist_build(ldap_handle, dn_path, filter_exp, attr_array,
2559 &group_base, &group_count)) != 0)
2560 {
f75f605a 2561 com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
2562 user_name, ldap_err2string(rc));
cd9e6b16 2563 goto cleanup;
2564 }
2565
78af4e6e 2566 if (group_count != 1)
cd9e6b16 2567 {
f75f605a 2568 com_err(whoami, 0, "LDAP server unable to find user %s in AD",
2569 user_name);
cd9e6b16 2570 goto cleanup;
2571 }
2572
2573 strcpy(distinguished_name, group_base->dn);
2574 if (rc = ldap_delete_s(ldap_handle, distinguished_name))
2575 {
f75f605a 2576 com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
2577 user_name, ldap_err2string(rc));
cd9e6b16 2578 }
2579
2580cleanup:
2581 linklist_free(group_base);
78af4e6e 2582 return(0);
cd9e6b16 2583}
2584
2585void linklist_free(LK_ENTRY *linklist_base)
2586{
2587 LK_ENTRY *linklist_previous;
2588
2589 while (linklist_base != NULL)
2590 {
2591 if (linklist_base->dn != NULL)
2592 free(linklist_base->dn);
2593 if (linklist_base->attribute != NULL)
2594 free(linklist_base->attribute);
2595 if (linklist_base->value != NULL)
2596 free(linklist_base->value);
2597 if (linklist_base->member != NULL)
2598 free(linklist_base->member);
2599 if (linklist_base->type != NULL)
2600 free(linklist_base->type);
2601 if (linklist_base->list != NULL)
2602 free(linklist_base->list);
2603 linklist_previous = linklist_base;
2604 linklist_base = linklist_previous->next;
2605 free(linklist_previous);
2606 }
2607}
2608
2609void free_values(char **modvalues)
2610{
2611 int i;
2612
2613 i = 0;
2614 if (modvalues != NULL)
2615 {
2616 while (modvalues[i] != NULL)
2617 {
2618 free(modvalues[i]);
2619 modvalues[i] = NULL;
2620 ++i;
2621 }
2622 free(modvalues);
2623 }
2624}
2625
2626int sid_update(LDAP *ldap_handle, char *dn_path)
2627{
2628 LK_ENTRY *ptr;
2629 int rc;
2630 unsigned char temp[126];
2631 char *av[3];
2632
2633 ptr = sid_base;
2634
2635 while (ptr != NULL)
2636 {
2637 memset(temp, 0, sizeof(temp));
2638 convert_b_to_a(temp, ptr->value, ptr->length);
5b8457c5 2639 if (!ptr->member)
2640 continue;
cd9e6b16 2641 av[0] = ptr->member;
2642 av[1] = temp;
2643 if (ptr->type == (char *)GROUPS)
2644 {
2645 ptr->type = NULL;
2646 rc = mr_query("add_list_sid_by_name", 2, av, NULL, NULL);
2647 }
2648 else if (ptr->type == (char *)USERS)
2649 {
2650 ptr->type = NULL;
2651 rc = mr_query("add_user_sid_by_login", 2, av, NULL, NULL);
2652 }
2653 ptr = ptr->next;
2654 }
2655 return(0);
2656}
2657
2658void convert_b_to_a(char *string, UCHAR *binary, int length)
2659{
2660 int i;
2661 int j;
2662 UCHAR tmp;
2663
2664 j = 0;
2665 for (i = 0; i < length; i++)
2666 {
2667 tmp = binary[i];
2668 string[j] = tmp;
2669 string[j] >>= 4;
2670 string[j] &= 0x0f;
2671 string[j] += 0x30;
2672 if (string[j] > '9')
2673 string[j] += 0x27;
2674 ++j;
2675 string[j] = tmp & 0x0f;
2676 string[j] += 0x30;
2677 if (string[j] > '9')
2678 string[j] += 0x27;
2679 j++;
2680 }
2681 string[j] = 0;
2682}
2683
2684static int illegalchars[] = {
2685 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
2686 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
2687 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, /* SPACE - / */
2688 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 0 - ? */
f75f605a 2689 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
cd9e6b16 2690 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* P - _ */
2691 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
2692 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
2693 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2694 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2695 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2696 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2697 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2698 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2699 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2700 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2701};
2702
2703int check_string(char *s)
2704{
78af4e6e 2705 char character;
2706
cd9e6b16 2707 for (; *s; s++)
2708 {
78af4e6e 2709 character = *s;
2710 if (isupper(character))
2711 character = tolower(character);
2712 if (illegalchars[(unsigned) character])
cd9e6b16 2713 return 0;
2714 }
2715 return 1;
2716}
2717
2718int mr_connect_cl(char *server, char *client, int version, int auth)
2719{
984c91b7 2720 int status;
2721 char *motd;
2722 char temp[128];
cd9e6b16 2723
2724 status = mr_connect(server);
2725 if (status)
2726 {
2727 com_err(whoami, status, "while connecting to Moira");
aea5154c 2728 return status;
cd9e6b16 2729 }
2730
2731 status = mr_motd(&motd);
2732 if (status)
2733 {
2734 mr_disconnect();
2735 com_err(whoami, status, "while checking server status");
aea5154c 2736 return status;
cd9e6b16 2737 }
2738 if (motd)
2739 {
984c91b7 2740 sprintf(temp, "The Moira server is currently unavailable: %s", motd);
2741 com_err(whoami, status, temp);
cd9e6b16 2742 mr_disconnect();
aea5154c 2743 return status;
cd9e6b16 2744 }
2745
2746 status = mr_version(version);
2747 if (status)
2748 {
2749 if (status == MR_UNKNOWN_PROC)
f78c7eaf 2750 {
2751 if (version > 2)
2752 status = MR_VERSION_HIGH;
2753 else
2754 status = MR_SUCCESS;
2755 }
cd9e6b16 2756
2757 if (status == MR_VERSION_HIGH)
f78c7eaf 2758 {
2759 com_err(whoami, 0, "Warning: This client is running newer code than the server.");
2760 com_err(whoami, 0, "Some operations may not work.");
2761 }
cd9e6b16 2762 else if (status && status != MR_VERSION_LOW)
f78c7eaf 2763 {
2764 com_err(whoami, status, "while setting query version number.");
2765 mr_disconnect();
aea5154c 2766 return status;
f78c7eaf 2767 }
cd9e6b16 2768 }
2769
2770 if (auth)
2771 {
2772 status = mr_auth(client);
2773 if (status)
f78c7eaf 2774 {
2775 com_err(whoami, status, "while authenticating to Moira.");
2776 mr_disconnect();
aea5154c 2777 return status;
f78c7eaf 2778 }
cd9e6b16 2779 }
2780
aea5154c 2781 return MR_SUCCESS;
cd9e6b16 2782}
2783
f78c7eaf 2784void AfsToWinAfs(char* path, char* winPath)
2785{
2786 char* pathPtr;
2787 char* winPathPtr;
2788 strcpy(winPath, WINAFS);
2789 pathPtr = path + strlen(AFS);
2790 winPathPtr = winPath + strlen(WINAFS);
2791
2792 while (*pathPtr)
2793 {
2794 if (*pathPtr == '/')
2795 *winPathPtr = '\\';
2796 else
2797 *winPathPtr = *pathPtr;
2798
2799 pathPtr++;
2800 winPathPtr++;
2801 }
2802}
This page took 0.546547 seconds and 5 git commands to generate.