]> andersk Git - moira.git/blob - incremental/winad/winad.c
4d886486d795e5e086606e67241a45379a00a79c
[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           sscanf(hp[i], "%*s %s", cPath);
2363           if (strlen(cPath) && strnicmp(cPath, AFS, strlen(AFS)) == 0)
2364             {
2365               sscanf(hp[i], "%*s %*s %*s %*s %s", cWeight);
2366               if (atoi(cWeight) < last_weight)
2367                 {
2368                   strcpy(path, cPath);
2369                   last_weight = (int)atoi(cWeight);
2370                 } 
2371             }
2372           ++i;
2373         }
2374       if (strlen(path))
2375         {
2376           if (!strnicmp(path, AFS, strlen(AFS)))
2377             {
2378               AfsToWinAfs(path, winPath);
2379               homedir_v[0] = winPath;
2380               ADD_ATTR("homeDirectory", homedir_v, LDAP_MOD_REPLACE);
2381               strcpy(winProfile, winPath);
2382               strcat(winProfile, "\\.winprofile");
2383               winProfile_v[0] = winProfile;
2384               ADD_ATTR("profilePath", winProfile_v, LDAP_MOD_REPLACE);
2385               drives_v[0] = "H:";
2386               ADD_ATTR("homeDrive", drives_v, LDAP_MOD_REPLACE);
2387             }
2388         }
2389     }
2390   uid_v[0] = Uid;
2391   if (strlen(Uid) == 0)
2392     uid_v[0] = NULL;
2393   ADD_ATTR("uid", uid_v, LDAP_MOD_REPLACE);
2394   ADD_ATTR("uidNumber", uid_v, LDAP_MOD_REPLACE);
2395   mitid_v[0] = MitId;
2396   if (strlen(MitId) == 0)
2397     mitid_v[0] = NULL;
2398   ADD_ATTR("employeeID", mitid_v, LDAP_MOD_REPLACE);
2399   mitMoiraId_v[0] = MoiraId;
2400   if (strlen(MoiraId) == 0)
2401     mitMoiraId_v[0] = NULL;
2402   ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
2403   if ((State != US_NO_PASSWD) && (State != US_REGISTERED))
2404     userAccountControl |= UF_ACCOUNTDISABLE;
2405   sprintf(userAccountControlStr, "%ld", userAccountControl);
2406   userAccountControl_v[0] = userAccountControlStr;
2407   ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_REPLACE);
2408   mods[n] = NULL;
2409   if ((rc = ldap_modify_s(ldap_handle, distinguished_name, mods)) != LDAP_SUCCESS)
2410     {
2411       com_err(whoami, 0, "Couldn't modify user data for %s : %s",
2412               user_name, ldap_err2string(rc));
2413     }
2414   for (i = 0; i < n; i++)
2415     free(mods[i]);
2416
2417   if (hp != NULL)
2418     {
2419       i = 0;
2420       while (hp[i])
2421         {
2422           free(hp[i]);
2423           i++;
2424         }
2425     }
2426
2427   return(rc);
2428 }
2429
2430 int user_rename(LDAP *ldap_handle, char *dn_path, char *before_user_name, 
2431                 char *user_name)
2432 {
2433   LDAPMod *mods[20];
2434   char new_dn[256];
2435   char old_dn[256];
2436   char upn[256];
2437   char temp[128];
2438   char *userPrincipalName_v[] = {NULL, NULL};
2439   char *altSecurityIdentities_v[] = {NULL, NULL};
2440   char *name_v[] = {NULL, NULL};
2441   char *samAccountName_v[] = {NULL, NULL};
2442   int  n;
2443   int  rc;
2444   int  i;
2445
2446   if (!check_string(before_user_name))
2447     {
2448       com_err(whoami, 0, "invalid LDAP user name %s", before_user_name);
2449       return(AD_INVALID_NAME);
2450     }
2451   if (!check_string(user_name))
2452     {
2453       com_err(whoami, 0, "invalid LDAP user name %s", user_name);
2454       return(AD_INVALID_NAME);
2455     }
2456
2457   strcpy(user_name, user_name);
2458   sprintf(old_dn, "cn=%s,%s,%s", before_user_name, user_ou, dn_path);
2459   sprintf(new_dn, "cn=%s", user_name);
2460   if ((rc = ldap_rename_s(ldap_handle, old_dn, new_dn, NULL, TRUE, 
2461                            NULL, NULL)) != LDAP_SUCCESS)
2462     {
2463       com_err(whoami, 0, "Couldn't rename user from %s to %s : %s",
2464               before_user_name, user_name, ldap_err2string(rc));
2465       return(rc);
2466     }
2467
2468   name_v[0] = user_name;
2469   sprintf(upn, "%s@%s", user_name, ldap_domain);
2470   userPrincipalName_v[0] = upn;
2471   sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
2472   altSecurityIdentities_v[0] = temp;
2473   samAccountName_v[0] = user_name;
2474
2475   n = 0;
2476   ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_REPLACE);
2477   ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_REPLACE);
2478   ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
2479   ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_REPLACE);
2480   mods[n] = NULL;
2481   sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, dn_path);
2482   if ((rc = ldap_modify_s(ldap_handle, new_dn, mods)) != LDAP_SUCCESS)
2483     {
2484       com_err(whoami, 0, "After renaming, couldn't modify user data for %s : %s",
2485               user_name, ldap_err2string(rc));
2486     }
2487   for (i = 0; i < n; i++)
2488     free(mods[i]);
2489   return(rc);
2490 }
2491
2492 int filesys_process(LDAP *ldap_handle, char *dn_path, char *fs_name, 
2493                     char *fs_type, char *fs_pack, int operation)
2494 {
2495   char  distinguished_name[256];
2496   char  winPath[256];
2497   char  winProfile[256];
2498   char  filter[128];
2499   char  *attr_array[3];
2500   char  *homedir_v[] = {NULL, NULL};
2501   char  *winProfile_v[] = {NULL, NULL};
2502   char  *drives_v[] = {NULL, NULL};
2503   int   group_count;
2504   int   n;
2505   int   rc;
2506   int   i;
2507   LDAPMod   *mods[20];
2508   LK_ENTRY  *group_base;
2509
2510   if (!check_string(fs_name))
2511     {
2512       com_err(whoami, 0, "invalid filesys name %s", fs_name);
2513       return(AD_INVALID_NAME);
2514     }
2515
2516   if (strcmp(fs_type, "AFS"))
2517     {
2518       com_err(whoami, 0, "invalid filesys type %s", fs_type);
2519       return(AD_INVALID_FILESYS);
2520     }
2521
2522   group_count = 0;
2523   group_base = NULL;
2524   sprintf(filter, "(sAMAccountName=%s)", fs_name);
2525   attr_array[0] = "cn";
2526   attr_array[1] = NULL;
2527   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
2528                            &group_base, &group_count)) != 0)
2529     {
2530       com_err(whoami, 0, "LDAP server couldn't process filesys %s : %s",
2531               fs_name, ldap_err2string(rc));
2532       return(rc);
2533     }
2534
2535   if (group_count != 1)
2536     {
2537       linklist_free(group_base);
2538       com_err(whoami, 0, "LDAP server unable to find user %s in AD",
2539               fs_name);
2540       return(LDAP_NO_SUCH_OBJECT);
2541     }
2542   strcpy(distinguished_name, group_base->dn);
2543   linklist_free(group_base);
2544   group_count = 0;
2545
2546   n = 0;
2547   if (operation == LDAP_MOD_ADD)
2548     {
2549       memset(winPath, 0, sizeof(winPath));
2550       AfsToWinAfs(fs_pack, winPath);
2551       homedir_v[0] = winPath;
2552       drives_v[0] = "H:";
2553       memset(winProfile, 0, sizeof(winProfile));
2554       strcpy(winProfile, winPath);
2555       strcat(winProfile, "\\.winprofile");
2556       winProfile_v[0] = winProfile;
2557     }
2558   else
2559     {
2560       homedir_v[0] = NULL;
2561       drives_v[0] = NULL;
2562       winProfile_v[0] = NULL;
2563     }
2564   ADD_ATTR("profilePath", winProfile_v, operation);
2565   ADD_ATTR("homeDrive", drives_v, operation);
2566   ADD_ATTR("homeDirectory", homedir_v, operation);
2567   mods[n] = NULL;
2568
2569   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
2570   if (rc != LDAP_SUCCESS)
2571     {
2572       com_err(whoami, 0, "Couldn't modify user data for filesys %s : %s",
2573               fs_name, ldap_err2string(rc));
2574     }
2575   for (i = 0; i < n; i++)
2576     free(mods[i]);
2577
2578   return(rc);
2579 }
2580
2581 int user_create(int ac, char **av, void *ptr)
2582 {
2583   LK_ENTRY  *group_base;
2584   LDAPMod *mods[20];
2585   char new_dn[256];
2586   char user_name[256];
2587   char sam_name[256];
2588   char upn[256];
2589   char *cn_v[] = {NULL, NULL};
2590   char *objectClass_v[] = {"top", "person", 
2591                            "organizationalPerson", 
2592                            "user", NULL};
2593
2594   char *samAccountName_v[] = {NULL, NULL};
2595   char *altSecurityIdentities_v[] = {NULL, NULL};
2596   char *mitMoiraId_v[] = {NULL, NULL};
2597   char *name_v[] = {NULL, NULL};
2598   char *desc_v[] = {NULL, NULL};
2599   char *userPrincipalName_v[] = {NULL, NULL};
2600   char *userAccountControl_v[] = {NULL, NULL};
2601   char *uid_v[] = {NULL, NULL};
2602   char *mitid_v[] = {NULL, NULL};
2603   char userAccountControlStr[80];
2604   char temp[128];
2605   u_int userAccountControl = UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD | UF_PASSWD_CANT_CHANGE;
2606   int  n;
2607   int  rc;
2608   int  i;
2609   int  group_count;
2610   char filter[128];
2611   char *attr_array[3];
2612   char **call_args;
2613
2614   call_args = ptr;
2615
2616   if (!check_string(av[U_NAME]))
2617     {
2618       callback_rc = AD_INVALID_NAME;
2619       com_err(whoami, 0, "invalid LDAP user name %s", av[U_NAME]);
2620       return(AD_INVALID_NAME);
2621     }
2622
2623   strcpy(user_name, av[U_NAME]);
2624   sprintf(upn, "%s@%s", user_name, ldap_domain);
2625   sprintf(sam_name, "%s", av[U_NAME]);
2626   samAccountName_v[0] = sam_name;
2627   if ((atoi(av[U_STATE]) != US_NO_PASSWD) && (atoi(av[U_STATE]) != US_REGISTERED))
2628     userAccountControl |= UF_ACCOUNTDISABLE;
2629   sprintf(userAccountControlStr, "%ld", userAccountControl);
2630   userAccountControl_v[0] = userAccountControlStr;
2631   userPrincipalName_v[0] = upn;
2632
2633   cn_v[0] = user_name;
2634   name_v[0] = user_name;
2635   desc_v[0] = "Auto account created by Moira";
2636   sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
2637   altSecurityIdentities_v[0] = temp;    
2638   sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, call_args[1]);
2639
2640   n = 0;
2641   ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
2642   ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2643   ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
2644   ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_ADD);
2645   ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_ADD);
2646   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2647   ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2648   ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2649   if (strlen(call_args[2]) != 0)
2650     {
2651       mitMoiraId_v[0] = call_args[2];
2652       ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_ADD);
2653     }
2654   ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_ADD);
2655   if (strlen(av[U_UID]) != 0)
2656     {
2657       uid_v[0] = av[U_UID];
2658       ADD_ATTR("uid", uid_v, LDAP_MOD_ADD);
2659       ADD_ATTR("uidNumber", uid_v, LDAP_MOD_ADD);
2660     }
2661   if (strlen(av[U_MITID]) != 0)
2662       mitid_v[0] = av[U_MITID];
2663   else
2664       mitid_v[0] = "none";
2665   ADD_ATTR("employeeID", mitid_v, LDAP_MOD_ADD);
2666   mods[n] = NULL;
2667
2668   rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
2669   for (i = 0; i < n; i++)
2670     free(mods[i]);
2671   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2672     {
2673       com_err(whoami, 0, "could not create user %s : %s",
2674               user_name, ldap_err2string(rc));
2675       callback_rc = rc;
2676       return(rc);
2677     }
2678   if (rc == LDAP_SUCCESS)
2679     {
2680       if ((rc = set_password(sam_name, "", ldap_domain)) != 0)
2681         {
2682           com_err(whoami, 0, "Couldn't set password for user %s : %ld",
2683                   user_name, rc);
2684         }
2685     }
2686   sprintf(filter, "(sAMAccountName=%s)", av[U_NAME]);
2687   if (strlen(call_args[2]) != 0)
2688     sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", call_args[2]);
2689   attr_array[0] = "objectSid";
2690   attr_array[1] = NULL;
2691   group_count = 0;
2692   group_base = NULL;
2693   if ((rc = linklist_build((LDAP *)call_args[0], call_args[1], filter, attr_array, 
2694                            &group_base, &group_count)) == LDAP_SUCCESS)
2695     {
2696       if (group_count != 1)
2697         {
2698           if (strlen(call_args[2]) != 0)
2699             {
2700               linklist_free(group_base);
2701               group_count = 0;
2702               group_base = NULL;
2703               sprintf(filter, "(sAMAccountName=%s)", av[U_NAME]);
2704               rc = linklist_build((LDAP *)call_args[0], call_args[1], filter, 
2705                                   attr_array, &group_base, &group_count);
2706             }
2707         }
2708       if (group_count == 1)
2709         {
2710           (*sid_ptr) = group_base;
2711           (*sid_ptr)->member = strdup(av[U_NAME]);
2712           (*sid_ptr)->type = (char *)GROUPS;
2713           sid_ptr = &(*sid_ptr)->next;
2714         }
2715       else
2716         {
2717           if (group_base != NULL)
2718             linklist_free(group_base);
2719         }
2720     }
2721   else
2722     {
2723       if (group_base != NULL)
2724         linklist_free(group_base);
2725     }
2726   return(0);
2727 }
2728
2729 int user_change_status(LDAP *ldap_handle, char *dn_path, 
2730                        char *user_name, char *MoiraId,
2731                        int operation)
2732 {
2733   char      filter[128];
2734   char      *attr_array[3];
2735   char      temp[256];
2736   char      distinguished_name[1024];
2737   char      **modvalues;
2738   char      *mitMoiraId_v[] = {NULL, NULL};
2739   LDAPMod   *mods[20];
2740   LK_ENTRY  *group_base;
2741   int       group_count;
2742   int       rc;
2743   int       i;
2744   int       n;
2745   ULONG     ulongValue;
2746
2747   if (!check_string(user_name))
2748     {
2749       com_err(whoami, 0, "invalid LDAP user name %s", user_name);
2750       return(AD_INVALID_NAME);
2751     }
2752
2753   group_count = 0;
2754   group_base = NULL;
2755
2756   if (strlen(MoiraId) != 0)
2757     {
2758       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
2759       attr_array[0] = "UserAccountControl";
2760       attr_array[1] = NULL;
2761       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
2762                                &group_base, &group_count)) != 0)
2763         {
2764           com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
2765                   user_name, ldap_err2string(rc));
2766           return(rc);
2767         }
2768     }
2769   if (group_count != 1)
2770     {
2771       linklist_free(group_base);
2772       group_count = 0;
2773       group_base = NULL;
2774       sprintf(filter, "(sAMAccountName=%s)", user_name);
2775       attr_array[0] = "UserAccountControl";
2776       attr_array[1] = NULL;
2777       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
2778                                &group_base, &group_count)) != 0)
2779         {
2780           com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
2781                   user_name, ldap_err2string(rc));
2782           return(rc);
2783         }
2784     }
2785
2786   if (group_count != 1)
2787     {
2788       linklist_free(group_base);
2789       com_err(whoami, 0, "LDAP server unable to find user %s in AD",
2790               user_name);
2791       return(LDAP_NO_SUCH_OBJECT);
2792     }
2793
2794   strcpy(distinguished_name, group_base->dn);
2795   ulongValue = atoi((*group_base).value);
2796   if (operation == MEMBER_DEACTIVATE)
2797     ulongValue |= UF_ACCOUNTDISABLE;
2798   else    
2799     ulongValue &= ~UF_ACCOUNTDISABLE;
2800   sprintf(temp, "%ld", ulongValue);
2801   if ((rc = construct_newvalues(group_base, group_count, (*group_base).value, 
2802                                 temp, &modvalues, REPLACE)) == 1)
2803     goto cleanup;
2804   linklist_free(group_base);
2805   group_base = NULL;
2806   group_count = 0;
2807   n = 0;
2808   ADD_ATTR("UserAccountControl", modvalues, LDAP_MOD_REPLACE);
2809   if (strlen(MoiraId) != 0)
2810     {
2811     mitMoiraId_v[0] = MoiraId;
2812     ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
2813     }
2814   mods[n] = NULL;
2815   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
2816   for (i = 0; i < n; i++)
2817     free(mods[i]);
2818   free_values(modvalues);
2819   if (rc != LDAP_SUCCESS)
2820     {
2821       com_err(whoami, 0, "LDAP server could not change status of user %s : %s",
2822               user_name, ldap_err2string(rc));
2823     }
2824 cleanup:
2825   return(rc);
2826 }
2827
2828 int user_delete(LDAP *ldap_handle, char *dn_path, 
2829                 char *u_name, char *MoiraId)
2830 {
2831   char      filter[128];
2832   char      *attr_array[3];
2833   char      distinguished_name[1024];
2834   char      user_name[512];
2835   LK_ENTRY  *group_base;
2836   int       group_count;
2837   int       rc;
2838
2839   if (!check_string(u_name))
2840     return(AD_INVALID_NAME);
2841
2842   strcpy(user_name, u_name);
2843   group_count = 0;
2844   group_base = NULL;
2845
2846   if (strlen(MoiraId) != 0)
2847     {
2848       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
2849       attr_array[0] = "name";
2850       attr_array[1] = NULL;
2851       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
2852                                &group_base, &group_count)) != 0)
2853         {
2854           com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
2855                   user_name, ldap_err2string(rc));
2856           goto cleanup;
2857         }
2858     }
2859   if (group_count != 1)
2860     {
2861       linklist_free(group_base);
2862       group_count = 0;
2863       group_base = NULL;
2864       sprintf(filter, "(sAMAccountName=%s)", user_name);
2865       attr_array[0] = "name";
2866       attr_array[1] = NULL;
2867       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
2868                                &group_base, &group_count)) != 0)
2869         {
2870           com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
2871                   user_name, ldap_err2string(rc));
2872           goto cleanup;
2873         }
2874     }
2875
2876   if (group_count != 1)
2877     {
2878       com_err(whoami, 0, "LDAP server unable to find user %s in AD",
2879               user_name);
2880       goto cleanup;
2881     }
2882
2883   strcpy(distinguished_name, group_base->dn);
2884   if (rc = ldap_delete_s(ldap_handle, distinguished_name))
2885     {
2886       com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
2887               user_name, ldap_err2string(rc));
2888     }
2889
2890 cleanup:
2891   linklist_free(group_base);
2892   return(0);
2893 }
2894
2895 void linklist_free(LK_ENTRY *linklist_base)
2896 {
2897   LK_ENTRY *linklist_previous;
2898
2899   while (linklist_base != NULL)
2900     {
2901       if (linklist_base->dn != NULL)
2902         free(linklist_base->dn);
2903       if (linklist_base->attribute != NULL)
2904         free(linklist_base->attribute);
2905       if (linklist_base->value != NULL)
2906         free(linklist_base->value);
2907       if (linklist_base->member != NULL)
2908         free(linklist_base->member);
2909       if (linklist_base->type != NULL)
2910         free(linklist_base->type);
2911       if (linklist_base->list != NULL)
2912         free(linklist_base->list);
2913       linklist_previous = linklist_base;
2914       linklist_base = linklist_previous->next;
2915       free(linklist_previous);
2916     }
2917 }
2918
2919 void free_values(char **modvalues)
2920 {
2921   int i;
2922
2923   i = 0;
2924   if (modvalues != NULL)
2925     {
2926     while (modvalues[i] != NULL)
2927       {
2928         free(modvalues[i]);
2929         modvalues[i] = NULL;
2930         ++i;
2931       }
2932     free(modvalues);
2933   }
2934 }
2935
2936 int sid_update(LDAP *ldap_handle, char *dn_path)
2937 {
2938   LK_ENTRY      *ptr;
2939   int           rc;
2940   unsigned char temp[126];
2941   char          *av[3];
2942
2943   ptr = sid_base;
2944
2945   while (ptr != NULL)
2946     {
2947       memset(temp, 0, sizeof(temp));
2948       convert_b_to_a(temp, ptr->value, ptr->length);
2949       if (!ptr->member)
2950         continue;
2951       av[0] = ptr->member;
2952       av[1] = temp;
2953       if (ptr->type == (char *)GROUPS)
2954         {
2955           ptr->type = NULL;
2956           rc = mr_query("add_list_sid_by_name", 2, av, NULL, NULL);
2957         }
2958       else if (ptr->type == (char *)USERS)
2959         {
2960           ptr->type = NULL;
2961           rc = mr_query("add_user_sid_by_login", 2, av, NULL, NULL);
2962         }
2963       ptr = ptr->next;
2964     }
2965   return(0);
2966 }
2967
2968 void convert_b_to_a(char *string, UCHAR *binary, int length)
2969 {
2970   int   i;
2971   int   j;
2972   UCHAR tmp;
2973
2974   j = 0;
2975   for (i = 0; i < length; i++)
2976     {
2977       tmp = binary[i];
2978       string[j] = tmp;
2979       string[j] >>= 4;
2980       string[j] &= 0x0f;
2981       string[j] += 0x30;
2982       if (string[j] > '9')
2983         string[j] += 0x27;
2984       ++j;
2985       string[j] = tmp & 0x0f;
2986       string[j] += 0x30;
2987       if (string[j] > '9')
2988         string[j] += 0x27;
2989       j++;
2990     }
2991   string[j] = 0;
2992 }
2993
2994 static int illegalchars[] = {
2995   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
2996   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
2997   1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, /* SPACE - / */
2998   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 0 - ? */
2999   0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
3000   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* P - _ */
3001   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
3002   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
3003   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3004   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3005   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3006   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3007   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3008   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
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 };
3012
3013 int check_string(char *s)
3014 {
3015   char  character;
3016
3017   for (; *s; s++)
3018     {
3019       character = *s;
3020       if (isupper(character))
3021         character = tolower(character);
3022       if (illegalchars[(unsigned) character])
3023         return 0;
3024     }
3025   return 1;
3026 }
3027
3028 int mr_connect_cl(char *server, char *client, int version, int auth)
3029 {
3030   int   status;
3031   char  *motd;
3032   char  temp[128];
3033
3034   status = mr_connect(server);
3035   if (status)
3036     {
3037       com_err(whoami, status, "while connecting to Moira");
3038       return status;
3039     }
3040
3041   status = mr_motd(&motd);
3042   if (status)
3043     {
3044       mr_disconnect();
3045       com_err(whoami, status, "while checking server status");
3046       return status;
3047     }
3048   if (motd)
3049     {
3050       sprintf(temp, "The Moira server is currently unavailable: %s", motd);
3051       com_err(whoami, status, temp);
3052       mr_disconnect();
3053       return status;
3054     }
3055
3056   status = mr_version(version);
3057   if (status)
3058     {
3059       if (status == MR_UNKNOWN_PROC)
3060         {
3061           if (version > 2)
3062             status = MR_VERSION_HIGH;
3063           else
3064             status = MR_SUCCESS;
3065         }
3066
3067       if (status == MR_VERSION_HIGH)
3068         {
3069           com_err(whoami, 0, "Warning: This client is running newer code than the server.");
3070                   com_err(whoami, 0, "Some operations may not work.");
3071         }
3072       else if (status && status != MR_VERSION_LOW)
3073         {
3074           com_err(whoami, status, "while setting query version number.");
3075           mr_disconnect();
3076           return status;
3077         }
3078     }
3079
3080   if (auth)
3081     {
3082       status = mr_auth(client);
3083       if (status)
3084         {
3085           com_err(whoami, status, "while authenticating to Moira.");
3086           mr_disconnect();
3087           return status;
3088         }
3089     }
3090
3091   return MR_SUCCESS;
3092 }
3093
3094 void AfsToWinAfs(char* path, char* winPath)
3095 {
3096     char* pathPtr;
3097     char* winPathPtr;
3098     strcpy(winPath, WINAFS);
3099     pathPtr = path + strlen(AFS);
3100     winPathPtr = winPath + strlen(WINAFS);
3101
3102     while (*pathPtr)
3103     {
3104         if (*pathPtr == '/')
3105           *winPathPtr = '\\';
3106         else
3107           *winPathPtr = *pathPtr;
3108
3109         pathPtr++;
3110         winPathPtr++;
3111     }
3112 }
3113
3114 int make_new_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
3115                    char *group_name, char *group_ou, char *group_membership, 
3116                    int group_security_flag, int updateGroup)
3117 {
3118   char  *av[3];
3119   char  *call_args[7];
3120   int   rc;
3121
3122   av[0] = group_name;
3123   call_args[0] = (char *)ldap_handle;
3124   call_args[1] = dn_path;
3125   call_args[2] = group_name;
3126   call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
3127   call_args[4] = (char *)updateGroup;
3128   call_args[5] = MoiraId;
3129   call_args[6] = NULL;
3130   sid_base = NULL;
3131   sid_ptr = &sid_base;
3132   callback_rc = 0;
3133   if (rc = mr_query("get_list_info", 1, av, group_create, call_args))
3134     {
3135       moira_disconnect();
3136       com_err(whoami, 0, "Couldn't create list %s : %s", group_name, error_message(rc));
3137       return(rc);
3138     }
3139   if (callback_rc)
3140     {
3141       moira_disconnect();
3142       com_err(whoami, 0, "Couldn't create list %s", group_name);
3143       return(callback_rc);
3144     }
3145
3146   if (sid_base != NULL)
3147     {
3148       sid_update(ldap_handle, dn_path);
3149       linklist_free(sid_base);
3150       sid_base = NULL;
3151     }
3152   return(0);
3153 }
3154
3155 int populate_group(LDAP *ldap_handle, char *dn_path, char *group_name, 
3156                    char *group_ou, char *group_membership, 
3157                    int group_security_flag, char *MoiraId)
3158 {
3159   char      *av[3];
3160   char      *call_args[7];
3161   char      *pUserOu;
3162   LK_ENTRY  *ptr;
3163   int       rc;
3164
3165   com_err(whoami, 0, "Populating group %s", group_name);
3166   av[0] = group_name;
3167   call_args[0] = (char *)ldap_handle;
3168   call_args[1] = dn_path;
3169   call_args[2] = group_name;
3170   call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
3171   call_args[4] = NULL;
3172   member_base = NULL;
3173   if (rc = mr_query("get_end_members_of_list", 1, av,
3174                     member_list_build, call_args))
3175     {
3176       com_err(whoami, 0, "Couldn't populate list %s : %s", 
3177               group_name, error_message(rc));
3178       return(3);
3179     }
3180   if (member_base != NULL)
3181     {
3182       ptr = member_base;
3183       while (ptr != NULL)
3184         {
3185           if (!strcasecmp(ptr->type, "LIST"))
3186             {
3187               ptr = ptr->next;
3188               continue;
3189             }
3190           pUserOu = user_ou;
3191           if (!strcasecmp(ptr->type, "STRING"))
3192             {
3193               if (contact_create(ldap_handle, dn_path, ptr->member, contact_ou))
3194                 return(3);
3195               pUserOu = contact_ou;
3196             }
3197           else if (!strcasecmp(ptr->type, "KERBEROS"))
3198             {
3199               if (contact_create(ldap_handle, dn_path, ptr->member, kerberos_ou))
3200                 return(3);
3201               pUserOu = kerberos_ou;
3202             }
3203           rc = member_add(ldap_handle, dn_path, group_name,
3204                           group_ou, group_membership, ptr->member, 
3205                           pUserOu, MoiraId);
3206           ptr = ptr->next;
3207         }
3208       linklist_free(member_base);
3209       member_base = NULL;
3210     }
3211   return(0);
3212 }
3213
3214 int process_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
3215                   char *group_name, char *group_ou, char *group_membership, 
3216                   int group_security_flag, int type)
3217 {
3218   char      before_desc[512];
3219   char      before_name[256];
3220   char      before_group_ou[256];
3221   char      before_group_membership[2];
3222   char      distinguishedName[256];
3223   char      ad_distinguishedName[256];
3224   char      filter[128];
3225   char      *attr_array[3];
3226   int       before_security_flag;
3227   int       group_count;
3228   int       rc;
3229   LK_ENTRY  *group_base;
3230   LK_ENTRY  *ptr;
3231   char      ou_both[512];
3232   char      ou_security[512];
3233   char      ou_distribution[512];
3234   char      ou_neither[512];
3235
3236   memset(ad_distinguishedName, '\0', sizeof(ad_distinguishedName));
3237   sprintf(distinguishedName, "CN=%s,%s,%s", group_name, group_ou, dn_path);
3238
3239
3240   memset(filter, '\0', sizeof(filter));
3241   group_base = NULL;
3242   group_count = 0;
3243   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
3244                         "*", MoiraId, 
3245                         "distinguishedName", &group_base, 
3246                         &group_count, filter))
3247     return(rc);
3248
3249   if (type == CHECK_GROUPS)
3250     {
3251       if (group_count == 1)
3252         {
3253           if (!strcasecmp(group_base->value, distinguishedName))
3254             {
3255               linklist_free(group_base);
3256               return(0);
3257             }
3258         }
3259       linklist_free(group_base);
3260       if (group_count == 0)
3261         return(AD_NO_GROUPS_FOUND);
3262       if (group_count == 1)
3263         return(AD_WRONG_GROUP_DN_FOUND);
3264       return(AD_MULTIPLE_GROUPS_FOUND);
3265     }
3266   if (group_count == 0)
3267     {
3268       return(AD_NO_GROUPS_FOUND);
3269     }
3270   if (group_count > 1)
3271     {
3272       ptr = group_base;
3273       while (ptr != NULL)
3274         {
3275           if (!strcasecmp(distinguishedName, ptr->value))
3276             break;
3277           ptr = ptr->next;
3278         }
3279       if (ptr == NULL)
3280         {
3281           com_err(whoami, 0, "%d groups with moira id = %s", group_count, MoiraId);
3282           ptr = group_base;
3283           while (ptr != NULL)
3284             {
3285               com_err(whoami, 0, "%s with moira id = %s", ptr->value, MoiraId);
3286               ptr = ptr->next;
3287             }
3288           linklist_free(group_base);
3289           return(AD_MULTIPLE_GROUPS_FOUND);
3290         } 
3291       ptr = group_base;
3292       while (ptr != NULL)
3293         {
3294           if (strcasecmp(distinguishedName, ptr->value))
3295             rc = ldap_delete_s(ldap_handle, ptr->value);
3296           ptr = ptr->next;
3297         }
3298       linklist_free(group_base);
3299       memset(filter, '\0', sizeof(filter));
3300       group_base = NULL;
3301       group_count = 0;
3302       if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
3303                             "*", MoiraId, 
3304                             "distinguishedName", &group_base, 
3305                             &group_count, filter))
3306         return(rc);
3307       if (group_count == 0)
3308         return(AD_NO_GROUPS_FOUND);
3309       if (group_count > 1)
3310         return(AD_MULTIPLE_GROUPS_FOUND);
3311     }
3312
3313   strcpy(ad_distinguishedName, group_base->value);
3314   linklist_free(group_base);
3315   group_base = NULL;
3316   group_count = 0;
3317
3318   attr_array[0] = "sAMAccountName";
3319   attr_array[1] = NULL;
3320   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3321                            &group_base, &group_count)) != 0)
3322     {
3323       com_err(whoami, 0, "LDAP server unable to get list info with MoiraId = %s: %s",
3324                MoiraId, ldap_err2string(rc));
3325       return(rc);
3326     }
3327   sprintf(filter, "(sAMAccountName=%s)", group_base->value);
3328
3329   if (!strcasecmp(ad_distinguishedName, distinguishedName))
3330     {
3331       linklist_free(group_base);
3332       group_base = NULL;
3333       group_count = 0;
3334       return(0);
3335     }
3336   linklist_free(group_base);
3337   group_base = NULL;
3338   group_count = 0;
3339   memset(ou_both, '\0', sizeof(ou_both));
3340   memset(ou_security, '\0', sizeof(ou_security));
3341   memset(ou_distribution, '\0', sizeof(ou_distribution));
3342   memset(ou_neither, '\0', sizeof(ou_neither));
3343   memset(before_name, '\0', sizeof(before_name));
3344   memset(before_desc, '\0', sizeof(before_desc));
3345   memset(before_group_membership, '\0', sizeof(before_group_membership));
3346   attr_array[0] = "name";
3347   attr_array[1] = NULL;
3348   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3349                            &group_base, &group_count)) != 0)
3350     {
3351       com_err(whoami, 0, "LDAP server unable to get list name with MoiraId = %s: %s",
3352               MoiraId, ldap_err2string(rc));
3353       return(rc);
3354     }
3355   strcpy(before_name, group_base->value);
3356   linklist_free(group_base);
3357   group_base = NULL;
3358   group_count = 0;
3359   attr_array[0] = "description";
3360   attr_array[1] = NULL;
3361   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3362                            &group_base, &group_count)) != 0)
3363     {
3364       com_err(whoami, 0, 
3365               "LDAP server unable to get list description with MoiraId = %s: %s",
3366               MoiraId, ldap_err2string(rc));
3367       return(rc);
3368     }
3369   if (group_count != 0)
3370     {
3371       strcpy(before_desc, group_base->value);
3372       linklist_free(group_base);
3373       group_base = NULL;
3374       group_count = 0;
3375     }
3376   change_to_lower_case(ad_distinguishedName);  
3377   strcpy(ou_both, group_ou_both);
3378   change_to_lower_case(ou_both);
3379   strcpy(ou_security, group_ou_security);
3380   change_to_lower_case(ou_security);
3381   strcpy(ou_distribution, group_ou_distribution);
3382   change_to_lower_case(ou_distribution);
3383   strcpy(ou_neither, group_ou_neither);
3384   change_to_lower_case(ou_neither);
3385   if (strstr(ad_distinguishedName, ou_both))
3386     {
3387       strcpy(before_group_ou, group_ou_both);
3388       before_group_membership[0] = 'B';
3389       before_security_flag = 1;
3390     }
3391   else if (strstr(ad_distinguishedName, ou_security))
3392     {
3393       strcpy(before_group_ou, group_ou_security);
3394       before_group_membership[0] = 'S';
3395       before_security_flag = 1;
3396     }
3397   else if (strstr(ad_distinguishedName, ou_distribution))
3398     {
3399       strcpy(before_group_ou, group_ou_distribution);
3400       before_group_membership[0] = 'D';
3401       before_security_flag = 0;
3402     }
3403   else if (strstr(ad_distinguishedName, ou_neither))
3404     {
3405       strcpy(before_group_ou, group_ou_neither);
3406       before_group_membership[0] = 'N';
3407       before_security_flag = 0;
3408     }
3409   else
3410     return(AD_NO_OU_FOUND);
3411   rc = group_rename(ldap_handle, dn_path, before_name, before_group_membership, 
3412                     before_group_ou, before_security_flag, before_desc,
3413                     group_name, group_membership, group_ou, group_security_flag,
3414                     before_desc, MoiraId, filter);
3415   return(rc);
3416 }
3417
3418 void change_to_lower_case(char *ptr)
3419 {
3420   int i;
3421
3422   for (i = 0; i < (int)strlen(ptr); i++)
3423     {
3424       ptr[i] = tolower(ptr[i]);
3425     }
3426 }
3427
3428 int ad_get_group(LDAP *ldap_handle, char *dn_path, 
3429                  char *group_name, char *group_membership, 
3430                  char *MoiraId, char *attribute,
3431                  LK_ENTRY **linklist_base, int *linklist_count,
3432                  char *rFilter)
3433 {
3434   LK_ENTRY  *pPtr;
3435   char  filter[128];
3436   char  *attr_array[3];
3437   int   rc;
3438
3439   (*linklist_base) = NULL;
3440   (*linklist_count) = 0;
3441   if (strlen(rFilter) != 0)
3442     {
3443       strcpy(filter, rFilter);
3444       attr_array[0] = attribute;
3445       attr_array[1] = NULL;
3446       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3447                                linklist_base, linklist_count)) != 0)
3448         {
3449           com_err(whoami, 0, "LDAP server unable to get list info with MoiraId = %s: %s",
3450                   MoiraId, ldap_err2string(rc));
3451          return(rc);
3452        }
3453     if ((*linklist_count) == 1)
3454       {
3455         strcpy(rFilter, filter);
3456         return(0);
3457       }
3458     }
3459
3460   linklist_free((*linklist_base));
3461   (*linklist_base) = NULL;
3462   (*linklist_count) = 0;
3463   if (strlen(MoiraId) != 0)
3464     {
3465       sprintf(filter, "(&(objectClass=group)(mitMoiraId=%s))", MoiraId);
3466       attr_array[0] = attribute;
3467       attr_array[1] = NULL;
3468       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3469                                linklist_base, linklist_count)) != 0)
3470         {
3471           com_err(whoami, 0, "LDAP server unable to get list info with MoiraId = %s: %s",
3472                   MoiraId, ldap_err2string(rc));
3473          return(rc);
3474        }
3475     }
3476   if ((*linklist_count) > 1)
3477     {
3478       com_err(whoami, 0, "multiple groups with mitMoiraId = %s", MoiraId);
3479       pPtr = (*linklist_base);
3480       while (pPtr)
3481         {
3482           com_err(whoami, 0, "groups %s has mitMoiraId = %s", pPtr->value, MoiraId);
3483           pPtr = pPtr->next;
3484         }
3485       linklist_free((*linklist_base));
3486       (*linklist_base) = NULL;
3487       (*linklist_count) = 0;
3488     }
3489   if ((*linklist_count) == 1)
3490     {
3491       strcpy(rFilter, filter);
3492       return(0);
3493     }
3494
3495   linklist_free((*linklist_base));
3496   (*linklist_base) = NULL;
3497   (*linklist_count) = 0;
3498   sprintf(filter, "(sAMAccountName=%s_group)", group_name);
3499   attr_array[0] = attribute;
3500   attr_array[1] = NULL;
3501   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3502                            linklist_base, linklist_count)) != 0)
3503     {
3504       com_err(whoami, 0, "LDAP server unable to get list info with MoiraId = %s: %s",
3505               MoiraId, ldap_err2string(rc));
3506       return(rc);
3507     }
3508   if ((*linklist_count) == 1)
3509     {
3510       strcpy(rFilter, filter);
3511       return(0);
3512     }
3513
3514   return(0);
3515 }
3516
3517 int check_user(LDAP *ldap_handle, char *dn_path, char *UserName, char *MoiraId)
3518 {
3519   char filter[128];
3520   char *attr_array[3];
3521   char SamAccountName[64];
3522   int  group_count;
3523   int  rc;
3524   LK_ENTRY  *group_base;
3525   LK_ENTRY  *gPtr;
3526
3527   group_count = 0;
3528   group_base = NULL;
3529
3530   if (strlen(MoiraId) != 0)
3531     {
3532       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
3533       attr_array[0] = "sAMAccountName";
3534       attr_array[1] = NULL;
3535       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3536                                &group_base, &group_count)) != 0)
3537         {
3538           com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
3539                   UserName, ldap_err2string(rc));
3540           return(rc);
3541         }
3542       if (group_count > 1)
3543         {
3544           com_err(whoami, 0, "multiple users exist with MoiraId = %s",
3545                   MoiraId);
3546           gPtr = group_base;
3547           while (gPtr)
3548             {
3549               com_err(whoami, 0, "user %s exist with MoiraId = %s",
3550                       gPtr->value, MoiraId);
3551               gPtr = gPtr->next;
3552             }
3553         }
3554     }
3555   if (group_count != 1)
3556     {
3557       linklist_free(group_base);
3558       group_count = 0;
3559       group_base = NULL;
3560       sprintf(filter, "(sAMAccountName=%s)", UserName);
3561       attr_array[0] = "sAMAccountName";
3562       attr_array[1] = NULL;
3563       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3564                                &group_base, &group_count)) != 0)
3565         {
3566           com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
3567                   UserName, ldap_err2string(rc));
3568           return(rc);
3569         }
3570     }
3571
3572   if (group_count != 1)
3573     {
3574       linklist_free(group_base);
3575       return(AD_NO_USER_FOUND);
3576     }
3577   strcpy(SamAccountName, group_base->value);
3578   linklist_free(group_base);
3579   group_count = 0;
3580   rc = 0;
3581   if (strcmp(SamAccountName, UserName))
3582     {
3583       rc = user_rename(ldap_handle, dn_path, SamAccountName, 
3584                        UserName);
3585     }
3586   return(0);
3587 }
This page took 0.308734 seconds and 3 git commands to generate.