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