]> andersk Git - moira.git/blob - incremental/winad/winad.c
Redo support for users with fsgroups.
[moira.git] / incremental / winad / winad.c
1 /* $Header$
2 /* winad.incr arguments examples
3  *
4  *
5  * arguments when moira creates the account - ignored by winad.incr since the account is unusable.
6  * users 0 11 #45198 45198 /bin/cmd cmd Last First Middle 0 950000001 2000 121049
7  *   login, unix_uid, shell, winconsoleshell, last, first, middle, status, mitid, type, moiraid
8  *
9  * arguments for creating or updating a user account 
10  * users 11 11 username 45206 /bin/cmd cmd Last First Middle 2 950000001 STAFF 121058 username 45206 /bin/cmd cmd Last First Middle 1 950000001 STAFF 121058
11  * users 11 11 #45206 45206 /bin/cmd cmd Last First Middle 0 950000001 STAFF 121058 newuser 45206 /bin/cmd cmd Last First Middle 2 950000001 STAFF 121058
12  *   login, unix_uid, shell, winconsoleshell, last, first, middle, status, mitid, type, moiraid
13  *
14  * arguments for deactivating/deleting a user account
15  * users 11 11 username 45206 /bin/cmd cmd Last First Middle 1 950000001 STAFF 121058 username 45206 /bin/cmd cmd Last First Middle 3 950000001 STAFF 121058
16  * users 11 11 username 45206 /bin/cmd cmd Last First Middle 2 950000001 STAFF 121058 username 45206 /bin/cmd cmd Last First Middle 3 950000001 STAFF 121058
17  *   login, unix_uid, shell, winconsoleshell, last, first, middle, status, mitid, type, moiraid
18  *
19  * arguments for reactivating a user account
20  * users 11 11 username 45206 /bin/cmd cmd Last First Middle 3 950000001 STAFF 121058 username 45206 /bin/cmd cmd Last First Middle 1 950000001 STAFF 121058
21  * users 11 11 username 45206 /bin/cmd cmd Last First Middle 3 950000001 STAFF 121058 username 45206 /bin/cmd cmd Last First Middle 2 950000001 STAFF 121058
22  *   login, unix_uid, shell, winconsoleshell, last, first, middle, status, mitid, type, moiraid
23  *
24  * arguments for changing user name
25  * users 11 11 oldusername 45206 /bin/cmd cmd Last First Middle 1 950000001 STAFF 121058 newusername 45206 /bin/cmd cmd Last First Middle 1 950000001 STAFF 121058
26  *   login, unix_uid, shell, winconsoleshell, last, first, middle, status, mitid, type, moiraid
27  *
28  * arguments for expunging a user
29  * users 11 0 username 45198 /bin/cmd cmd Last First Middle 0 950000001 2000 121049
30  *   login, unix_uid, shell, winconsoleshell, last, first, middle, status, mitid, type, moiraid
31  *
32  * arguments for creating a "special" group/list
33  * list 0 11 listname 1 1 0 0 0 -1 NONE 0 description 92616
34  *   listname, active, publicflg, hidden, maillist, grouplist, gid, acl_type, acl_id, description, moiraid
35  * 
36  * arguments for creating a "mail" group/list
37  * list 0 11 listname 1 1 0 1 0 -1 NONE 0 description 92616
38  *   listname, active, publicflg, hidden, maillist, grouplist, gid, acl_type, acl_id, description, moiraid
39  *
40  * arguments for creating a "group" group/list
41  * list 0 11 listname 1 1 0 0 1 -1 NONE 0 description 92616
42  *   listname, active, publicflg, hidden, maillist, grouplist, gid, acl_type, acl_id, description, moiraid
43  *
44  * arguments for creating a "group/mail" group/list
45  * list 0 11 listname 1 1 0 1 1 -1 NONE 0 description 92616
46  *   listname, active, publicflg, hidden, maillist, grouplist, gid, acl_type, acl_id, description, moiraid
47  *
48  * arguments to add a USER member to group/list
49  * imembers 0 12 listname USER userName 1 1 0 0 0 -1 1 92616 121047
50  *   list_name, user_type, name, active, publicflg, hidden, maillist, grouplist, gid, userStatus, moiraListId, moiraUserId
51  *
52  * arguments to add a STRING or KERBEROS member to group/list
53  * imembers 0 10 listname STRING stringName 1 1 0 0 0 -1 92616
54  * imembers 0 10 listlistnameName KERBEROS kerberosName 1 1 0 0 0 -1 92616
55  *   list_name, user_type, name, active, publicflg, hidden, maillist, grouplist, gid, moiraListId
56  *
57  * NOTE: group members of type LIST are ignored.
58  *
59  * arguments to remove a USER member to group/list
60  * imembers 12 0 listname USER userName 1 1 0 0 0 -1 1 92616 121047
61  *   list_name, user_type, name, active, publicflg, hidden, maillist, grouplist, gid, userStatus, moiraListId, moiraUserId
62  *
63  * arguments to remove a STRING or KERBEROS member to group/list
64  * imembers 10 0 listname STRING stringName 1 1 0 0 0 -1 92616
65  * imembers 10 0 listname KERBEROS kerberosName 1 1 0 0 0 -1 92616
66  *   list_name, user_type, name, active, publicflg, hidden, maillist, grouplist, gid, moiraListId
67  *
68  * NOTE: group members of type LIST are ignored.
69  *
70  * arguments for renaming a group/list
71  * list 11 11 oldlistname 1 1 0 0 0 -1 NONE 0 description 92616 newlistname 1 1 0 0 0 -1 description 0 92616
72  *   name, active, publicflg, hidden, maillist, grouplist, gid, acl_type, acl_id, description, moiraListId
73  *
74  * arguments for deleting a group/list
75  * list 11 0 listname 1 1 0 0 0 -1 NONE 0 description 92616
76  *   name, active, publicflg, hidden, maillist, grouplist, gid, acl_type, acl_id, description, moiraListId
77
78  * arguments for adding a file system
79  * filesys 0 12 username AFS ATHENA.MIT.EDU /afs/athena.mit.edu/user/n/e/username /mit/username w descripton username wheel 1 HOMEDIR 101727
80  *
81  * arguments for deleting a file system
82  * filesys 12 0 username AFS ATHENA.MIT.EDU /afs/athena.mit.edu/user/n/e/username /mit/username w descripton username wheel 1 HOMEDIR 101727
83 */
84 #include <mit-copyright.h>
85 #ifdef _WIN32
86 #include <windows.h>
87 #include <stdlib.h>
88 #include <malloc.h>
89 #include <lmaccess.h>
90 #endif
91 #include <hesiod.h>
92 #include <string.h>
93 #include <ldap.h>
94 #include <stdio.h>
95 #include <moira.h>
96 #include <moira_site.h>
97 #include <mrclient.h>
98 #include <krb5.h>
99 #include <krb.h>
100 #include <gsssasl.h>
101 #include <gssldap.h>
102 #include "kpasswd.h"
103
104 #ifdef _WIN32
105 #ifndef ECONNABORTED
106 #define ECONNABORTED WSAECONNABORTED
107 #endif
108 #ifndef ECONNREFUSED
109 #define ECONNREFUSED WSAECONNREFUSED
110 #endif
111 #ifndef EHOSTUNREACH
112 #define EHOSTUNREACH WSAEHOSTUNREACH
113 #endif
114 #define krb5_xfree free
115 #define F_OK 0
116 #define sleep(A) Sleep(A * 1000);
117 #endif /* _WIN32 */
118
119 #ifndef _WIN32
120 #include <sys/types.h>
121 #include <netinet/in.h>
122 #include <arpa/nameser.h>
123 #include <resolv.h>
124 #include <sys/utsname.h>
125 #include <unistd.h>
126
127 #define WINADCFG "/moira/winad/winad.cfg"
128 #define strnicmp(A,B,C) strncasecmp(A,B,C)
129 #define UCHAR unsigned char
130
131 #define UF_SCRIPT               0x0001
132 #define UF_ACCOUNTDISABLE       0x0002
133 #define UF_HOMEDIR_REQUIRED     0x0008
134 #define UF_LOCKOUT              0x0010
135 #define UF_PASSWD_NOTREQD       0x0020
136 #define UF_PASSWD_CANT_CHANGE   0x0040
137 #define UF_DONT_EXPIRE_PASSWD   0x10000
138
139 #define UF_TEMP_DUPLICATE_ACCOUNT       0x0100
140 #define UF_NORMAL_ACCOUNT               0x0200
141 #define UF_INTERDOMAIN_TRUST_ACCOUNT    0x0800
142 #define UF_WORKSTATION_TRUST_ACCOUNT    0x1000
143 #define UF_SERVER_TRUST_ACCOUNT         0x2000
144
145 #ifndef BYTE
146 #define BYTE unsigned char
147 #endif
148 typedef unsigned int DWORD;
149 typedef unsigned long ULONG;
150
151 typedef struct _GUID
152 {
153   unsigned long Data1;
154   unsigned short Data2;
155   unsigned short Data3;
156   unsigned char Data4[8];
157 } GUID;
158
159 typedef struct _SID_IDENTIFIER_AUTHORITY { 
160   BYTE Value[6]; 
161 } SID_IDENTIFIER_AUTHORITY, *PSID_IDENTIFIER_AUTHORITY; 
162
163 typedef struct _SID {
164   BYTE  Revision;
165   BYTE  SubAuthorityCount;
166   SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
167   DWORD SubAuthority[512];
168 } SID;
169 #endif/*!WIN32*/
170
171 #ifndef WINADCFG
172 #define WINADCFG "winad.cfg"
173 #endif
174
175 #define AFS "/afs/"
176 #define WINAFS "\\\\afs\\all\\"
177
178 #define ADS_GROUP_TYPE_GLOBAL_GROUP         0x00000002
179 #define ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP   0x00000004
180 #define ADS_GROUP_TYPE_LOCAL_GROUP          0x00000004
181 #define ADS_GROUP_TYPE_UNIVERSAL_GROUP      0x00000008
182 #define ADS_GROUP_TYPE_SECURITY_ENABLED     0x80000000
183
184 #define QUERY_VERSION -1
185 #define PRIMARY_REALM "ATHENA.MIT.EDU"
186
187 #define SUBSTITUTE  1
188 #define REPLACE     2
189
190 #define USERS         0
191 #define GROUPS        1
192
193 #define MEMBER_ADD          1
194 #define MEMBER_REMOVE       2
195 #define MEMBER_CHANGE_NAME  3
196 #define MEMBER_ACTIVATE     4
197 #define MEMBER_DEACTIVATE   5
198 #define MEMBER_CREATE       6
199
200 #define MOIRA_ALL       0x0
201 #define MOIRA_USERS     0x1
202 #define MOIRA_KERBEROS  0x2
203 #define MOIRA_STRINGS   0x4
204 #define MOIRA_LISTS     0x8
205
206 #define CHECK_GROUPS    1
207 #define CLEANUP_GROUPS  2
208
209 #define AD_NO_GROUPS_FOUND        -1
210 #define AD_WRONG_GROUP_DN_FOUND   -2
211 #define AD_MULTIPLE_GROUPS_FOUND  -3
212 #define AD_INVALID_NAME           -4
213 #define AD_LDAP_FAILURE           -5
214 #define AD_INVALID_FILESYS        -6
215 #define AD_NO_ATTRIBUTE_FOUND     -7
216 #define AD_NO_OU_FOUND            -8
217 #define AD_NO_USER_FOUND          -9
218
219 typedef struct lk_entry {
220   int     op;
221   int     length;
222   int     ber_value;
223   char    *dn;
224   char    *attribute;
225   char    *value;
226   char    *member;
227   char    *type;
228   char    *list;
229   struct  lk_entry *next;
230 } LK_ENTRY;
231
232 #define STOP_FILE "/moira/winad/nowinad"
233 #define file_exists(file) (access((file), F_OK) == 0)
234
235 #define LDAP_BERVAL struct berval
236 #define MAX_SERVER_NAMES 32
237
238 #define ADD_ATTR(t, v, o)               \
239   mods[n] = malloc(sizeof(LDAPMod));    \
240   mods[n]->mod_op = o;  \
241   mods[n]->mod_type = t;                \
242   mods[n++]->mod_values = v
243
244 LK_ENTRY *member_base = NULL;
245 LK_ENTRY *sid_base = NULL;
246 LK_ENTRY **sid_ptr = NULL;
247 static char tbl_buf[1024];
248 char  kerberos_ou[] = "OU=kerberos,OU=moira";
249 char  contact_ou[] = "OU=strings,OU=moira";
250 char  user_ou[] = "OU=users,OU=moira";
251 char  group_ou_distribution[] = "OU=mail,OU=lists,OU=moira";
252 char  group_ou_root[] = "OU=lists,OU=moira";
253 char  group_ou_security[] = "OU=group,OU=lists,OU=moira";
254 char  group_ou_neither[] = "OU=special,OU=lists,OU=moira";
255 char  group_ou_both[] = "OU=mail,OU=group,OU=lists,OU=moira";
256 char *whoami;
257 char ldap_domain[256];
258 int  mr_connections = 0;
259 int  callback_rc;
260 char default_server[256];
261 static char tbl_buf[1024];
262
263 extern int set_password(char *user, char *password, char *domain);
264
265 int ad_get_group(LDAP *ldap_handle, char *dn_path, char *group_name, 
266                 char *group_membership, char *MoiraId, char *attribute,
267                 LK_ENTRY **linklist_base, int *linklist_count,
268               char *rFilter);
269 void AfsToWinAfs(char* path, char* winPath);
270 int ad_connect(LDAP **ldap_handle, char *ldap_domain, char *dn_path, 
271                char *Win2kPassword, char *Win2kUser, char *default_server,
272                int connect_to_kdc);
273 void ad_kdc_disconnect();
274 void check_winad(void);
275 int check_user(LDAP *ldap_handle, char *dn_path, char *UserName, char *MoiraId);
276 int filesys_process(LDAP *ldap_handle, char *dn_path, char *fs_name, 
277                     char *fs_type, char *fs_pack, int operation);
278 int get_group_membership(char *group_membership, char *group_ou, 
279                          int *security_flag, char **av);
280 int process_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
281                   char *group_name, char *group_ou, char *group_membership, 
282                   int group_security_flag, int type);
283 int process_lists(int ac, char **av, void *ptr);
284 int user_create(int ac, char **av, void *ptr);
285 int user_change_status(LDAP *ldap_handle, char *dn_path, 
286                        char *user_name, char *MoiraId, int operation);
287 int user_delete(LDAP *ldap_handle, char *dn_path, 
288                 char *u_name, char *MoiraId);
289 int user_rename(LDAP *ldap_handle, char *dn_path, char *before_user_name, 
290                 char *user_name);
291 int user_update(LDAP *ldap_handle, char *dn_path, char *user_name,
292                 char *uid, char *MitId, char *MoiraId, int State);
293 void change_to_lower_case(char *ptr);
294 int contact_create(LDAP *ld, char *bind_path, char *user, char *group_ou);
295 int group_create(int ac, char **av, void *ptr);
296 int group_delete(LDAP *ldap_handle, char *dn_path, 
297                  char *group_name, char *group_membership, char *MoiraId);
298 int group_rename(LDAP *ldap_handle, char *dn_path, 
299                  char *before_group_name, char *before_group_membership, 
300                  char *before_group_ou, int before_security_flag, char *before_desc,
301                  char *after_group_name, char *after_group_membership, 
302                  char *after_group_ou, int after_security_flag, char *after_desc,
303                  char *MoiraId, char *filter);
304 int make_new_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
305                    char *group_name, char *group_ou, char *group_membership, 
306                    int group_security_flag, int updateGroup);
307 int member_list_build(int ac, char **av, void *ptr);
308 int member_add(LDAP *ldap_handle, char *dn_path, char *group_name, 
309                         char *group_ou, char *group_membership, 
310                         char *user_name, char *pUserOu, char *MoiraId);
311 int member_remove(LDAP *ldap_handle, char *dn_path, char *group_name, 
312                   char *group_ou, char *group_membership, char *user_name,
313                   char *pUserOu, char *MoiraId);
314 int populate_group(LDAP *ldap_handle, char *dn_path, char *group_name, 
315                    char *group_ou, char *group_membership, 
316                    int group_security_flag, char *MoiraId);
317 int sid_update(LDAP *ldap_handle, char *dn_path);
318 int check_string(char *s);
319 void convert_b_to_a(char *string, UCHAR *binary, int length);
320 int mr_connect_cl(char *server, char *client, int version, int auth);
321
322 void do_filesys(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
323              char **before, int beforec, char **after, int afterc);
324 void do_list(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
325              char **before, int beforec, char **after, int afterc);
326 void do_user(LDAP *ldap_handle, char *dn_path, char *ldap_hostname, 
327              char **before, int beforec, char **after, int afterc);
328 void do_member(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
329                char **before, int beforec, char **after, int afterc);
330 int linklist_create_entry(char *attribute, char *value,
331                           LK_ENTRY **linklist_entry);
332 int linklist_build(LDAP *ldap_handle, char *dn_path, char *search_exp, 
333                    char **attr_array, LK_ENTRY **linklist_base, 
334                    int *linklist_count);
335 void linklist_free(LK_ENTRY *linklist_base);
336
337 int retrieve_attributes(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
338                         char *distinguished_name, LK_ENTRY **linklist_current);
339 int retrieve_entries(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
340                      LK_ENTRY **linklist_base, int *linklist_count);
341 int retrieve_values(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
342                     char *Attribute, char *distinguished_name, 
343                     LK_ENTRY **linklist_current);
344
345 int construct_newvalues(LK_ENTRY *linklist_base, int modvalue_count, 
346                         char *oldValue, char *newValue,
347                         char ***modvalues, int type);
348 void free_values(char **modvalues);
349
350 int convert_domain_to_dn(char *domain, char **bind_path);
351 void get_distinguished_name(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
352                             char *distinguished_name);
353 int moira_disconnect(void);
354 int moira_connect(void);
355 void print_to_screen(const char *fmt, ...);
356
357 int main(int argc, char **argv)
358 {
359   unsigned long   rc;
360   int             beforec;
361   int             afterc;
362   int             i;
363   char            *table;
364   char            **before;
365   char            **after;
366   LDAP            *ldap_handle;
367   FILE            *fptr;
368   char            dn_path[256];
369
370   whoami = ((whoami = (char *)strrchr(argv[0], '/')) ? whoami+1 : argv[0]);
371
372   if (argc < 4)
373     {
374       com_err(whoami, 0, "%s", "argc < 4");
375       exit(1);
376     }
377   beforec = atoi(argv[2]);
378   afterc = atoi(argv[3]);
379
380   if (argc < (4 + beforec + afterc))
381     {
382       com_err(whoami, 0, "%s", "argc < (4 + breforec + afterc)");
383       exit(1);
384     }
385
386   table = argv[1];
387   before = &argv[4];
388   after = &argv[4 + beforec];
389
390   for (i = 1; i < argc; i++)
391     {
392       strcat(tbl_buf, argv[i]);
393       strcat(tbl_buf, " ");
394     }
395   com_err(whoami, 0, "%s", tbl_buf);
396
397   check_winad();
398
399   memset(ldap_domain, '\0', sizeof(ldap_domain));
400   if ((fptr = fopen(WINADCFG, "r")) != NULL)
401     {
402       fread(ldap_domain, sizeof(char), sizeof(ldap_domain), fptr);
403       fclose(fptr);
404     }
405   if (strlen(ldap_domain) == 0)
406     strcpy(ldap_domain, "win.mit.edu");
407   initialize_sms_error_table();
408   initialize_krb_error_table();
409
410   memset(default_server, '\0', sizeof(default_server));
411   memset(dn_path, '\0', sizeof(dn_path));
412   for (i = 0; i < 5; i++)
413     {
414       if (!(rc = ad_connect(&ldap_handle, ldap_domain, dn_path, "", "", default_server, 1)))
415          break;
416       sleep(2);
417     }
418   if (rc)
419     {
420           critical_alert("incremental", "winad.incr cannot connect to any server in domain %s", ldap_domain);
421       exit(1);
422     }
423
424   for (i = 0; i < (int)strlen(table); i++)
425     table[i] = tolower(table[i]);
426   if (!strcmp(table, "users"))
427     do_user(ldap_handle, dn_path, ldap_domain, before, beforec, after,
428             afterc);
429   else if (!strcmp(table, "list"))
430     do_list(ldap_handle, dn_path, ldap_domain, before, beforec, after,
431             afterc);
432   else if (!strcmp(table, "imembers"))
433     do_member(ldap_handle, dn_path, ldap_domain, before, beforec, after,
434               afterc);
435   else if (!strcmp(table, "filesys"))
436     do_filesys(ldap_handle, dn_path, ldap_domain, before, beforec, after,
437                afterc);
438 /*
439   else if (!strcmp(table, "quota"))
440     do_quota(before, beforec, after, afterc);
441 */
442
443   ad_kdc_disconnect();
444   rc = ldap_unbind_s(ldap_handle);
445   exit(0);
446 }
447
448 void do_filesys(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
449              char **before, int beforec, char **after, int afterc)
450 {
451   long  rc;
452   char  *av[3];
453   char  *call_args[7];
454   int   acreate;
455   int   atype;
456   int   bcreate;
457   int   btype;
458   int   abort_flag;
459
460   abort_flag = 0;
461
462   if (afterc < FS_CREATE)
463     atype = acreate = 0;
464   else
465     {
466       atype = !strcmp(after[FS_TYPE], "AFS");
467       acreate = atoi(after[FS_CREATE]);
468     }
469
470   if (beforec < FS_CREATE)
471     {
472       if (acreate == 0 || atype == 0)
473         goto cleanup;
474       com_err(whoami, 0, "Processing filesys %s", after[FS_NAME]);
475       abort_flag = 0;
476       while (1)
477       {
478         if ((rc = filesys_process(ldap_handle, dn_path, after[FS_NAME], 
479                     after[FS_TYPE], after[FS_PACK], LDAP_MOD_ADD)) != LDAP_NO_SUCH_OBJECT)
480           {
481             if (rc != LDAP_SUCCESS)
482               com_err(whoami, 0, "Couldn't process filesys %s", after[FS_NAME]);
483             break;
484           }
485         if (abort_flag == 1)
486           break;
487         sleep(1);
488         abort_flag = 1;
489         if (rc = moira_connect())
490           {
491             critical_alert("AD incremental",
492                            "Error contacting Moira server : %s",
493                            error_message(rc));
494             return;
495           }
496         av[0] = after[FS_NAME];
497         call_args[0] = (char *)ldap_handle;
498         call_args[1] = dn_path;
499         call_args[2] = "";
500         call_args[3] = NULL;
501         sid_base = NULL;
502         sid_ptr = &sid_base;
503         callback_rc = 0;
504         if (rc = mr_query("get_user_account_by_login", 1, av, user_create,
505                           call_args))
506           {
507             moira_disconnect();
508             com_err(whoami, 0, "Couldn't process filesys %s", after[FS_NAME]);
509             break;
510           }
511         if (callback_rc)
512           {
513             moira_disconnect();
514             com_err(whoami, 0, "Couldn't process filesys %s", after[FS_NAME]);
515             break;
516           }
517         if (sid_base != NULL)
518           {
519             sid_update(ldap_handle, dn_path);
520             linklist_free(sid_base);
521             sid_base = NULL;
522           }
523         moira_disconnect();
524       }
525       goto cleanup;
526     }
527
528   btype = !strcmp(before[FS_TYPE], "AFS");
529   bcreate = atoi(before[FS_CREATE]);
530   if (afterc < FS_CREATE)
531     {
532       if (btype && bcreate)
533         {
534           if (rc = filesys_process(ldap_handle, dn_path, before[FS_NAME], 
535                       before[FS_TYPE], before[FS_PACK], LDAP_MOD_DELETE))
536             {
537               com_err(whoami, 0, "Couldn't delete filesys %s", before[FS_NAME]);
538             }
539         }
540       return;
541     }
542
543   if (!acreate)
544     return;
545
546   if (!atype && !btype)
547     {
548       if (strcmp(before[FS_TYPE], "ERR") || strcmp(after[FS_TYPE], "ERR"))
549         {
550           com_err(whoami, 0, "Filesystem %s or %s is not AFS",
551                   before[FS_NAME], after[FS_NAME]);
552           return;
553         }
554     }
555   com_err(whoami, 0, "Processing filesys %s", after[FS_NAME]);
556   abort_flag = 0;
557   while (1)
558   {
559     if ((rc = filesys_process(ldap_handle, dn_path, after[FS_NAME], 
560                     after[FS_TYPE], after[FS_PACK], LDAP_MOD_ADD)) != LDAP_NO_SUCH_OBJECT)
561       {
562         if (rc != LDAP_SUCCESS)
563           com_err(whoami, 0, "Couldn't process filesys %s", after[FS_NAME]);
564         break;
565       }
566     if (abort_flag == 1)
567       break;
568     sleep(1);
569     abort_flag = 1;
570     if (rc = moira_connect())
571       {
572         critical_alert("AD incremental",
573                        "Error contacting Moira server : %s",
574                        error_message(rc));
575         return;
576       }
577     av[0] = after[FS_NAME];
578     call_args[0] = (char *)ldap_handle;
579     call_args[1] = dn_path;
580     call_args[2] = "";
581     call_args[3] = NULL;
582     sid_base = NULL;
583     sid_ptr = &sid_base;
584     callback_rc = 0;
585     if (rc = mr_query("get_user_account_by_login", 1, av, user_create,
586                       call_args))
587       {
588         moira_disconnect();
589         com_err(whoami, 0, "Couldn't process filesys %s", after[FS_NAME]);
590         break;
591       }
592     if (callback_rc)
593       {
594         moira_disconnect();
595         com_err(whoami, 0, "Couldn't process filesys %s", after[FS_NAME]);
596         break;
597       }
598     if (sid_base != NULL)
599       {
600         sid_update(ldap_handle, dn_path);
601         linklist_free(sid_base);
602         sid_base = NULL;
603       }
604     moira_disconnect();
605   }
606
607 cleanup:
608   return;
609 }
610
611 #define L_LIST_DESC 9
612 #define L_LIST_ID   10
613
614 void do_list(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
615              char **before, int beforec, char **after, int afterc)
616 {
617   int   updateGroup;
618   long  rc;
619   char  group_membership[6];
620   char  list_id[32];
621   int   security_flag;
622   char  filter[128];
623   char  group_ou[256];
624   char  before_list_id[32];
625   char  before_group_membership[1];
626   int   before_security_flag;
627   char  before_group_ou[256];
628   LK_ENTRY *ptr = NULL;
629
630   if (beforec == 0 && afterc == 0)
631     return;
632
633   memset(list_id, '\0', sizeof(list_id));
634   memset(before_list_id, '\0', sizeof(before_list_id));
635   memset(before_group_ou, '\0', sizeof(before_group_ou));
636   memset(before_group_membership, '\0', sizeof(before_group_membership));
637   memset(group_ou, '\0', sizeof(group_ou));
638   memset(group_membership, '\0', sizeof(group_membership));
639   updateGroup = 0;
640
641   if (beforec > L_GID)
642     {
643       if (beforec < L_LIST_ID)
644         return;
645       if (beforec > L_LIST_DESC)
646         {
647           strcpy(before_list_id, before[L_LIST_ID]);
648         }
649       before_security_flag = 0;
650       get_group_membership(before_group_membership, before_group_ou, &before_security_flag, before);
651     }
652   if (afterc > L_GID)
653     {
654       if (afterc < L_LIST_ID)
655         return;
656       if (afterc > L_LIST_DESC)
657         {
658           strcpy(list_id, before[L_LIST_ID]);
659         }
660       security_flag = 0;
661       get_group_membership(group_membership, group_ou, &security_flag, after);
662     }
663
664   if ((beforec == 0) && (afterc == 0)) /*this case should never happen*/
665     return;
666
667   updateGroup = 0;
668   if (beforec)
669     {
670       updateGroup = 1;
671       if ((rc = process_group(ldap_handle, dn_path, before_list_id, before[L_NAME], 
672                               before_group_ou, before_group_membership, 
673                               before_security_flag, CHECK_GROUPS)))
674         {
675           if (rc == AD_NO_GROUPS_FOUND)
676             updateGroup = 0;
677           else
678             {
679               if ((rc == AD_WRONG_GROUP_DN_FOUND) || (rc == AD_MULTIPLE_GROUPS_FOUND))
680                 {
681                   rc = process_group(ldap_handle, dn_path, before_list_id, before[L_NAME], 
682                                      before_group_ou, before_group_membership, 
683                                      before_security_flag, CLEANUP_GROUPS);
684                 }
685               if ((rc != AD_NO_GROUPS_FOUND) && (rc != 0))
686                 {
687                   com_err(whoami, 0, "Could not change list name from %s to %s",
688                           before[L_NAME], after[L_NAME]);
689                   return;
690                 }
691               if (rc == AD_NO_GROUPS_FOUND)
692                 updateGroup = 0;
693             }
694         }
695     }
696   
697   if ((beforec != 0) && (afterc != 0))
698     {
699       if (((strcmp(after[L_NAME], before[L_NAME])) || 
700           ((!strcmp(after[L_NAME], before[L_NAME])) && 
701            (strcmp(before_group_ou, group_ou)))) &&
702           (updateGroup == 1))
703         {
704           com_err(whoami, 0, "Changing list name from %s to %s",
705                   before[L_NAME], after[L_NAME]);
706           if ((strlen(before_group_ou) == 0) || (strlen(before_group_membership) == 0) ||
707               (strlen(group_ou) == 0) || (strlen(group_membership) == 0))
708             {
709               com_err(whoami, 0, "%s", "couldn't find the group OU's");
710               return;
711             }
712           memset(filter, '\0', sizeof(filter));
713           if ((rc = group_rename(ldap_handle, dn_path, 
714                                  before[L_NAME], before_group_membership, 
715                                  before_group_ou, before_security_flag, before[L_LIST_DESC],
716                                  after[L_NAME], group_membership, 
717                                  group_ou, security_flag, after[L_LIST_DESC],
718                                  list_id, filter)))
719             {
720               if (rc != AD_NO_GROUPS_FOUND)
721                 {
722                   com_err(whoami, 0, "Could not change list name from %s to %s",
723                           before[L_NAME], after[L_NAME]);
724                   return;
725                 }
726               updateGroup = 0;
727             }
728           beforec = 0;
729         }
730       else
731         beforec = 0;
732     }
733
734   if (beforec)
735     {
736       if ((strlen(before_group_ou) == 0) || (strlen(before_group_membership) == 0))
737         {
738           com_err(whoami, 0, "couldn't find the group OU for group %s", before[L_NAME]);
739           return;
740         }
741       com_err(whoami, 0, "Deleting group %s", before[L_NAME]);
742       rc = group_delete(ldap_handle, dn_path, before[L_NAME], 
743                         before_group_membership, before_list_id);
744       return;
745     }
746   if (afterc)
747     {
748       if (!updateGroup)
749         {
750           com_err(whoami, 0, "Creating group %s", after[L_NAME]);
751           if (rc = process_group(ldap_handle, dn_path, list_id, after[L_NAME], 
752                                   group_ou, group_membership, 
753                                   security_flag, CHECK_GROUPS))
754             {
755               if (rc != AD_NO_GROUPS_FOUND)
756                 {
757                   if ((rc == AD_WRONG_GROUP_DN_FOUND) || (rc == AD_MULTIPLE_GROUPS_FOUND))
758                     {
759                       rc = process_group(ldap_handle, dn_path, list_id, after[L_NAME], 
760                                          group_ou, group_membership, 
761                                          security_flag, CLEANUP_GROUPS);
762                     }
763                   if (rc)
764                     {
765                       com_err(whoami, 0, "Could not create list %s", after[L_NAME]);
766                       return;
767                     }
768                 }
769             }
770         }
771       else
772         com_err(whoami, 0, "Updating group %s information", after[L_NAME]);
773
774       if (rc = moira_connect())
775         {
776           critical_alert("AD incremental",
777                          "Error contacting Moira server : %s",
778                          error_message(rc));
779           return;
780         }
781
782       if (make_new_group(ldap_handle, dn_path, list_id, after[L_NAME], 
783                          group_ou, group_membership, security_flag, updateGroup))
784         {
785           moira_disconnect();
786           return;
787         }
788       if (atoi(after[L_ACTIVE]))
789         {
790           populate_group(ldap_handle, dn_path, after[L_NAME], group_ou, 
791                          group_membership, security_flag, list_id);
792         }
793       moira_disconnect();
794     }
795
796   return;
797 }
798
799 #define LM_EXTRA_ACTIVE   (LM_END)
800 #define LM_EXTRA_PUBLIC   (LM_END+1)
801 #define LM_EXTRA_HIDDEN   (LM_END+2)
802 #define LM_EXTRA_MAILLIST (LM_END+3)
803 #define LM_EXTRA_GROUP    (LM_END+4)
804 #define LM_EXTRA_GID      (LM_END+5)
805 #define LMN_LIST_ID       (LM_END+6)
806 #define LM_LIST_ID        (LM_END+7)
807 #define LM_USER_ID        (LM_END+8)
808 #define LM_EXTRA_END      (LM_END+9)
809
810 void do_member(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
811                char **before, int beforec, char **after, int afterc)
812 {
813   char  group_name[128];
814   char  user_name[128];
815   char  user_type[128];
816   char  moira_list_id[32];
817   char  moira_user_id[32];
818   char  group_membership[1];
819   char  group_ou[256];
820   char  *args[16];
821   char  **ptr;
822   char  *av[7];
823   char  *call_args[7];
824   char  *pUserOu;
825   int   security_flag;
826   int   rc;
827
828   pUserOu = NULL;
829   ptr = NULL;
830   memset(moira_list_id, '\0', sizeof(moira_list_id));
831   memset(moira_user_id, '\0', sizeof(moira_user_id));
832   if (afterc)
833     {
834       if (afterc < LM_EXTRA_GID)
835         return;
836       if (!atoi(after[LM_EXTRA_ACTIVE]))
837         return;
838       ptr = after;
839       if (!strcasecmp(ptr[LM_TYPE], "LIST"))
840         return;
841       strcpy(user_name, after[LM_MEMBER]);
842       strcpy(group_name, after[LM_LIST]);
843       strcpy(user_type, after[LM_TYPE]);
844       if (!strcasecmp(ptr[LM_TYPE], "USER"))
845         {
846           if (afterc > LMN_LIST_ID)
847             {
848               strcpy(moira_list_id, after[LM_LIST_ID]);
849               strcpy(moira_user_id, after[LM_USER_ID]);
850             }
851         }
852       else
853         {
854           if (afterc > LM_EXTRA_GID)
855             strcpy(moira_list_id, after[LMN_LIST_ID]);
856         }
857     }
858   else if (beforec)
859     {
860       if (beforec < LM_EXTRA_GID)
861         return;
862       if (!atoi(before[LM_EXTRA_ACTIVE]))
863           return;
864       ptr = before;
865       if (!strcasecmp(ptr[LM_TYPE], "LIST"))
866         return;
867       strcpy(user_name, before[LM_MEMBER]);
868       strcpy(group_name, before[LM_LIST]);
869       strcpy(user_type, before[LM_TYPE]);
870       if (!strcasecmp(ptr[LM_TYPE], "USER"))
871         {
872           if (beforec > LMN_LIST_ID)
873             {
874               strcpy(moira_list_id, before[LM_LIST_ID]);
875               strcpy(moira_user_id, before[LM_USER_ID]);
876             }
877         }
878       else
879         {
880           if (beforec > LM_EXTRA_GID)
881             strcpy(moira_list_id, before[LMN_LIST_ID]);
882         }
883     }
884
885   if (ptr == NULL)
886     return;
887
888   args[L_NAME] = ptr[LM_LIST];
889   args[L_ACTIVE] = ptr[LM_EXTRA_ACTIVE];
890   args[L_PUBLIC] = ptr[LM_EXTRA_PUBLIC];
891   args[L_HIDDEN] = ptr[LM_EXTRA_HIDDEN];
892   args[L_MAILLIST] = ptr[LM_EXTRA_MAILLIST];
893   args[L_GROUP] = ptr[LM_EXTRA_GROUP];
894   args[L_GID] = ptr[LM_EXTRA_GID];
895
896   security_flag = 0;
897   memset(group_ou, '\0', sizeof(group_ou));
898   get_group_membership(group_membership, group_ou, &security_flag, args);
899   if (strlen(group_ou) == 0)
900     {
901       com_err(whoami, 0, "couldn't find the group OU for group %s", group_name);
902       return;
903     }
904   if (rc = process_group(ldap_handle, dn_path, moira_list_id, group_name, group_ou, group_membership, security_flag, CHECK_GROUPS))
905     {
906       if (rc != AD_NO_GROUPS_FOUND)
907         {
908           if (rc = process_group(ldap_handle, dn_path, moira_list_id, group_name, group_ou, group_membership, security_flag, CLEANUP_GROUPS))
909             {
910               if (rc != AD_NO_GROUPS_FOUND)
911                 {
912                   if (afterc)
913                     com_err(whoami, 0, "Couldn't add %s to group %s - unable to process group", user_name, group_name);
914                   else
915                     com_err(whoami, 0, "Couldn't remove %s from group %s - unable to process group", user_name, group_name);
916                   return;
917                 }
918             }
919         }
920     }
921   if (rc == AD_NO_GROUPS_FOUND)
922     {
923       if (rc = moira_connect())
924         {
925           critical_alert("AD incremental",
926                          "Error contacting Moira server : %s",
927                          error_message(rc));
928           return;
929         }
930
931       com_err(whoami, 0, "creating group %s", group_name);
932       if (make_new_group(ldap_handle, dn_path, moira_list_id, ptr[LM_LIST], 
933                          group_ou, group_membership, security_flag, 0))
934         {
935           moira_disconnect();
936           return;
937         }
938       if (atoi(ptr[LM_EXTRA_ACTIVE]))
939         {
940           populate_group(ldap_handle, dn_path, ptr[LM_LIST], group_ou, 
941                          group_membership, security_flag, moira_list_id);
942         }
943       moira_disconnect();
944     }
945   rc = 0;
946   if (beforec)
947     {
948       com_err(whoami, 0, "removing user %s from list %s", user_name, group_name);
949       pUserOu = user_ou;
950       if (!strcasecmp(ptr[LM_TYPE], "STRING"))
951         {
952           if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], contact_ou))
953             return;
954           pUserOu = contact_ou;
955         }
956       else if (!strcasecmp(ptr[LM_TYPE], "KERBEROS"))
957         {
958           if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], kerberos_ou))
959             return;
960           pUserOu = kerberos_ou;
961         }
962       if (rc = member_remove(ldap_handle, dn_path, group_name,
963                              group_ou, group_membership, ptr[LM_MEMBER], 
964                              pUserOu, moira_list_id))
965           com_err(whoami, 0, "couldn't remove %s from group %s", user_name, group_name);
966       return;
967     }
968
969   com_err(whoami, 0, "Adding %s to list %s", user_name, group_name);
970   pUserOu = user_ou;
971   if (!strcasecmp(ptr[LM_TYPE], "STRING"))
972     {
973       if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], contact_ou))
974         return;
975       pUserOu = contact_ou;
976     }
977   else if (!strcasecmp(ptr[LM_TYPE], "KERBEROS"))
978     {
979       if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], kerberos_ou))
980         return;
981       pUserOu = kerberos_ou;
982     }
983   else if (!strcasecmp(ptr[LM_TYPE], "USER"))
984     {
985       if ((rc = check_user(ldap_handle, dn_path, ptr[LM_MEMBER], 
986                            moira_user_id)) == AD_NO_USER_FOUND)
987         {
988           if (rc = moira_connect())
989             {
990               critical_alert("AD incremental", 
991                              "Error connection to Moira : %s",
992                              error_message(rc));
993               return;
994             }
995           com_err(whoami, 0, "creating user %s", after[U_NAME]);
996           av[0] = ptr[LM_MEMBER];
997           call_args[0] = (char *)ldap_handle;
998           call_args[1] = dn_path;
999           call_args[2] = moira_user_id;
1000           call_args[3] = NULL;
1001           sid_base = NULL;
1002           sid_ptr = &sid_base;
1003           callback_rc = 0;
1004           if (rc = mr_query("get_user_account_by_login", 1, av, user_create,
1005                             call_args))
1006             {
1007               moira_disconnect();
1008               com_err(whoami, 0, "couldn't create user %s : %s",
1009                       ptr[LM_MEMBER], error_message(rc));
1010               return;
1011             }
1012           if (callback_rc)
1013             {
1014               moira_disconnect();
1015               com_err(whoami, 0, "couldn't create user %s", ptr[LM_MEMBER]);
1016               return;
1017             }
1018           sleep(1);
1019           if (sid_base != NULL)
1020             {
1021               sid_update(ldap_handle, dn_path);
1022               linklist_free(sid_base);
1023             }
1024         }
1025       else
1026         {
1027           if (rc != 0)
1028             return;
1029         }
1030       pUserOu = user_ou;
1031     }
1032
1033   if (rc = member_add(ldap_handle, dn_path, group_name,
1034                   group_ou, group_membership, ptr[LM_MEMBER],
1035                   pUserOu, moira_list_id))
1036     {
1037       com_err(whoami, 0, "couldn't add %s to group %s", user_name, group_name);
1038     }
1039   return;
1040 }
1041
1042
1043 #define U_USER_ID 10
1044
1045 void do_user(LDAP *ldap_handle, char *dn_path, char *ldap_hostname, 
1046              char **before, int beforec, char **after, 
1047              int afterc)
1048 {
1049   int   rc;
1050   char  *av[7];
1051   char  after_user_id[32];
1052   char  before_user_id[32];
1053   char  *call_args[7];
1054
1055   if ((beforec == 0) && (afterc == 0))
1056     return;
1057
1058   memset(after_user_id, '\0', sizeof(after_user_id));
1059   memset(before_user_id, '\0', sizeof(before_user_id));
1060   if (beforec > U_USER_ID)
1061     strcpy(before_user_id, before[U_USER_ID]);
1062   if (afterc > U_USER_ID)
1063     strcpy(after_user_id, after[U_USER_ID]);
1064
1065   if ((beforec == 0) && (afterc == 0)) /*this case should never happen */
1066     return;
1067
1068   if ((beforec == 0) && (afterc != 0)) /*this case only happens when the account*/
1069     return;                            /*account is first created but not usable*/
1070
1071   if ((beforec != 0) && (afterc == 0)) /*this case only happens when the account*/
1072     {                                  /*is expunged*/
1073       if (atoi(before[U_STATE]) == 0)
1074         {
1075           com_err(whoami, 0, "expunging user %s from AD", before[U_NAME]);
1076           user_delete(ldap_handle, dn_path, before[U_NAME], before_user_id);
1077         }
1078       return;
1079     }
1080
1081   /*process anything that gets here*/
1082   if ((rc = check_user(ldap_handle, dn_path, before[U_NAME], 
1083                        before_user_id)) == AD_NO_USER_FOUND)
1084     {
1085       if (rc = moira_connect())
1086         {
1087           critical_alert("AD incremental", 
1088                          "Error connection to Moira : %s",
1089                          error_message(rc));
1090           return;
1091         }
1092       com_err(whoami, 0, "creating user %s", after[U_NAME]);
1093
1094       av[0] = after[U_NAME];
1095       call_args[0] = (char *)ldap_handle;
1096       call_args[1] = dn_path;
1097       call_args[2] = after_user_id;
1098       call_args[3] = NULL;
1099       sid_base = NULL;
1100       sid_ptr = &sid_base;
1101       callback_rc = 0;
1102       if (rc = mr_query("get_user_account_by_login", 1, av, user_create,
1103                         call_args))
1104         {
1105           moira_disconnect();
1106           com_err(whoami, 0, "couldn't create user %s : %s",
1107                   after[U_NAME], error_message(rc));
1108           return;
1109         }
1110       if (callback_rc)
1111         {
1112           moira_disconnect();
1113           com_err(whoami, 0, "couldn't create user %s", after[U_NAME]);
1114           return;
1115         }
1116       sleep(1);
1117       if (sid_base != NULL)
1118         {
1119           sid_update(ldap_handle, dn_path);
1120           linklist_free(sid_base);
1121         }
1122       return;
1123     }
1124   else
1125     {
1126       if (rc != 0)
1127         return;
1128     }
1129   if (strcmp(before[U_NAME], after[U_NAME]))
1130     {
1131       if ((check_string(before[U_NAME])) && (check_string(after[U_NAME])))
1132         {
1133           com_err(whoami, 0, "changing user %s to %s", 
1134                   before[U_NAME], after[U_NAME]);
1135           if ((rc = user_rename(ldap_handle, dn_path, before[U_NAME], 
1136                                 after[U_NAME])) != LDAP_SUCCESS)
1137             {
1138               return;
1139             }
1140         }
1141     }
1142   com_err(whoami, 0, "updating user %s information", after[U_NAME]);
1143   rc = user_update(ldap_handle, dn_path, after[U_NAME],
1144                    after[U_UID], after[U_MITID], 
1145                    after_user_id, atoi(after[U_STATE]));
1146   return;
1147 }
1148
1149 int construct_newvalues(LK_ENTRY *linklist_base, int modvalue_count, 
1150                         char *oldValue, char *newValue,
1151                         char ***modvalues, int type)
1152 {
1153   LK_ENTRY    *linklist_ptr;
1154   int         i;
1155   char        *cPtr;
1156
1157   if (((*modvalues) = calloc(1, (modvalue_count + 1) * sizeof(char *)))
1158       == NULL)
1159     {
1160       return(1);
1161     }
1162   for (i = 0; i < (modvalue_count + 1); i++)
1163     (*modvalues)[i] = NULL;
1164   if (modvalue_count != 0)
1165     {
1166       linklist_ptr = linklist_base;
1167       for (i = 0; i < modvalue_count; i++)
1168         {
1169           if ((oldValue != NULL) && (newValue != NULL))
1170             {
1171               if ((cPtr = (char *)strstr(linklist_ptr->value, oldValue))
1172                  != (char *)NULL)
1173                 {
1174                   if (type == REPLACE)
1175                     {
1176                       if (((*modvalues)[i] = calloc(1, strlen(newValue) + 1))
1177                           == NULL)
1178                         return(1);
1179                       memset((*modvalues)[i], '\0', strlen(newValue) + 1);
1180                       strcpy((*modvalues)[i], newValue);
1181                     }
1182                   else
1183                     {
1184                       if (((*modvalues)[i] = calloc(1, 
1185                                         (int)(cPtr - linklist_ptr->value) + 
1186                                         (linklist_ptr->length - strlen(oldValue)) + 
1187                                         strlen(newValue) + 1)) == NULL)
1188                         return(1);
1189                       memset((*modvalues)[i], '\0', 
1190                              (int)(cPtr - linklist_ptr->value) + 
1191                              (linklist_ptr->length - strlen(oldValue)) + 
1192                              strlen(newValue) + 1);
1193                       memcpy((*modvalues)[i], linklist_ptr->value, 
1194                              (int)(cPtr - linklist_ptr->value));
1195                       strcat((*modvalues)[i], newValue);
1196                       strcat((*modvalues)[i], 
1197      &linklist_ptr->value[(int)(cPtr - linklist_ptr->value) + strlen(oldValue)]);
1198                     }
1199                 }
1200               else
1201                 {
1202                   (*modvalues)[i] = calloc(1, linklist_ptr->length + 1);
1203                   memset((*modvalues)[i], '\0', linklist_ptr->length + 1);
1204                   memcpy((*modvalues)[i], linklist_ptr->value,
1205                          linklist_ptr->length);
1206                 }
1207             }
1208         else
1209             {
1210               (*modvalues)[i] = calloc(1, linklist_ptr->length + 1);
1211               memset((*modvalues)[i], '\0', linklist_ptr->length + 1);
1212               memcpy((*modvalues)[i], linklist_ptr->value,
1213                      linklist_ptr->length);
1214             }
1215           linklist_ptr = linklist_ptr->next;
1216         }
1217       (*modvalues)[i] = NULL;
1218     }
1219   return(0);
1220 }
1221
1222
1223 int linklist_build(LDAP *ldap_handle, char *dn_path, char *search_exp, 
1224                    char **attr_array, LK_ENTRY **linklist_base,
1225                    int *linklist_count)
1226 {
1227   ULONG       rc;
1228   LDAPMessage *ldap_entry;
1229
1230   rc = 0;
1231   ldap_entry = NULL;
1232   (*linklist_base) = NULL;
1233   (*linklist_count) = 0;
1234   if ((rc = ldap_search_s(ldap_handle, dn_path, LDAP_SCOPE_SUBTREE, 
1235                           search_exp, attr_array, 0, &ldap_entry))
1236       != LDAP_SUCCESS)
1237     return(0);
1238   rc = retrieve_entries(ldap_handle, ldap_entry, linklist_base, linklist_count);
1239
1240   ldap_msgfree(ldap_entry);
1241   return(rc);
1242 }
1243
1244
1245 int retrieve_entries(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
1246                      LK_ENTRY **linklist_base, int *linklist_count)
1247 {
1248   char        distinguished_name[1024];
1249   LK_ENTRY    *linklist_ptr;
1250   int         rc;
1251
1252   if ((ldap_entry = ldap_first_entry(ldap_handle, ldap_entry)) == NULL)
1253     return(0);
1254
1255   memset(distinguished_name, '\0', sizeof(distinguished_name));
1256   get_distinguished_name(ldap_handle, ldap_entry, distinguished_name);
1257
1258   if ((rc = retrieve_attributes(ldap_handle, ldap_entry, distinguished_name,
1259                                 linklist_base)) != 0)
1260     return(rc);
1261
1262   while ((ldap_entry = ldap_next_entry(ldap_handle, ldap_entry)) != NULL)
1263     {
1264       memset(distinguished_name, '\0', sizeof(distinguished_name));
1265       get_distinguished_name(ldap_handle, ldap_entry, distinguished_name);
1266
1267       if ((rc = retrieve_attributes(ldap_handle, ldap_entry, distinguished_name,
1268                                     linklist_base)) != 0)
1269         return(rc);
1270     }
1271
1272   linklist_ptr = (*linklist_base);
1273   (*linklist_count) = 0;
1274   while (linklist_ptr != NULL)
1275     {
1276       ++(*linklist_count);
1277       linklist_ptr = linklist_ptr->next;
1278     }
1279   return(0);
1280 }
1281
1282 int retrieve_attributes(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
1283                         char *distinguished_name, LK_ENTRY **linklist_current)
1284 {
1285   char        *Attribute;
1286   BerElement  *ptr;
1287
1288   ptr = NULL;
1289   if ((Attribute = ldap_first_attribute(ldap_handle, ldap_entry, &ptr)) != NULL)
1290     {
1291       retrieve_values(ldap_handle, ldap_entry, Attribute, distinguished_name,
1292                       linklist_current);
1293       ldap_memfree(Attribute);
1294       while ((Attribute = ldap_next_attribute(ldap_handle, ldap_entry, 
1295                                               ptr)) != NULL)
1296         {
1297           retrieve_values(ldap_handle, ldap_entry, Attribute,
1298                           distinguished_name, linklist_current);
1299           ldap_memfree(Attribute);
1300         }
1301     }
1302   ldap_ber_free(ptr, 0);
1303   return(0);
1304 }
1305
1306 int retrieve_values(LDAP *ldap_handle, LDAPMessage *ldap_entry,
1307                     char *Attribute, char *distinguished_name,
1308                     LK_ENTRY **linklist_current)
1309 {
1310   char        **str_value;
1311   char        temp[256];
1312   void        **Ptr;
1313   int         use_bervalue;
1314   LK_ENTRY    *linklist_previous;
1315   LDAP_BERVAL **ber_value;
1316   DWORD       ber_length;
1317 #ifdef LDAP_DEBUG
1318   SID         *sid;
1319   GUID        *guid;
1320   int         i;
1321   int         intValue;
1322   DWORD       *subauth;
1323   SID_IDENTIFIER_AUTHORITY    *sid_auth;
1324   unsigned char   *subauth_count;
1325 #endif /*LDAP_BEGUG*/
1326
1327   use_bervalue = 0;
1328   memset(temp, '\0', sizeof(temp));
1329   if ((!strcmp(Attribute, "objectSid")) ||
1330       (!strcmp(Attribute, "objectGUID")))
1331     use_bervalue = 1;
1332
1333   if (use_bervalue)
1334     {
1335       ber_value = ldap_get_values_len(ldap_handle, ldap_entry, Attribute);
1336       Ptr = (void **)ber_value;
1337       str_value = NULL;
1338       }
1339   else
1340     {
1341       str_value = ldap_get_values(ldap_handle, ldap_entry, Attribute);
1342       Ptr = (void **)str_value;
1343       ber_value = NULL;
1344     }
1345   if (Ptr != NULL)
1346     {
1347       for (; *Ptr; Ptr++) 
1348         {
1349           if ((linklist_previous = calloc(1, sizeof(LK_ENTRY))) == NULL)
1350             return(1);
1351           memset(linklist_previous, '\0', sizeof(LK_ENTRY));
1352           linklist_previous->next = (*linklist_current);
1353           (*linklist_current) = linklist_previous;
1354
1355           if (((*linklist_current)->attribute = calloc(1, 
1356                                                strlen(Attribute) + 1)) == NULL)
1357             return(1);
1358           memset((*linklist_current)->attribute, '\0', strlen(Attribute) + 1);
1359           strcpy((*linklist_current)->attribute, Attribute);
1360           if (use_bervalue)
1361             {
1362               ber_length = (*(LDAP_BERVAL **)Ptr)->bv_len;
1363               if (((*linklist_current)->value = calloc(1, ber_length)) == NULL)
1364                 return(1);
1365               memset((*linklist_current)->value, '\0', ber_length);
1366               memcpy((*linklist_current)->value, (*(LDAP_BERVAL **)Ptr)->bv_val, 
1367                                                   ber_length);
1368               (*linklist_current)->length = ber_length;
1369             }
1370           else
1371             {
1372               if (((*linklist_current)->value = calloc(1, 
1373                                                   strlen(*Ptr) + 1)) == NULL)
1374                 return(1);
1375               memset((*linklist_current)->value, '\0', strlen(*Ptr) + 1);
1376               (*linklist_current)->length = strlen(*Ptr);
1377               strcpy((*linklist_current)->value, *Ptr);
1378             }
1379           (*linklist_current)->ber_value = use_bervalue;
1380           if (((*linklist_current)->dn = calloc(1, 
1381                                       strlen(distinguished_name) + 1)) == NULL)
1382             return(1);
1383           memset((*linklist_current)->dn, '\0', strlen(distinguished_name) + 1);
1384           strcpy((*linklist_current)->dn, distinguished_name);
1385
1386 #ifdef LDAP_DEBUG
1387           if (!strcmp(Attribute, "objectGUID"))
1388             {
1389               guid = (GUID *)((*linklist_current)->value);
1390               sprintf(temp, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 
1391                       guid->Data1, guid->Data2, guid->Data3, 
1392                       guid->Data4[0], guid->Data4[1], guid->Data4[2], 
1393                       guid->Data4[3], guid->Data4[4], guid->Data4[5], 
1394                       guid->Data4[6], guid->Data4[7]);
1395               print_to_screen("     %20s : {%s}\n", Attribute, temp);
1396             }
1397           else if (!strcmp(Attribute, "objectSid"))
1398             {
1399               sid = (SID *)((*(LDAP_BERVAL **)Ptr)->bv_val);
1400 #ifdef _WIN32
1401               print_to_screen("        Revision = %d\n", sid->Revision);
1402               print_to_screen("        SID Identifier Authority:\n");
1403               sid_auth = &sid->IdentifierAuthority;
1404               if (sid_auth->Value[0])
1405                 print_to_screen("            SECURITY_NULL_SID_AUTHORITY\n");
1406               else if (sid_auth->Value[1])
1407                 print_to_screen("            SECURITY_WORLD_SID_AUTHORITY\n");
1408               else if (sid_auth->Value[2])
1409                 print_to_screen("            SECURITY_LOCAL_SID_AUTHORITY\n");
1410               else if (sid_auth->Value[3])
1411                 print_to_screen("            SECURITY_CREATOR_SID_AUTHORITY\n");
1412               else if (sid_auth->Value[5])
1413                 print_to_screen("            SECURITY_NT_AUTHORITY\n");
1414               else
1415                 print_to_screen("            UNKNOWN SID AUTHORITY\n");
1416               subauth_count = GetSidSubAuthorityCount(sid);
1417               print_to_screen("        SidSubAuthorityCount = %d\n", 
1418                               *subauth_count);
1419               print_to_screen("        SidSubAuthority:\n");
1420               for (i = 0; i < *subauth_count; i++)
1421                 {
1422                   if ((subauth = GetSidSubAuthority(sid, i)) != NULL)
1423                     print_to_screen("            %u\n", *subauth);
1424                 }
1425 #endif
1426             }
1427           else if ((!memcmp(Attribute, "userAccountControl", 
1428                             strlen("userAccountControl"))) ||
1429                    (!memcmp(Attribute, "sAMAccountType", 
1430                             strlen("sAmAccountType"))))
1431             {
1432               intValue = atoi(*Ptr);
1433               print_to_screen("     %20s : %ld\n",Attribute, intValue);
1434               if (!memcmp(Attribute, "userAccountControl", 
1435                           strlen("userAccountControl")))
1436                 {
1437                   if (intValue & UF_ACCOUNTDISABLE)
1438                     print_to_screen("     %20s :    %s\n", 
1439                                     "", "Account disabled");
1440                   else
1441                     print_to_screen("     %20s :    %s\n", 
1442                                     "", "Account active");
1443                   if (intValue & UF_HOMEDIR_REQUIRED)
1444                     print_to_screen("     %20s :    %s\n", 
1445                                     "", "Home directory required");
1446                   if (intValue & UF_LOCKOUT)
1447                     print_to_screen("     %20s :    %s\n", 
1448                                     "", "Account locked out");
1449                   if (intValue & UF_PASSWD_NOTREQD)
1450                     print_to_screen("     %20s :    %s\n", 
1451                                     "", "No password required");
1452                   if (intValue & UF_PASSWD_CANT_CHANGE)
1453                     print_to_screen("     %20s :    %s\n",
1454                                     "", "Cannot change password");
1455                   if (intValue & UF_TEMP_DUPLICATE_ACCOUNT)
1456                     print_to_screen("     %20s :    %s\n", 
1457                                     "", "Temp duplicate account");
1458                   if (intValue & UF_NORMAL_ACCOUNT)
1459                     print_to_screen("     %20s :    %s\n", 
1460                                     "", "Normal account");
1461                   if (intValue & UF_INTERDOMAIN_TRUST_ACCOUNT)
1462                     print_to_screen("     %20s :    %s\n", 
1463                                     "", "Interdomain trust account");
1464                   if (intValue & UF_WORKSTATION_TRUST_ACCOUNT)
1465                     print_to_screen("     %20s :    %s\n", 
1466                                     "", "Workstation trust account");
1467                   if (intValue & UF_SERVER_TRUST_ACCOUNT)
1468                     print_to_screen("     %20s :    %s\n", 
1469                                     "", "Server trust account");
1470                 }
1471             }
1472           else
1473             {
1474               print_to_screen("     %20s : %s\n",Attribute, *Ptr);
1475             }
1476 #endif /*LDAP_DEBUG*/
1477         }
1478       if (str_value != NULL)
1479         ldap_value_free(str_value);
1480       if (ber_value != NULL)
1481         ldap_value_free_len(ber_value);
1482     }
1483   (*linklist_current) = linklist_previous;
1484   return(0);
1485 }
1486
1487 int moira_connect(void)
1488 {
1489   long    rc;
1490   char    HostName[64];
1491
1492   if (!mr_connections++)
1493     {
1494 #ifdef _WIN32
1495       memset(HostName, '\0', sizeof(HostName));
1496       strcpy(HostName, "ttsp");
1497       rc = mr_connect_cl(HostName, "winad.incr", QUERY_VERSION, 1);
1498 /*det
1499       rc = mr_connect(HostName);
1500 */
1501 #else
1502       struct utsname uts;
1503       uname(&uts);
1504       rc = mr_connect_cl(uts.nodename, "winad.incr", QUERY_VERSION, 1);
1505 /*
1506       rc = mr_connect(uts.nodename);
1507 */
1508 #endif /*WIN32*/
1509 /*det
1510       if (!rc)
1511         rc = mr_auth("winad.incr");
1512 */
1513       return rc;
1514     }
1515   return 0;
1516 }
1517
1518 void check_winad(void)
1519 {
1520   int i;
1521   
1522   for (i = 0; file_exists(STOP_FILE); i++)
1523     {
1524       if (i > 30)
1525         {
1526           critical_alert("AD incremental",
1527                          "WINAD incremental failed (%s exists): %s",
1528                          STOP_FILE, tbl_buf);
1529           exit(1);
1530         }
1531       sleep(60);
1532     }
1533 }
1534
1535 int moira_disconnect(void)
1536 {
1537
1538   if (!--mr_connections)
1539     {
1540       mr_disconnect();
1541     }
1542   return 0;
1543 }
1544
1545 void get_distinguished_name(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
1546                             char *distinguished_name)
1547 {
1548   char    *CName;
1549
1550   CName = ldap_get_dn(ldap_handle, ldap_entry);
1551   if (CName == NULL)
1552     return;
1553   strcpy(distinguished_name, CName);
1554   ldap_memfree(CName);
1555 }
1556
1557 int linklist_create_entry(char *attribute, char *value, 
1558                           LK_ENTRY **linklist_entry)
1559 {
1560   (*linklist_entry) = calloc(1, sizeof(LK_ENTRY));
1561   if (!(*linklist_entry))
1562     {
1563       return(1);
1564     }
1565   memset((*linklist_entry), '\0', sizeof(LK_ENTRY));
1566   (*linklist_entry)->attribute = calloc(1, strlen(attribute) + 1);
1567   memset((*linklist_entry)->attribute, '\0', strlen(attribute) + 1);
1568   strcpy((*linklist_entry)->attribute, attribute);
1569   (*linklist_entry)->value = calloc(1, strlen(value) + 1);
1570   memset((*linklist_entry)->value, '\0', strlen(value) + 1);
1571   strcpy((*linklist_entry)->value, value);
1572   (*linklist_entry)->length = strlen(value);
1573   (*linklist_entry)->next = NULL;
1574   return(0);
1575 }
1576
1577 void print_to_screen(const char *fmt, ...)
1578 {
1579   va_list pvar;
1580
1581   va_start(pvar, fmt);
1582   vfprintf(stderr, fmt, pvar);
1583   fflush(stderr);
1584   va_end(pvar);
1585 }
1586
1587 int get_group_membership(char *group_membership, char *group_ou, 
1588                          int *security_flag, char **av)
1589 {
1590   int  maillist_flag;
1591   int  group_flag;
1592
1593   maillist_flag = atoi(av[L_MAILLIST]);
1594   group_flag = atoi(av[L_GROUP]);
1595   if (security_flag != NULL)
1596     (*security_flag) = 0;
1597
1598   if ((maillist_flag) && (group_flag))
1599     {
1600       if (group_membership != NULL)
1601         group_membership[0] = 'B';
1602       if (security_flag != NULL)
1603         (*security_flag) = 1;
1604       if (group_ou != NULL)
1605         strcpy(group_ou, group_ou_both);
1606     }
1607   else if ((!maillist_flag) && (group_flag))
1608     {
1609       if (group_membership != NULL)
1610         group_membership[0] = 'S';
1611       if (security_flag != NULL)
1612         (*security_flag) = 1;
1613       if (group_ou != NULL)
1614         strcpy(group_ou, group_ou_security);
1615     }
1616   else if ((maillist_flag) && (!group_flag))
1617     {
1618       if (group_membership != NULL)
1619         group_membership[0] = 'D';
1620       if (group_ou != NULL)
1621         strcpy(group_ou, group_ou_distribution);
1622     }
1623   else
1624     {
1625       if (group_membership != NULL)
1626         group_membership[0] = 'N';
1627       if (group_ou != NULL)
1628         strcpy(group_ou, group_ou_neither);
1629     }
1630   return(0);
1631 }
1632
1633 int group_rename(LDAP *ldap_handle, char *dn_path, 
1634                  char *before_group_name, char *before_group_membership, 
1635                  char *before_group_ou, int before_security_flag, char *before_desc,
1636                  char *after_group_name, char *after_group_membership, 
1637                  char *after_group_ou, int after_security_flag, char *after_desc,
1638                  char *MoiraId, char *filter)
1639 {
1640   LDAPMod   *mods[20];
1641   char      old_dn[512];
1642   char      new_dn[512];
1643   char      new_dn_path[512];
1644   char      sam_name[256];
1645   char      *attr_array[3];
1646   char      *mitMoiraId_v[] = {NULL, NULL};
1647   char      *name_v[] = {NULL, NULL};
1648   char      *desc_v[] = {NULL, NULL};
1649   char      *samAccountName_v[] = {NULL, NULL};
1650   char      *groupTypeControl_v[] = {NULL, NULL};
1651   u_int     groupTypeControl = ADS_GROUP_TYPE_GLOBAL_GROUP;
1652   char      groupTypeControlStr[80];
1653   int       n;
1654   int       i;
1655   int       rc;
1656   LK_ENTRY  *group_base;
1657   int       group_count;
1658
1659   if (!check_string(before_group_name))
1660     {
1661       com_err(whoami, 0, "invalid LDAP list name %s", before_group_name);
1662       return(AD_INVALID_NAME);
1663     }
1664   if (!check_string(after_group_name))
1665     {
1666       com_err(whoami, 0, "invalid LDAP list name %s", after_group_name);
1667       return(AD_INVALID_NAME);
1668     }
1669
1670   group_count = 0;
1671   group_base = NULL;
1672   if (rc = ad_get_group(ldap_handle, dn_path, before_group_name, 
1673                         before_group_membership, 
1674                         MoiraId, "distinguishedName", &group_base, 
1675                         &group_count, filter))
1676     return(rc);
1677
1678   if (group_count == 0)
1679     {
1680       return(AD_NO_GROUPS_FOUND);
1681     }
1682   if (group_count != 1)
1683     {
1684       com_err(whoami, 0,
1685               "multiple groups with MoiraId = %s exist in the AD",
1686               MoiraId);
1687       return(AD_MULTIPLE_GROUPS_FOUND);
1688     }
1689   strcpy(old_dn, group_base->value);
1690
1691   linklist_free(group_base);
1692   group_base = NULL;
1693   group_count = 0;
1694   attr_array[0] = "sAMAccountName";
1695   attr_array[1] = NULL;
1696   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
1697                            &group_base, &group_count)) != 0)
1698     {
1699       com_err(whoami, 0, "LDAP server unable to get list %s dn : %s",
1700               after_group_name, ldap_err2string(rc));
1701       return(rc);
1702     }
1703   if (group_count != 1)
1704     {
1705       com_err(whoami, 0,
1706               "Unable to get sAMAccountName for group %s", 
1707               before_group_name);
1708       return(AD_LDAP_FAILURE);
1709     }
1710
1711   strcpy(sam_name, group_base->value);
1712   linklist_free(group_base);
1713   group_base = NULL;
1714   group_count = 0;
1715
1716   sprintf(new_dn_path, "%s,%s", after_group_ou, dn_path);
1717   sprintf(new_dn, "cn=%s", after_group_name);
1718   if ((rc = ldap_rename_s(ldap_handle, old_dn, new_dn, new_dn_path,
1719                           TRUE, NULL, NULL)) != LDAP_SUCCESS)
1720     {
1721       com_err(whoami, 0, "Couldn't rename list from %s to %s : %s",
1722               before_group_name, after_group_name, ldap_err2string(rc));
1723       return(rc);
1724     }
1725
1726   name_v[0] = after_group_name;
1727   if (!strncmp(&sam_name[strlen(sam_name) - strlen("_group")], "_group", strlen("_group")))
1728     {
1729       sprintf(sam_name, "%s_group", after_group_name);
1730     }
1731   else
1732     {
1733       com_err(whoami, 0, "Couldn't rename list from %s to %s : sAMAccountName not found",
1734               before_group_name, after_group_name);
1735       return(rc);
1736     }
1737   samAccountName_v[0] = sam_name;
1738   if (after_security_flag)
1739     groupTypeControl |= ADS_GROUP_TYPE_SECURITY_ENABLED;
1740   sprintf(groupTypeControlStr, "%ld", groupTypeControl);
1741   groupTypeControl_v[0] = groupTypeControlStr;
1742   n = 0;
1743   ADD_ATTR("samAccountName", samAccountName_v, LDAP_MOD_REPLACE);
1744   ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
1745   desc_v[0] = after_desc;
1746   if (strlen(after_desc) == 0)
1747     desc_v[0] = NULL;
1748   ADD_ATTR("description", desc_v, LDAP_MOD_REPLACE);
1749   mitMoiraId_v[0] = MoiraId;
1750   ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
1751   ADD_ATTR("groupType", groupTypeControl_v, LDAP_MOD_REPLACE);
1752   mods[n] = NULL;
1753   sprintf(new_dn, "cn=%s,%s,%s", after_group_name, after_group_ou, dn_path);
1754   if ((rc = ldap_modify_s(ldap_handle, new_dn, mods)) != LDAP_SUCCESS)
1755     {
1756       com_err(whoami, 0, "After renaming, couldn't modify list data for %s : %s",
1757               after_group_name, ldap_err2string(rc));
1758     }
1759   for (i = 0; i < n; i++)
1760     free(mods[i]);
1761   return(rc);
1762 }
1763
1764 int group_create(int ac, char **av, void *ptr)
1765 {
1766   LDAPMod *mods[20];
1767   LK_ENTRY  *group_base;
1768   char new_dn[256];
1769   char group_ou[256];
1770   char new_group_name[256];
1771   char sam_group_name[256];
1772   char cn_group_name[256];
1773   char *cn_v[] = {NULL, NULL};
1774   char *objectClass_v[] = {"top", "group", NULL};
1775   char info[256];
1776   char *samAccountName_v[] = {NULL, NULL};
1777   char *managedBy_v[] = {NULL, NULL};
1778   char *altSecurityIdentities_v[] = {NULL, NULL};
1779   char *member_v[] = {NULL, NULL};
1780   char *name_v[] = {NULL, NULL};
1781   char *desc_v[] = {NULL, NULL};
1782   char *info_v[] = {NULL, NULL};
1783   char *mitMoiraId_v[] = {NULL, NULL};
1784   char *groupTypeControl_v[] = {NULL, NULL};
1785   char groupTypeControlStr[80];
1786   char group_membership[1];
1787   int  i;
1788   int  security_flag;
1789   u_int groupTypeControl = ADS_GROUP_TYPE_GLOBAL_GROUP;
1790   int  n;
1791   int  rc;
1792   int  group_count;
1793   int  updateGroup;
1794   char filter[128];
1795   char *attr_array[3];
1796   char **call_args;
1797
1798   call_args = ptr;
1799
1800   if (!check_string(av[L_NAME]))
1801     {
1802       com_err(whoami, 0, "invalid LDAP list name %s", av[L_NAME]);
1803       return(AD_INVALID_NAME);
1804     }
1805
1806   updateGroup = (int)call_args[4];
1807   memset(group_ou, 0, sizeof(group_ou));
1808   memset(group_membership, 0, sizeof(group_membership));
1809   security_flag = 0;
1810   get_group_membership(group_membership, group_ou, &security_flag, av);
1811   strcpy(new_group_name, av[L_NAME]);
1812   sprintf(new_dn, "cn=%s,%s,%s", new_group_name, group_ou, call_args[1]);
1813   if (security_flag)
1814     groupTypeControl |= ADS_GROUP_TYPE_SECURITY_ENABLED;
1815   
1816   sprintf(sam_group_name, "%s_group", av[L_NAME]);
1817
1818   if (!updateGroup)
1819     {
1820
1821       sprintf(groupTypeControlStr, "%ld", groupTypeControl);
1822       groupTypeControl_v[0] = groupTypeControlStr;
1823
1824       strcpy(cn_group_name, av[L_NAME]);
1825
1826       samAccountName_v[0] = sam_group_name;
1827       name_v[0] = new_group_name;
1828       cn_v[0] = new_group_name;
1829
1830       n = 0;
1831       ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
1832       ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
1833       ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
1834       ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
1835       ADD_ATTR("name", name_v, LDAP_MOD_ADD);
1836       if (strlen(av[L_DESC]) != 0)
1837         {
1838           desc_v[0] = av[L_DESC];
1839           ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
1840         }
1841       ADD_ATTR("groupType", groupTypeControl_v, LDAP_MOD_ADD);
1842       if (strlen(av[L_ACE_NAME]) != 0)
1843         {
1844           sprintf(info, "The Administrator of this list is: %s", av[L_ACE_NAME]);
1845           info_v[0] = info;
1846           ADD_ATTR("info", info_v, LDAP_MOD_ADD);
1847         }
1848       if (strlen(call_args[5]) != 0)
1849         {
1850           mitMoiraId_v[0] = call_args[5];
1851           ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_ADD);
1852         }
1853       mods[n] = NULL;
1854
1855       rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
1856
1857       for (i = 0; i < n; i++)
1858         free(mods[i]);
1859       if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
1860         {
1861           com_err(whoami, 0, "Unable to create/update list %s in AD : %s",
1862                   av[L_NAME], ldap_err2string(rc));
1863           callback_rc = rc;
1864           return(rc);
1865         }
1866     }
1867   if ((rc == LDAP_ALREADY_EXISTS) || (updateGroup))
1868     {
1869       n = 0;
1870       desc_v[0] = NULL;
1871       if (strlen(av[L_DESC]) != 0)
1872         desc_v[0] = av[L_DESC];
1873       ADD_ATTR("description", desc_v, LDAP_MOD_REPLACE);
1874       info_v[0] = NULL;
1875       if (strlen(av[L_ACE_NAME]) != 0)
1876         {
1877           sprintf(info, "The Administrator of this list is: %s", av[L_ACE_NAME]);
1878           info_v[0] = info;
1879         }
1880       ADD_ATTR("info", info_v, LDAP_MOD_REPLACE);
1881       if (strlen(call_args[5]) != 0)
1882         {
1883           mitMoiraId_v[0] = call_args[5];
1884           ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
1885         }
1886       if (!(atoi(av[L_ACTIVE])))
1887         {
1888           member_v[0] = NULL;
1889           ADD_ATTR("member", member_v, LDAP_MOD_REPLACE);
1890         }
1891       mods[n] = NULL;
1892       rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
1893       for (i = 0; i < n; i++)
1894         free(mods[i]);
1895     }
1896
1897   sprintf(filter, "(sAMAccountName=%s)", sam_group_name);
1898   if (strlen(call_args[5]) != 0)
1899     sprintf(filter, "(&(objectClass=group) (mitMoiraId=%s))", call_args[5]);
1900   attr_array[0] = "objectSid";
1901   attr_array[1] = NULL;
1902   group_count = 0;
1903   group_base = NULL;
1904   if ((rc = linklist_build((LDAP *)call_args[0], call_args[1], filter, attr_array, 
1905                            &group_base, &group_count)) == LDAP_SUCCESS)
1906     {
1907       if (group_count != 1)
1908         {
1909           if (strlen(call_args[5]) != 0)
1910             {
1911               linklist_free(group_base);
1912               group_count = 0;
1913               group_base = NULL;
1914               sprintf(filter, "(sAMAccountName=%s)", sam_group_name);
1915               rc = linklist_build((LDAP *)call_args[0], call_args[1], filter, 
1916                                   attr_array, &group_base, &group_count);
1917             }
1918         }
1919       if (group_count == 1)
1920         {
1921           (*sid_ptr) = group_base;
1922           (*sid_ptr)->member = strdup(av[L_NAME]);
1923           (*sid_ptr)->type = (char *)GROUPS;
1924           sid_ptr = &(*sid_ptr)->next;
1925         }
1926       else
1927         {
1928           if (group_base != NULL)
1929             linklist_free(group_base);
1930         }
1931     }
1932   else
1933     {
1934       if (group_base != NULL)
1935         linklist_free(group_base);
1936     }
1937   return(LDAP_SUCCESS);
1938 }
1939
1940 int group_delete(LDAP *ldap_handle, char *dn_path, char *group_name, 
1941                  char *group_membership, char *MoiraId)
1942 {
1943   LK_ENTRY  *group_base;
1944   char      temp[512];
1945   char      filter[128];
1946   int       group_count;
1947   int       rc;
1948
1949   if (!check_string(group_name))
1950     {
1951       com_err(whoami, 0, "invalid LDAP list name %s", group_name);
1952       return(AD_INVALID_NAME);
1953     }
1954
1955   memset(filter, '\0', sizeof(filter));
1956   group_count = 0;
1957   group_base = NULL;
1958   sprintf(temp, "%s,%s", group_ou_root, dn_path);
1959   if (rc = ad_get_group(ldap_handle, temp, group_name, 
1960                         group_membership, MoiraId, 
1961                         "distinguishedName", &group_base, 
1962                         &group_count, filter))
1963     return(rc);
1964
1965   if (group_count == 1)
1966     {
1967       if ((rc = ldap_delete_s(ldap_handle, group_base->value)) != LDAP_SUCCESS)
1968         {
1969           linklist_free(group_base);
1970           com_err(whoami, 0, "Unable to delete list %s from AD : %s",
1971                   group_name, ldap_err2string(rc));
1972           return(rc);
1973         }
1974       linklist_free(group_base);
1975     }
1976   else
1977     {
1978       linklist_free(group_base);
1979       com_err(whoami, 0, "Unable to find list %s in AD.", group_name);
1980       return(AD_NO_GROUPS_FOUND);
1981     }
1982
1983   return(0);
1984 }
1985
1986 int process_lists(int ac, char **av, void *ptr)
1987 {
1988   int   rc;
1989   int   security_flag;
1990   char  group_ou[256];
1991   char  group_membership[2];
1992   char  **call_args;
1993
1994   call_args = ptr;
1995
1996   security_flag = 0;
1997   memset(group_ou, '\0', sizeof(group_ou));
1998   memset(group_membership, '\0', sizeof(group_membership));
1999   get_group_membership(group_membership, group_ou, &security_flag, av);
2000   rc = member_add((LDAP *)call_args[0], (char *)call_args[1], av[L_NAME],
2001                   group_ou, group_membership, call_args[2], 
2002                   (char *)call_args[3], "");
2003   return(0);
2004 }
2005
2006 int member_list_build(int ac, char **av, void *ptr)
2007 {
2008   LK_ENTRY  *linklist;
2009   char      temp[1024];
2010   char      **call_args;
2011
2012   call_args = ptr;
2013
2014   strcpy(temp, av[ACE_NAME]);
2015   if (!check_string(temp))
2016     return(0);
2017   if (!strcmp(av[ACE_TYPE], "USER"))
2018     {
2019       if (!((int)call_args[3] & MOIRA_USERS))
2020         return(0);
2021     }
2022   else if (!strcmp(av[ACE_TYPE], "STRING"))
2023     {
2024       if (!((int)call_args[3] & MOIRA_STRINGS))
2025         return(0);
2026       if (contact_create((LDAP *)call_args[0], call_args[1], temp, contact_ou))
2027         return(0);
2028     }
2029   else if (!strcmp(av[ACE_TYPE], "LIST"))
2030     {
2031       if (!((int)call_args[3] & MOIRA_LISTS))
2032         return(0);
2033     }
2034   else if (!strcmp(av[ACE_TYPE], "KERBEROS"))
2035     {
2036       if (!((int)call_args[3] & MOIRA_KERBEROS))
2037         return(0);
2038       if (contact_create((LDAP *)call_args[0], call_args[1], temp, kerberos_ou))
2039         return(0);
2040     }
2041   else
2042     return(0);
2043
2044   linklist = member_base;
2045   while (linklist)
2046     {
2047     if (!strcasecmp(temp, linklist->member))
2048       return(0);
2049     linklist = linklist->next;
2050     }
2051   linklist = calloc(1, sizeof(LK_ENTRY));
2052   linklist->op = 1;
2053   linklist->dn = NULL;
2054   linklist->list = calloc(1, strlen(call_args[2]) + 1);
2055   strcpy(linklist->list, call_args[2]);
2056   linklist->type = calloc(1, strlen(av[ACE_TYPE]) + 1);
2057   strcpy(linklist->type, av[ACE_TYPE]);
2058   linklist->member = calloc(1, strlen(temp) + 1);
2059   strcpy(linklist->member, temp);
2060   linklist->next = member_base;
2061   member_base = linklist;
2062   return(0);
2063 }
2064
2065 int member_remove(LDAP *ldap_handle, char *dn_path, char *group_name, 
2066                   char *group_ou, char *group_membership, char *user_name,
2067                   char *UserOu, char *MoiraId)
2068 {
2069   char        distinguished_name[1024];
2070   char        *modvalues[2];
2071   char        temp[256];
2072   char        filter[128];
2073   int         group_count;
2074   int         i;
2075   int         n;
2076   LDAPMod     *mods[20];
2077   LK_ENTRY    *group_base;
2078   ULONG       rc;
2079
2080   if (!check_string(group_name))
2081     return(AD_INVALID_NAME);
2082
2083   memset(filter, '\0', sizeof(filter));
2084   group_base = NULL;
2085   group_count = 0;
2086   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
2087                         group_membership, MoiraId, 
2088                         "distinguishedName", &group_base, 
2089                         &group_count, filter))
2090     return(rc);
2091
2092   if (group_count != 1)
2093     {
2094       com_err(whoami, 0, "LDAP server unable to find list %s in AD",
2095               group_name);
2096       linklist_free(group_base);
2097       group_base = NULL;
2098       group_count = 0;
2099       goto cleanup;
2100     }
2101   strcpy(distinguished_name, group_base->value);
2102   linklist_free(group_base);
2103   group_base = NULL;
2104   group_count = 0;
2105
2106   sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
2107   modvalues[0] = temp;
2108   modvalues[1] = NULL;
2109
2110   n = 0;
2111   ADD_ATTR("member", modvalues, LDAP_MOD_DELETE);
2112   mods[n] = NULL;
2113   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
2114   for (i = 0; i < n; i++)
2115     free(mods[i]);
2116   if ((!strcmp(UserOu, kerberos_ou)) || (!strcmp(UserOu, contact_ou)))
2117     {
2118       if (rc == LDAP_UNWILLING_TO_PERFORM)
2119         rc = LDAP_SUCCESS;
2120     }
2121   if (rc != LDAP_SUCCESS)
2122     {
2123       com_err(whoami, 0, "LDAP server unable to modify list %s members : %s",
2124               group_name, ldap_err2string(rc));
2125       goto cleanup;
2126     }
2127
2128 cleanup:
2129   return(rc);
2130 }
2131
2132 int member_add(LDAP *ldap_handle, char *dn_path, char *group_name, 
2133                char *group_ou, char *group_membership, char *user_name, 
2134                char *UserOu, char *MoiraId)
2135 {
2136   char        distinguished_name[1024];
2137   char        *modvalues[2];
2138   char        temp[256];
2139   char        filter[128];
2140   int         group_count;
2141   int         n;
2142   int         i;
2143   LDAPMod     *mods[20];
2144   LK_ENTRY    *group_base;
2145   ULONG       rc;
2146
2147   if (!check_string(group_name))
2148     return(AD_INVALID_NAME);
2149
2150   rc = 0;
2151   memset(filter, '\0', sizeof(filter));
2152   group_base = NULL;
2153   group_count = 0;
2154   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
2155                         group_membership, MoiraId, 
2156                         "distinguishedName", &group_base, 
2157                         &group_count, filter))
2158     return(rc);
2159
2160   if (group_count != 1)
2161     {
2162       linklist_free(group_base);
2163       group_base = NULL;
2164       group_count = 0;
2165       com_err(whoami, 0, "LDAP server unable to find list %s in AD",
2166               group_name);
2167       return(AD_MULTIPLE_GROUPS_FOUND);
2168     }
2169
2170   strcpy(distinguished_name, group_base->value);
2171   linklist_free(group_base);
2172   group_base = NULL;
2173   group_count = 0;
2174
2175   sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
2176   modvalues[0] = temp;
2177   modvalues[1] = NULL;
2178
2179   n = 0;
2180   ADD_ATTR("member", modvalues, LDAP_MOD_ADD);
2181   mods[n] = NULL;
2182   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
2183   if (rc == LDAP_ALREADY_EXISTS)
2184     rc = LDAP_SUCCESS;
2185   if ((!strcmp(UserOu, contact_ou)) || (!strcmp(UserOu, kerberos_ou)))
2186     {
2187       if (rc == LDAP_UNWILLING_TO_PERFORM)
2188         rc = LDAP_SUCCESS;
2189     }
2190   for (i = 0; i < n; i++)
2191     free(mods[i]);
2192   if (rc != LDAP_SUCCESS)
2193     {
2194       com_err(whoami, 0, "LDAP server unable to add %s to list %s as a member : %s",
2195               user_name, group_name, ldap_err2string(rc));
2196     }
2197
2198   return(rc);
2199 }
2200
2201 int contact_create(LDAP *ld, char *bind_path, char *user, char *group_ou)
2202 {
2203   LDAPMod *mods[20];
2204   char new_dn[256];
2205   char cn_user_name[256];
2206   char contact_name[256];
2207   char *email_v[] = {NULL, NULL};
2208   char *cn_v[] = {NULL, NULL};
2209   char *contact_v[] = {NULL, NULL};
2210   char *objectClass_v[] = {"top", "person", 
2211                            "organizationalPerson", 
2212                            "contact", NULL};
2213   char *name_v[] = {NULL, NULL};
2214   char *desc_v[] = {NULL, NULL};
2215   int  n;
2216   int  rc;
2217   int  i;
2218
2219   if (!check_string(user))
2220     {
2221       com_err(whoami, 0, "invalid LDAP name %s", user);
2222       return(AD_INVALID_NAME);
2223     }
2224   strcpy(contact_name, user);
2225   sprintf(cn_user_name,"CN=%s,%s,%s", contact_name, group_ou, bind_path);
2226   cn_v[0] = cn_user_name;
2227   contact_v[0] = contact_name;
2228   name_v[0] = user;
2229   desc_v[0] = "Auto account created by Moira";
2230   email_v[0] = user;
2231
2232   strcpy(new_dn, cn_user_name);
2233   n = 0;
2234   ADD_ATTR("cn", contact_v, LDAP_MOD_ADD);
2235   ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2236   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2237   ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2238   ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2239   if (!strcmp(group_ou, contact_ou))
2240     {
2241       ADD_ATTR("mail", email_v, LDAP_MOD_ADD);
2242     }
2243   mods[n] = NULL;
2244
2245   rc = ldap_add_ext_s(ld, new_dn, mods, NULL, NULL);
2246   for (i = 0; i < n; i++)
2247     free(mods[i]);
2248   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2249     {
2250       n = 0;
2251       ADD_ATTR("cn", contact_v, LDAP_MOD_ADD);
2252       ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2253       ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2254       ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2255       ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2256       mods[n] = NULL;
2257       rc = ldap_add_ext_s(ld, new_dn, mods, NULL, NULL);
2258       for (i = 0; i < n; i++)
2259         free(mods[i]);
2260     }
2261   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2262     {
2263       com_err(whoami, 0, "could not create contact %s : %s",
2264               user, ldap_err2string(rc));
2265       return(rc);
2266     }
2267   return(0);
2268 }
2269
2270 int user_update(LDAP *ldap_handle, char *dn_path, char *user_name,
2271                 char *Uid, char *MitId, char *MoiraId, int State)
2272 {
2273   LDAPMod   *mods[20];
2274   LK_ENTRY  *group_base;
2275   int  group_count;
2276   char distinguished_name[256];
2277   char *mitMoiraId_v[] = {NULL, NULL};
2278   char *uid_v[] = {NULL, NULL};
2279   char *mitid_v[] = {NULL, NULL};
2280   char *homedir_v[] = {NULL, NULL};
2281   char *winProfile_v[] = {NULL, NULL};
2282   char *drives_v[] = {NULL, NULL};
2283   char *userAccountControl_v[] = {NULL, NULL};
2284   char userAccountControlStr[80];
2285   int  n;
2286   int  rc;
2287   int  i;
2288   int  last_weight;
2289   u_int userAccountControl = UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD | UF_PASSWD_CANT_CHANGE;
2290   char filter[128];
2291   char *attr_array[3];
2292   char cWeight[3];
2293   char **hp;
2294   char path[256];
2295   char cPath[256];
2296   char temp[256];
2297   char winPath[256];
2298   char winProfile[256];
2299
2300   if (!check_string(user_name))
2301     {
2302       com_err(whoami, 0, "invalid LDAP user name %s", user_name);
2303       return(AD_INVALID_NAME);
2304     }
2305
2306   group_count = 0;
2307   group_base = NULL;
2308
2309   if (strlen(MoiraId) != 0)
2310     {
2311       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
2312       attr_array[0] = "cn";
2313       attr_array[1] = NULL;
2314       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
2315                                &group_base, &group_count)) != 0)
2316         {
2317           com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
2318                   user_name, ldap_err2string(rc));
2319           return(rc);
2320         }
2321     }
2322   if (group_count != 1)
2323     {
2324       linklist_free(group_base);
2325       group_base = NULL;
2326       group_count = 0;
2327       sprintf(filter, "(sAMAccountName=%s)", user_name);
2328       attr_array[0] = "cn";
2329       attr_array[1] = NULL;
2330       sprintf(temp, "%s,%s", user_ou, dn_path);
2331       if ((rc = linklist_build(ldap_handle, temp, filter, attr_array, 
2332                                &group_base, &group_count)) != 0)
2333         {
2334           com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
2335                   user_name, ldap_err2string(rc));
2336           return(rc);
2337         }
2338     }
2339
2340   if (group_count != 1)
2341     {
2342       com_err(whoami, 0, "LDAP server unable to find user %s in AD",
2343               user_name);
2344       linklist_free(group_base);
2345       return(AD_NO_USER_FOUND);
2346     }
2347   strcpy(distinguished_name, group_base->dn);
2348
2349   linklist_free(group_base);
2350   group_count = 0;
2351   n = 0;
2352   if ((hp = hes_resolve(user_name, "filsys")) != NULL)
2353     {
2354       memset(cWeight, 0, sizeof(cWeight));
2355       memset(cPath, 0, sizeof(cPath));
2356       memset(path, 0, sizeof(path));
2357       memset(winPath, 0, sizeof(winPath));
2358       last_weight = 1000;
2359       i = 0;
2360       while (hp[i] != NULL)
2361         {
2362           if (sscanf(hp[i], "%*s %s", cPath))
2363             {
2364               if (strnicmp(cPath, AFS, strlen(AFS)) == 0)
2365                 {
2366                   if (sscanf(hp[i], "%*s %*s %*s %*s %s", cWeight))
2367                     {
2368                       if (atoi(cWeight) < last_weight)
2369                         {
2370                           strcpy(path, cPath);
2371                           last_weight = (int)atoi(cWeight);
2372                         }
2373                     }
2374                   else 
2375                     strcpy(path, cPath);
2376                 }
2377             }
2378           ++i;
2379         }
2380       if (strlen(path))
2381         {
2382           if (!strnicmp(path, AFS, strlen(AFS)))
2383             {
2384               AfsToWinAfs(path, winPath);
2385               homedir_v[0] = winPath;
2386               ADD_ATTR("homeDirectory", homedir_v, LDAP_MOD_REPLACE);
2387               strcpy(winProfile, winPath);
2388               strcat(winProfile, "\\.winprofile");
2389               winProfile_v[0] = winProfile;
2390               ADD_ATTR("profilePath", winProfile_v, LDAP_MOD_REPLACE);
2391               drives_v[0] = "H:";
2392               ADD_ATTR("homeDrive", drives_v, LDAP_MOD_REPLACE);
2393             }
2394         }
2395     }
2396   uid_v[0] = Uid;
2397   if (strlen(Uid) == 0)
2398     uid_v[0] = NULL;
2399   ADD_ATTR("uid", uid_v, LDAP_MOD_REPLACE);
2400   ADD_ATTR("uidNumber", uid_v, LDAP_MOD_REPLACE);
2401   mitid_v[0] = MitId;
2402   if (strlen(MitId) == 0)
2403     mitid_v[0] = NULL;
2404   ADD_ATTR("employeeID", mitid_v, LDAP_MOD_REPLACE);
2405   mitMoiraId_v[0] = MoiraId;
2406   if (strlen(MoiraId) == 0)
2407     mitMoiraId_v[0] = NULL;
2408   ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
2409   if ((State != US_NO_PASSWD) && (State != US_REGISTERED))
2410     userAccountControl |= UF_ACCOUNTDISABLE;
2411   sprintf(userAccountControlStr, "%ld", userAccountControl);
2412   userAccountControl_v[0] = userAccountControlStr;
2413   ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_REPLACE);
2414   mods[n] = NULL;
2415   if ((rc = ldap_modify_s(ldap_handle, distinguished_name, mods)) != LDAP_SUCCESS)
2416     {
2417       com_err(whoami, 0, "Couldn't modify user data for %s : %s",
2418               user_name, ldap_err2string(rc));
2419     }
2420   for (i = 0; i < n; i++)
2421     free(mods[i]);
2422
2423   if (hp != NULL)
2424     {
2425       i = 0;
2426       while (hp[i])
2427         {
2428           free(hp[i]);
2429           i++;
2430         }
2431     }
2432
2433   return(rc);
2434 }
2435
2436 int user_rename(LDAP *ldap_handle, char *dn_path, char *before_user_name, 
2437                 char *user_name)
2438 {
2439   LDAPMod *mods[20];
2440   char new_dn[256];
2441   char old_dn[256];
2442   char upn[256];
2443   char temp[128];
2444   char *userPrincipalName_v[] = {NULL, NULL};
2445   char *altSecurityIdentities_v[] = {NULL, NULL};
2446   char *name_v[] = {NULL, NULL};
2447   char *samAccountName_v[] = {NULL, NULL};
2448   int  n;
2449   int  rc;
2450   int  i;
2451
2452   if (!check_string(before_user_name))
2453     {
2454       com_err(whoami, 0, "invalid LDAP user name %s", before_user_name);
2455       return(AD_INVALID_NAME);
2456     }
2457   if (!check_string(user_name))
2458     {
2459       com_err(whoami, 0, "invalid LDAP user name %s", user_name);
2460       return(AD_INVALID_NAME);
2461     }
2462
2463   strcpy(user_name, user_name);
2464   sprintf(old_dn, "cn=%s,%s,%s", before_user_name, user_ou, dn_path);
2465   sprintf(new_dn, "cn=%s", user_name);
2466   if ((rc = ldap_rename_s(ldap_handle, old_dn, new_dn, NULL, TRUE, 
2467                            NULL, NULL)) != LDAP_SUCCESS)
2468     {
2469       com_err(whoami, 0, "Couldn't rename user from %s to %s : %s",
2470               before_user_name, user_name, ldap_err2string(rc));
2471       return(rc);
2472     }
2473
2474   name_v[0] = user_name;
2475   sprintf(upn, "%s@%s", user_name, ldap_domain);
2476   userPrincipalName_v[0] = upn;
2477   sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
2478   altSecurityIdentities_v[0] = temp;
2479   samAccountName_v[0] = user_name;
2480
2481   n = 0;
2482   ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_REPLACE);
2483   ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_REPLACE);
2484   ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
2485   ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_REPLACE);
2486   mods[n] = NULL;
2487   sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, dn_path);
2488   if ((rc = ldap_modify_s(ldap_handle, new_dn, mods)) != LDAP_SUCCESS)
2489     {
2490       com_err(whoami, 0, "After renaming, couldn't modify user data for %s : %s",
2491               user_name, ldap_err2string(rc));
2492     }
2493   for (i = 0; i < n; i++)
2494     free(mods[i]);
2495   return(rc);
2496 }
2497
2498 int filesys_process(LDAP *ldap_handle, char *dn_path, char *fs_name, 
2499                     char *fs_type, char *fs_pack, int operation)
2500 {
2501   char  distinguished_name[256];
2502   char  winPath[256];
2503   char  winProfile[256];
2504   char  filter[128];
2505   char  *attr_array[3];
2506   char  *homedir_v[] = {NULL, NULL};
2507   char  *winProfile_v[] = {NULL, NULL};
2508   char  *drives_v[] = {NULL, NULL};
2509   int   group_count;
2510   int   n;
2511   int   rc;
2512   int   i;
2513   LDAPMod   *mods[20];
2514   LK_ENTRY  *group_base;
2515
2516   if (!check_string(fs_name))
2517     {
2518       com_err(whoami, 0, "invalid filesys name %s", fs_name);
2519       return(AD_INVALID_NAME);
2520     }
2521
2522   if (strcmp(fs_type, "AFS"))
2523     {
2524       com_err(whoami, 0, "invalid filesys type %s", fs_type);
2525       return(AD_INVALID_FILESYS);
2526     }
2527
2528   group_count = 0;
2529   group_base = NULL;
2530   sprintf(filter, "(sAMAccountName=%s)", fs_name);
2531   attr_array[0] = "cn";
2532   attr_array[1] = NULL;
2533   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
2534                            &group_base, &group_count)) != 0)
2535     {
2536       com_err(whoami, 0, "LDAP server couldn't process filesys %s : %s",
2537               fs_name, ldap_err2string(rc));
2538       return(rc);
2539     }
2540
2541   if (group_count != 1)
2542     {
2543       linklist_free(group_base);
2544       com_err(whoami, 0, "LDAP server unable to find user %s in AD",
2545               fs_name);
2546       return(LDAP_NO_SUCH_OBJECT);
2547     }
2548   strcpy(distinguished_name, group_base->dn);
2549   linklist_free(group_base);
2550   group_count = 0;
2551
2552   n = 0;
2553   if (operation == LDAP_MOD_ADD)
2554     {
2555       memset(winPath, 0, sizeof(winPath));
2556       AfsToWinAfs(fs_pack, winPath);
2557       homedir_v[0] = winPath;
2558       drives_v[0] = "H:";
2559       memset(winProfile, 0, sizeof(winProfile));
2560       strcpy(winProfile, winPath);
2561       strcat(winProfile, "\\.winprofile");
2562       winProfile_v[0] = winProfile;
2563     }
2564   else
2565     {
2566       homedir_v[0] = NULL;
2567       drives_v[0] = NULL;
2568       winProfile_v[0] = NULL;
2569     }
2570   ADD_ATTR("profilePath", winProfile_v, operation);
2571   ADD_ATTR("homeDrive", drives_v, operation);
2572   ADD_ATTR("homeDirectory", homedir_v, operation);
2573   mods[n] = NULL;
2574
2575   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
2576   if (rc != LDAP_SUCCESS)
2577     {
2578       com_err(whoami, 0, "Couldn't modify user data for filesys %s : %s",
2579               fs_name, ldap_err2string(rc));
2580     }
2581   for (i = 0; i < n; i++)
2582     free(mods[i]);
2583
2584   return(rc);
2585 }
2586
2587 int user_create(int ac, char **av, void *ptr)
2588 {
2589   LK_ENTRY  *group_base;
2590   LDAPMod *mods[20];
2591   char new_dn[256];
2592   char user_name[256];
2593   char sam_name[256];
2594   char upn[256];
2595   char *cn_v[] = {NULL, NULL};
2596   char *objectClass_v[] = {"top", "person", 
2597                            "organizationalPerson", 
2598                            "user", NULL};
2599
2600   char *samAccountName_v[] = {NULL, NULL};
2601   char *altSecurityIdentities_v[] = {NULL, NULL};
2602   char *mitMoiraId_v[] = {NULL, NULL};
2603   char *name_v[] = {NULL, NULL};
2604   char *desc_v[] = {NULL, NULL};
2605   char *userPrincipalName_v[] = {NULL, NULL};
2606   char *userAccountControl_v[] = {NULL, NULL};
2607   char *uid_v[] = {NULL, NULL};
2608   char *mitid_v[] = {NULL, NULL};
2609   char userAccountControlStr[80];
2610   char temp[128];
2611   u_int userAccountControl = UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD | UF_PASSWD_CANT_CHANGE;
2612   int  n;
2613   int  rc;
2614   int  i;
2615   int  group_count;
2616   char filter[128];
2617   char *attr_array[3];
2618   char **call_args;
2619
2620   call_args = ptr;
2621
2622   if (!check_string(av[U_NAME]))
2623     {
2624       callback_rc = AD_INVALID_NAME;
2625       com_err(whoami, 0, "invalid LDAP user name %s", av[U_NAME]);
2626       return(AD_INVALID_NAME);
2627     }
2628
2629   strcpy(user_name, av[U_NAME]);
2630   sprintf(upn, "%s@%s", user_name, ldap_domain);
2631   sprintf(sam_name, "%s", av[U_NAME]);
2632   samAccountName_v[0] = sam_name;
2633   if ((atoi(av[U_STATE]) != US_NO_PASSWD) && (atoi(av[U_STATE]) != US_REGISTERED))
2634     userAccountControl |= UF_ACCOUNTDISABLE;
2635   sprintf(userAccountControlStr, "%ld", userAccountControl);
2636   userAccountControl_v[0] = userAccountControlStr;
2637   userPrincipalName_v[0] = upn;
2638
2639   cn_v[0] = user_name;
2640   name_v[0] = user_name;
2641   desc_v[0] = "Auto account created by Moira";
2642   sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
2643   altSecurityIdentities_v[0] = temp;    
2644   sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, call_args[1]);
2645
2646   n = 0;
2647   ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
2648   ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2649   ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
2650   ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_ADD);
2651   ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_ADD);
2652   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2653   ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2654   ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2655   if (strlen(call_args[2]) != 0)
2656     {
2657       mitMoiraId_v[0] = call_args[2];
2658       ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_ADD);
2659     }
2660   ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_ADD);
2661   if (strlen(av[U_UID]) != 0)
2662     {
2663       uid_v[0] = av[U_UID];
2664       ADD_ATTR("uid", uid_v, LDAP_MOD_ADD);
2665       ADD_ATTR("uidNumber", uid_v, LDAP_MOD_ADD);
2666     }
2667   if (strlen(av[U_MITID]) != 0)
2668       mitid_v[0] = av[U_MITID];
2669   else
2670       mitid_v[0] = "none";
2671   ADD_ATTR("employeeID", mitid_v, LDAP_MOD_ADD);
2672   mods[n] = NULL;
2673
2674   rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
2675   for (i = 0; i < n; i++)
2676     free(mods[i]);
2677   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2678     {
2679       com_err(whoami, 0, "could not create user %s : %s",
2680               user_name, ldap_err2string(rc));
2681       callback_rc = rc;
2682       return(rc);
2683     }
2684   if (rc == LDAP_SUCCESS)
2685     {
2686       if ((rc = set_password(sam_name, "", ldap_domain)) != 0)
2687         {
2688           com_err(whoami, 0, "Couldn't set password for user %s : %ld",
2689                   user_name, rc);
2690         }
2691     }
2692   sprintf(filter, "(sAMAccountName=%s)", av[U_NAME]);
2693   if (strlen(call_args[2]) != 0)
2694     sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", call_args[2]);
2695   attr_array[0] = "objectSid";
2696   attr_array[1] = NULL;
2697   group_count = 0;
2698   group_base = NULL;
2699   if ((rc = linklist_build((LDAP *)call_args[0], call_args[1], filter, attr_array, 
2700                            &group_base, &group_count)) == LDAP_SUCCESS)
2701     {
2702       if (group_count != 1)
2703         {
2704           if (strlen(call_args[2]) != 0)
2705             {
2706               linklist_free(group_base);
2707               group_count = 0;
2708               group_base = NULL;
2709               sprintf(filter, "(sAMAccountName=%s)", av[U_NAME]);
2710               rc = linklist_build((LDAP *)call_args[0], call_args[1], filter, 
2711                                   attr_array, &group_base, &group_count);
2712             }
2713         }
2714       if (group_count == 1)
2715         {
2716           (*sid_ptr) = group_base;
2717           (*sid_ptr)->member = strdup(av[U_NAME]);
2718           (*sid_ptr)->type = (char *)GROUPS;
2719           sid_ptr = &(*sid_ptr)->next;
2720         }
2721       else
2722         {
2723           if (group_base != NULL)
2724             linklist_free(group_base);
2725         }
2726     }
2727   else
2728     {
2729       if (group_base != NULL)
2730         linklist_free(group_base);
2731     }
2732   return(0);
2733 }
2734
2735 int user_change_status(LDAP *ldap_handle, char *dn_path, 
2736                        char *user_name, char *MoiraId,
2737                        int operation)
2738 {
2739   char      filter[128];
2740   char      *attr_array[3];
2741   char      temp[256];
2742   char      distinguished_name[1024];
2743   char      **modvalues;
2744   char      *mitMoiraId_v[] = {NULL, NULL};
2745   LDAPMod   *mods[20];
2746   LK_ENTRY  *group_base;
2747   int       group_count;
2748   int       rc;
2749   int       i;
2750   int       n;
2751   ULONG     ulongValue;
2752
2753   if (!check_string(user_name))
2754     {
2755       com_err(whoami, 0, "invalid LDAP user name %s", user_name);
2756       return(AD_INVALID_NAME);
2757     }
2758
2759   group_count = 0;
2760   group_base = NULL;
2761
2762   if (strlen(MoiraId) != 0)
2763     {
2764       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
2765       attr_array[0] = "UserAccountControl";
2766       attr_array[1] = NULL;
2767       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
2768                                &group_base, &group_count)) != 0)
2769         {
2770           com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
2771                   user_name, ldap_err2string(rc));
2772           return(rc);
2773         }
2774     }
2775   if (group_count != 1)
2776     {
2777       linklist_free(group_base);
2778       group_count = 0;
2779       group_base = NULL;
2780       sprintf(filter, "(sAMAccountName=%s)", user_name);
2781       attr_array[0] = "UserAccountControl";
2782       attr_array[1] = NULL;
2783       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
2784                                &group_base, &group_count)) != 0)
2785         {
2786           com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
2787                   user_name, ldap_err2string(rc));
2788           return(rc);
2789         }
2790     }
2791
2792   if (group_count != 1)
2793     {
2794       linklist_free(group_base);
2795       com_err(whoami, 0, "LDAP server unable to find user %s in AD",
2796               user_name);
2797       return(LDAP_NO_SUCH_OBJECT);
2798     }
2799
2800   strcpy(distinguished_name, group_base->dn);
2801   ulongValue = atoi((*group_base).value);
2802   if (operation == MEMBER_DEACTIVATE)
2803     ulongValue |= UF_ACCOUNTDISABLE;
2804   else    
2805     ulongValue &= ~UF_ACCOUNTDISABLE;
2806   sprintf(temp, "%ld", ulongValue);
2807   if ((rc = construct_newvalues(group_base, group_count, (*group_base).value, 
2808                                 temp, &modvalues, REPLACE)) == 1)
2809     goto cleanup;
2810   linklist_free(group_base);
2811   group_base = NULL;
2812   group_count = 0;
2813   n = 0;
2814   ADD_ATTR("UserAccountControl", modvalues, LDAP_MOD_REPLACE);
2815   if (strlen(MoiraId) != 0)
2816     {
2817     mitMoiraId_v[0] = MoiraId;
2818     ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
2819     }
2820   mods[n] = NULL;
2821   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
2822   for (i = 0; i < n; i++)
2823     free(mods[i]);
2824   free_values(modvalues);
2825   if (rc != LDAP_SUCCESS)
2826     {
2827       com_err(whoami, 0, "LDAP server could not change status of user %s : %s",
2828               user_name, ldap_err2string(rc));
2829     }
2830 cleanup:
2831   return(rc);
2832 }
2833
2834 int user_delete(LDAP *ldap_handle, char *dn_path, 
2835                 char *u_name, char *MoiraId)
2836 {
2837   char      filter[128];
2838   char      *attr_array[3];
2839   char      distinguished_name[1024];
2840   char      user_name[512];
2841   LK_ENTRY  *group_base;
2842   int       group_count;
2843   int       rc;
2844
2845   if (!check_string(u_name))
2846     return(AD_INVALID_NAME);
2847
2848   strcpy(user_name, u_name);
2849   group_count = 0;
2850   group_base = NULL;
2851
2852   if (strlen(MoiraId) != 0)
2853     {
2854       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
2855       attr_array[0] = "name";
2856       attr_array[1] = NULL;
2857       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
2858                                &group_base, &group_count)) != 0)
2859         {
2860           com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
2861                   user_name, ldap_err2string(rc));
2862           goto cleanup;
2863         }
2864     }
2865   if (group_count != 1)
2866     {
2867       linklist_free(group_base);
2868       group_count = 0;
2869       group_base = NULL;
2870       sprintf(filter, "(sAMAccountName=%s)", user_name);
2871       attr_array[0] = "name";
2872       attr_array[1] = NULL;
2873       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
2874                                &group_base, &group_count)) != 0)
2875         {
2876           com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
2877                   user_name, ldap_err2string(rc));
2878           goto cleanup;
2879         }
2880     }
2881
2882   if (group_count != 1)
2883     {
2884       com_err(whoami, 0, "LDAP server unable to find user %s in AD",
2885               user_name);
2886       goto cleanup;
2887     }
2888
2889   strcpy(distinguished_name, group_base->dn);
2890   if (rc = ldap_delete_s(ldap_handle, distinguished_name))
2891     {
2892       com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
2893               user_name, ldap_err2string(rc));
2894     }
2895
2896 cleanup:
2897   linklist_free(group_base);
2898   return(0);
2899 }
2900
2901 void linklist_free(LK_ENTRY *linklist_base)
2902 {
2903   LK_ENTRY *linklist_previous;
2904
2905   while (linklist_base != NULL)
2906     {
2907       if (linklist_base->dn != NULL)
2908         free(linklist_base->dn);
2909       if (linklist_base->attribute != NULL)
2910         free(linklist_base->attribute);
2911       if (linklist_base->value != NULL)
2912         free(linklist_base->value);
2913       if (linklist_base->member != NULL)
2914         free(linklist_base->member);
2915       if (linklist_base->type != NULL)
2916         free(linklist_base->type);
2917       if (linklist_base->list != NULL)
2918         free(linklist_base->list);
2919       linklist_previous = linklist_base;
2920       linklist_base = linklist_previous->next;
2921       free(linklist_previous);
2922     }
2923 }
2924
2925 void free_values(char **modvalues)
2926 {
2927   int i;
2928
2929   i = 0;
2930   if (modvalues != NULL)
2931     {
2932     while (modvalues[i] != NULL)
2933       {
2934         free(modvalues[i]);
2935         modvalues[i] = NULL;
2936         ++i;
2937       }
2938     free(modvalues);
2939   }
2940 }
2941
2942 int sid_update(LDAP *ldap_handle, char *dn_path)
2943 {
2944   LK_ENTRY      *ptr;
2945   int           rc;
2946   unsigned char temp[126];
2947   char          *av[3];
2948
2949   ptr = sid_base;
2950
2951   while (ptr != NULL)
2952     {
2953       memset(temp, 0, sizeof(temp));
2954       convert_b_to_a(temp, ptr->value, ptr->length);
2955       if (!ptr->member)
2956         continue;
2957       av[0] = ptr->member;
2958       av[1] = temp;
2959       if (ptr->type == (char *)GROUPS)
2960         {
2961           ptr->type = NULL;
2962           rc = mr_query("add_list_sid_by_name", 2, av, NULL, NULL);
2963         }
2964       else if (ptr->type == (char *)USERS)
2965         {
2966           ptr->type = NULL;
2967           rc = mr_query("add_user_sid_by_login", 2, av, NULL, NULL);
2968         }
2969       ptr = ptr->next;
2970     }
2971   return(0);
2972 }
2973
2974 void convert_b_to_a(char *string, UCHAR *binary, int length)
2975 {
2976   int   i;
2977   int   j;
2978   UCHAR tmp;
2979
2980   j = 0;
2981   for (i = 0; i < length; i++)
2982     {
2983       tmp = binary[i];
2984       string[j] = tmp;
2985       string[j] >>= 4;
2986       string[j] &= 0x0f;
2987       string[j] += 0x30;
2988       if (string[j] > '9')
2989         string[j] += 0x27;
2990       ++j;
2991       string[j] = tmp & 0x0f;
2992       string[j] += 0x30;
2993       if (string[j] > '9')
2994         string[j] += 0x27;
2995       j++;
2996     }
2997   string[j] = 0;
2998 }
2999
3000 static int illegalchars[] = {
3001   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
3002   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
3003   1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, /* SPACE - / */
3004   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 0 - ? */
3005   0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
3006   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* P - _ */
3007   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
3008   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
3009   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3010   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3011   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3012   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3013   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3014   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3015   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3016   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3017 };
3018
3019 int check_string(char *s)
3020 {
3021   char  character;
3022
3023   for (; *s; s++)
3024     {
3025       character = *s;
3026       if (isupper(character))
3027         character = tolower(character);
3028       if (illegalchars[(unsigned) character])
3029         return 0;
3030     }
3031   return 1;
3032 }
3033
3034 int mr_connect_cl(char *server, char *client, int version, int auth)
3035 {
3036   int   status;
3037   char  *motd;
3038   char  temp[128];
3039
3040   status = mr_connect(server);
3041   if (status)
3042     {
3043       com_err(whoami, status, "while connecting to Moira");
3044       return status;
3045     }
3046
3047   status = mr_motd(&motd);
3048   if (status)
3049     {
3050       mr_disconnect();
3051       com_err(whoami, status, "while checking server status");
3052       return status;
3053     }
3054   if (motd)
3055     {
3056       sprintf(temp, "The Moira server is currently unavailable: %s", motd);
3057       com_err(whoami, status, temp);
3058       mr_disconnect();
3059       return status;
3060     }
3061
3062   status = mr_version(version);
3063   if (status)
3064     {
3065       if (status == MR_UNKNOWN_PROC)
3066         {
3067           if (version > 2)
3068             status = MR_VERSION_HIGH;
3069           else
3070             status = MR_SUCCESS;
3071         }
3072
3073       if (status == MR_VERSION_HIGH)
3074         {
3075           com_err(whoami, 0, "Warning: This client is running newer code than the server.");
3076                   com_err(whoami, 0, "Some operations may not work.");
3077         }
3078       else if (status && status != MR_VERSION_LOW)
3079         {
3080           com_err(whoami, status, "while setting query version number.");
3081           mr_disconnect();
3082           return status;
3083         }
3084     }
3085
3086   if (auth)
3087     {
3088       status = mr_auth(client);
3089       if (status)
3090         {
3091           com_err(whoami, status, "while authenticating to Moira.");
3092           mr_disconnect();
3093           return status;
3094         }
3095     }
3096
3097   return MR_SUCCESS;
3098 }
3099
3100 void AfsToWinAfs(char* path, char* winPath)
3101 {
3102     char* pathPtr;
3103     char* winPathPtr;
3104     strcpy(winPath, WINAFS);
3105     pathPtr = path + strlen(AFS);
3106     winPathPtr = winPath + strlen(WINAFS);
3107
3108     while (*pathPtr)
3109     {
3110         if (*pathPtr == '/')
3111           *winPathPtr = '\\';
3112         else
3113           *winPathPtr = *pathPtr;
3114
3115         pathPtr++;
3116         winPathPtr++;
3117     }
3118 }
3119
3120 int make_new_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
3121                    char *group_name, char *group_ou, char *group_membership, 
3122                    int group_security_flag, int updateGroup)
3123 {
3124   char  *av[3];
3125   char  *call_args[7];
3126   int   rc;
3127
3128   av[0] = group_name;
3129   call_args[0] = (char *)ldap_handle;
3130   call_args[1] = dn_path;
3131   call_args[2] = group_name;
3132   call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
3133   call_args[4] = (char *)updateGroup;
3134   call_args[5] = MoiraId;
3135   call_args[6] = NULL;
3136   sid_base = NULL;
3137   sid_ptr = &sid_base;
3138   callback_rc = 0;
3139   if (rc = mr_query("get_list_info", 1, av, group_create, call_args))
3140     {
3141       moira_disconnect();
3142       com_err(whoami, 0, "Couldn't create list %s : %s", group_name, error_message(rc));
3143       return(rc);
3144     }
3145   if (callback_rc)
3146     {
3147       moira_disconnect();
3148       com_err(whoami, 0, "Couldn't create list %s", group_name);
3149       return(callback_rc);
3150     }
3151
3152   if (sid_base != NULL)
3153     {
3154       sid_update(ldap_handle, dn_path);
3155       linklist_free(sid_base);
3156       sid_base = NULL;
3157     }
3158   return(0);
3159 }
3160
3161 int populate_group(LDAP *ldap_handle, char *dn_path, char *group_name, 
3162                    char *group_ou, char *group_membership, 
3163                    int group_security_flag, char *MoiraId)
3164 {
3165   char      *av[3];
3166   char      *call_args[7];
3167   char      *pUserOu;
3168   LK_ENTRY  *ptr;
3169   int       rc;
3170
3171   com_err(whoami, 0, "Populating group %s", group_name);
3172   av[0] = group_name;
3173   call_args[0] = (char *)ldap_handle;
3174   call_args[1] = dn_path;
3175   call_args[2] = group_name;
3176   call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
3177   call_args[4] = NULL;
3178   member_base = NULL;
3179   if (rc = mr_query("get_end_members_of_list", 1, av,
3180                     member_list_build, call_args))
3181     {
3182       com_err(whoami, 0, "Couldn't populate list %s : %s", 
3183               group_name, error_message(rc));
3184       return(3);
3185     }
3186   if (member_base != NULL)
3187     {
3188       ptr = member_base;
3189       while (ptr != NULL)
3190         {
3191           if (!strcasecmp(ptr->type, "LIST"))
3192             {
3193               ptr = ptr->next;
3194               continue;
3195             }
3196           pUserOu = user_ou;
3197           if (!strcasecmp(ptr->type, "STRING"))
3198             {
3199               if (contact_create(ldap_handle, dn_path, ptr->member, contact_ou))
3200                 return(3);
3201               pUserOu = contact_ou;
3202             }
3203           else if (!strcasecmp(ptr->type, "KERBEROS"))
3204             {
3205               if (contact_create(ldap_handle, dn_path, ptr->member, kerberos_ou))
3206                 return(3);
3207               pUserOu = kerberos_ou;
3208             }
3209           rc = member_add(ldap_handle, dn_path, group_name,
3210                           group_ou, group_membership, ptr->member, 
3211                           pUserOu, MoiraId);
3212           ptr = ptr->next;
3213         }
3214       linklist_free(member_base);
3215       member_base = NULL;
3216     }
3217   return(0);
3218 }
3219
3220 int process_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
3221                   char *group_name, char *group_ou, char *group_membership, 
3222                   int group_security_flag, int type)
3223 {
3224   char      before_desc[512];
3225   char      before_name[256];
3226   char      before_group_ou[256];
3227   char      before_group_membership[2];
3228   char      distinguishedName[256];
3229   char      ad_distinguishedName[256];
3230   char      filter[128];
3231   char      *attr_array[3];
3232   int       before_security_flag;
3233   int       group_count;
3234   int       rc;
3235   LK_ENTRY  *group_base;
3236   LK_ENTRY  *ptr;
3237   char      ou_both[512];
3238   char      ou_security[512];
3239   char      ou_distribution[512];
3240   char      ou_neither[512];
3241
3242   memset(ad_distinguishedName, '\0', sizeof(ad_distinguishedName));
3243   sprintf(distinguishedName, "CN=%s,%s,%s", group_name, group_ou, dn_path);
3244
3245
3246   memset(filter, '\0', sizeof(filter));
3247   group_base = NULL;
3248   group_count = 0;
3249   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
3250                         "*", MoiraId, 
3251                         "distinguishedName", &group_base, 
3252                         &group_count, filter))
3253     return(rc);
3254
3255   if (type == CHECK_GROUPS)
3256     {
3257       if (group_count == 1)
3258         {
3259           if (!strcasecmp(group_base->value, distinguishedName))
3260             {
3261               linklist_free(group_base);
3262               return(0);
3263             }
3264         }
3265       linklist_free(group_base);
3266       if (group_count == 0)
3267         return(AD_NO_GROUPS_FOUND);
3268       if (group_count == 1)
3269         return(AD_WRONG_GROUP_DN_FOUND);
3270       return(AD_MULTIPLE_GROUPS_FOUND);
3271     }
3272   if (group_count == 0)
3273     {
3274       return(AD_NO_GROUPS_FOUND);
3275     }
3276   if (group_count > 1)
3277     {
3278       ptr = group_base;
3279       while (ptr != NULL)
3280         {
3281           if (!strcasecmp(distinguishedName, ptr->value))
3282             break;
3283           ptr = ptr->next;
3284         }
3285       if (ptr == NULL)
3286         {
3287           com_err(whoami, 0, "%d groups with moira id = %s", group_count, MoiraId);
3288           ptr = group_base;
3289           while (ptr != NULL)
3290             {
3291               com_err(whoami, 0, "%s with moira id = %s", ptr->value, MoiraId);
3292               ptr = ptr->next;
3293             }
3294           linklist_free(group_base);
3295           return(AD_MULTIPLE_GROUPS_FOUND);
3296         } 
3297       ptr = group_base;
3298       while (ptr != NULL)
3299         {
3300           if (strcasecmp(distinguishedName, ptr->value))
3301             rc = ldap_delete_s(ldap_handle, ptr->value);
3302           ptr = ptr->next;
3303         }
3304       linklist_free(group_base);
3305       memset(filter, '\0', sizeof(filter));
3306       group_base = NULL;
3307       group_count = 0;
3308       if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
3309                             "*", MoiraId, 
3310                             "distinguishedName", &group_base, 
3311                             &group_count, filter))
3312         return(rc);
3313       if (group_count == 0)
3314         return(AD_NO_GROUPS_FOUND);
3315       if (group_count > 1)
3316         return(AD_MULTIPLE_GROUPS_FOUND);
3317     }
3318
3319   strcpy(ad_distinguishedName, group_base->value);
3320   linklist_free(group_base);
3321   group_base = NULL;
3322   group_count = 0;
3323
3324   attr_array[0] = "sAMAccountName";
3325   attr_array[1] = NULL;
3326   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3327                            &group_base, &group_count)) != 0)
3328     {
3329       com_err(whoami, 0, "LDAP server unable to get list info with MoiraId = %s: %s",
3330                MoiraId, ldap_err2string(rc));
3331       return(rc);
3332     }
3333   sprintf(filter, "(sAMAccountName=%s)", group_base->value);
3334
3335   if (!strcasecmp(ad_distinguishedName, distinguishedName))
3336     {
3337       linklist_free(group_base);
3338       group_base = NULL;
3339       group_count = 0;
3340       return(0);
3341     }
3342   linklist_free(group_base);
3343   group_base = NULL;
3344   group_count = 0;
3345   memset(ou_both, '\0', sizeof(ou_both));
3346   memset(ou_security, '\0', sizeof(ou_security));
3347   memset(ou_distribution, '\0', sizeof(ou_distribution));
3348   memset(ou_neither, '\0', sizeof(ou_neither));
3349   memset(before_name, '\0', sizeof(before_name));
3350   memset(before_desc, '\0', sizeof(before_desc));
3351   memset(before_group_membership, '\0', sizeof(before_group_membership));
3352   attr_array[0] = "name";
3353   attr_array[1] = NULL;
3354   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3355                            &group_base, &group_count)) != 0)
3356     {
3357       com_err(whoami, 0, "LDAP server unable to get list name with MoiraId = %s: %s",
3358               MoiraId, ldap_err2string(rc));
3359       return(rc);
3360     }
3361   strcpy(before_name, group_base->value);
3362   linklist_free(group_base);
3363   group_base = NULL;
3364   group_count = 0;
3365   attr_array[0] = "description";
3366   attr_array[1] = NULL;
3367   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3368                            &group_base, &group_count)) != 0)
3369     {
3370       com_err(whoami, 0, 
3371               "LDAP server unable to get list description with MoiraId = %s: %s",
3372               MoiraId, ldap_err2string(rc));
3373       return(rc);
3374     }
3375   if (group_count != 0)
3376     {
3377       strcpy(before_desc, group_base->value);
3378       linklist_free(group_base);
3379       group_base = NULL;
3380       group_count = 0;
3381     }
3382   change_to_lower_case(ad_distinguishedName);  
3383   strcpy(ou_both, group_ou_both);
3384   change_to_lower_case(ou_both);
3385   strcpy(ou_security, group_ou_security);
3386   change_to_lower_case(ou_security);
3387   strcpy(ou_distribution, group_ou_distribution);
3388   change_to_lower_case(ou_distribution);
3389   strcpy(ou_neither, group_ou_neither);
3390   change_to_lower_case(ou_neither);
3391   if (strstr(ad_distinguishedName, ou_both))
3392     {
3393       strcpy(before_group_ou, group_ou_both);
3394       before_group_membership[0] = 'B';
3395       before_security_flag = 1;
3396     }
3397   else if (strstr(ad_distinguishedName, ou_security))
3398     {
3399       strcpy(before_group_ou, group_ou_security);
3400       before_group_membership[0] = 'S';
3401       before_security_flag = 1;
3402     }
3403   else if (strstr(ad_distinguishedName, ou_distribution))
3404     {
3405       strcpy(before_group_ou, group_ou_distribution);
3406       before_group_membership[0] = 'D';
3407       before_security_flag = 0;
3408     }
3409   else if (strstr(ad_distinguishedName, ou_neither))
3410     {
3411       strcpy(before_group_ou, group_ou_neither);
3412       before_group_membership[0] = 'N';
3413       before_security_flag = 0;
3414     }
3415   else
3416     return(AD_NO_OU_FOUND);
3417   rc = group_rename(ldap_handle, dn_path, before_name, before_group_membership, 
3418                     before_group_ou, before_security_flag, before_desc,
3419                     group_name, group_membership, group_ou, group_security_flag,
3420                     before_desc, MoiraId, filter);
3421   return(rc);
3422 }
3423
3424 void change_to_lower_case(char *ptr)
3425 {
3426   int i;
3427
3428   for (i = 0; i < (int)strlen(ptr); i++)
3429     {
3430       ptr[i] = tolower(ptr[i]);
3431     }
3432 }
3433
3434 int ad_get_group(LDAP *ldap_handle, char *dn_path, 
3435                  char *group_name, char *group_membership, 
3436                  char *MoiraId, char *attribute,
3437                  LK_ENTRY **linklist_base, int *linklist_count,
3438                  char *rFilter)
3439 {
3440   LK_ENTRY  *pPtr;
3441   char  filter[128];
3442   char  *attr_array[3];
3443   int   rc;
3444
3445   (*linklist_base) = NULL;
3446   (*linklist_count) = 0;
3447   if (strlen(rFilter) != 0)
3448     {
3449       strcpy(filter, rFilter);
3450       attr_array[0] = attribute;
3451       attr_array[1] = NULL;
3452       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3453                                linklist_base, linklist_count)) != 0)
3454         {
3455           com_err(whoami, 0, "LDAP server unable to get list info with MoiraId = %s: %s",
3456                   MoiraId, ldap_err2string(rc));
3457          return(rc);
3458        }
3459     if ((*linklist_count) == 1)
3460       {
3461         strcpy(rFilter, filter);
3462         return(0);
3463       }
3464     }
3465
3466   linklist_free((*linklist_base));
3467   (*linklist_base) = NULL;
3468   (*linklist_count) = 0;
3469   if (strlen(MoiraId) != 0)
3470     {
3471       sprintf(filter, "(&(objectClass=group)(mitMoiraId=%s))", MoiraId);
3472       attr_array[0] = attribute;
3473       attr_array[1] = NULL;
3474       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3475                                linklist_base, linklist_count)) != 0)
3476         {
3477           com_err(whoami, 0, "LDAP server unable to get list info with MoiraId = %s: %s",
3478                   MoiraId, ldap_err2string(rc));
3479          return(rc);
3480        }
3481     }
3482   if ((*linklist_count) > 1)
3483     {
3484       com_err(whoami, 0, "multiple groups with mitMoiraId = %s", MoiraId);
3485       pPtr = (*linklist_base);
3486       while (pPtr)
3487         {
3488           com_err(whoami, 0, "groups %s has mitMoiraId = %s", pPtr->value, MoiraId);
3489           pPtr = pPtr->next;
3490         }
3491       linklist_free((*linklist_base));
3492       (*linklist_base) = NULL;
3493       (*linklist_count) = 0;
3494     }
3495   if ((*linklist_count) == 1)
3496     {
3497       strcpy(rFilter, filter);
3498       return(0);
3499     }
3500
3501   linklist_free((*linklist_base));
3502   (*linklist_base) = NULL;
3503   (*linklist_count) = 0;
3504   sprintf(filter, "(sAMAccountName=%s_group)", group_name);
3505   attr_array[0] = attribute;
3506   attr_array[1] = NULL;
3507   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3508                            linklist_base, linklist_count)) != 0)
3509     {
3510       com_err(whoami, 0, "LDAP server unable to get list info with MoiraId = %s: %s",
3511               MoiraId, ldap_err2string(rc));
3512       return(rc);
3513     }
3514   if ((*linklist_count) == 1)
3515     {
3516       strcpy(rFilter, filter);
3517       return(0);
3518     }
3519
3520   return(0);
3521 }
3522
3523 int check_user(LDAP *ldap_handle, char *dn_path, char *UserName, char *MoiraId)
3524 {
3525   char filter[128];
3526   char *attr_array[3];
3527   char SamAccountName[64];
3528   int  group_count;
3529   int  rc;
3530   LK_ENTRY  *group_base;
3531   LK_ENTRY  *gPtr;
3532
3533   group_count = 0;
3534   group_base = NULL;
3535
3536   if (strlen(MoiraId) != 0)
3537     {
3538       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
3539       attr_array[0] = "sAMAccountName";
3540       attr_array[1] = NULL;
3541       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3542                                &group_base, &group_count)) != 0)
3543         {
3544           com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
3545                   UserName, ldap_err2string(rc));
3546           return(rc);
3547         }
3548       if (group_count > 1)
3549         {
3550           com_err(whoami, 0, "multiple users exist with MoiraId = %s",
3551                   MoiraId);
3552           gPtr = group_base;
3553           while (gPtr)
3554             {
3555               com_err(whoami, 0, "user %s exist with MoiraId = %s",
3556                       gPtr->value, MoiraId);
3557               gPtr = gPtr->next;
3558             }
3559         }
3560     }
3561   if (group_count != 1)
3562     {
3563       linklist_free(group_base);
3564       group_count = 0;
3565       group_base = NULL;
3566       sprintf(filter, "(sAMAccountName=%s)", UserName);
3567       attr_array[0] = "sAMAccountName";
3568       attr_array[1] = NULL;
3569       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3570                                &group_base, &group_count)) != 0)
3571         {
3572           com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
3573                   UserName, ldap_err2string(rc));
3574           return(rc);
3575         }
3576     }
3577
3578   if (group_count != 1)
3579     {
3580       linklist_free(group_base);
3581       return(AD_NO_USER_FOUND);
3582     }
3583   strcpy(SamAccountName, group_base->value);
3584   linklist_free(group_base);
3585   group_count = 0;
3586   rc = 0;
3587   if (strcmp(SamAccountName, UserName))
3588     {
3589       rc = user_rename(ldap_handle, dn_path, SamAccountName, 
3590                        UserName);
3591     }
3592   return(0);
3593 }
This page took 0.317299 seconds and 5 git commands to generate.