]> andersk Git - moira.git/blob - incremental/winad/winad.c
d687b55a0218725ed766032187a198e2fefb2a09
[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 to 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 to 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, after[U_NAME], 
1083                        after_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("_zZxc")], "_zZx", strlen("_zZx")))
1728     {
1729       sprintf(sam_name, "%s_zZx%c", after_group_name, after_group_membership[0]);
1730     }
1731   else if (!strncmp(&sam_name[strlen(sam_name) - strlen("_group")], "_group", strlen("_group")))
1732     {
1733       sprintf(sam_name, "%s_group", after_group_name);
1734     }
1735   else
1736     {
1737       com_err(whoami, 0, "Couldn't rename list from %s to %s : sAMAccountName not found",
1738               before_group_name, after_group_name);
1739       return(rc);
1740     }
1741   samAccountName_v[0] = sam_name;
1742   if (after_security_flag)
1743     groupTypeControl |= ADS_GROUP_TYPE_SECURITY_ENABLED;
1744   sprintf(groupTypeControlStr, "%ld", groupTypeControl);
1745   groupTypeControl_v[0] = groupTypeControlStr;
1746   n = 0;
1747   ADD_ATTR("samAccountName", samAccountName_v, LDAP_MOD_REPLACE);
1748   ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
1749   desc_v[0] = after_desc;
1750   if (strlen(after_desc) == 0)
1751     desc_v[0] = NULL;
1752   ADD_ATTR("description", desc_v, LDAP_MOD_REPLACE);
1753   mitMoiraId_v[0] = MoiraId;
1754   ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
1755   ADD_ATTR("groupType", groupTypeControl_v, LDAP_MOD_REPLACE);
1756   mods[n] = NULL;
1757   sprintf(new_dn, "cn=%s,%s,%s", after_group_name, after_group_ou, dn_path);
1758   if ((rc = ldap_modify_s(ldap_handle, new_dn, mods)) != LDAP_SUCCESS)
1759     {
1760       com_err(whoami, 0, "After renaming, couldn't modify list data for %s : %s",
1761               after_group_name, ldap_err2string(rc));
1762     }
1763   for (i = 0; i < n; i++)
1764     free(mods[i]);
1765   return(rc);
1766 }
1767
1768 int group_create(int ac, char **av, void *ptr)
1769 {
1770   LDAPMod *mods[20];
1771   LK_ENTRY  *group_base;
1772   char new_dn[256];
1773   char group_ou[256];
1774   char new_group_name[256];
1775   char sam_group_name[256];
1776   char cn_group_name[256];
1777   char *cn_v[] = {NULL, NULL};
1778   char *objectClass_v[] = {"top", "group", NULL};
1779   char info[256];
1780   char *samAccountName_v[] = {NULL, NULL};
1781   char *managedBy_v[] = {NULL, NULL};
1782   char *altSecurityIdentities_v[] = {NULL, NULL};
1783   char *member_v[] = {NULL, NULL};
1784   char *name_v[] = {NULL, NULL};
1785   char *desc_v[] = {NULL, NULL};
1786   char *info_v[] = {NULL, NULL};
1787   char *mitMoiraId_v[] = {NULL, NULL};
1788   char *groupTypeControl_v[] = {NULL, NULL};
1789   char groupTypeControlStr[80];
1790   char group_membership[1];
1791   int  i;
1792   int  security_flag;
1793   u_int groupTypeControl = ADS_GROUP_TYPE_GLOBAL_GROUP;
1794   int  n;
1795   int  rc;
1796   int  group_count;
1797   int  updateGroup;
1798   char filter[128];
1799   char *attr_array[3];
1800   char **call_args;
1801
1802   call_args = ptr;
1803
1804   if (!check_string(av[L_NAME]))
1805     {
1806       com_err(whoami, 0, "invalid LDAP list name %s", av[L_NAME]);
1807       return(AD_INVALID_NAME);
1808     }
1809
1810   updateGroup = (int)call_args[4];
1811   memset(group_ou, 0, sizeof(group_ou));
1812   memset(group_membership, 0, sizeof(group_membership));
1813   security_flag = 0;
1814   get_group_membership(group_membership, group_ou, &security_flag, av);
1815   strcpy(new_group_name, av[L_NAME]);
1816   sprintf(new_dn, "cn=%s,%s,%s", new_group_name, group_ou, call_args[1]);
1817   if (security_flag)
1818     groupTypeControl |= ADS_GROUP_TYPE_SECURITY_ENABLED;
1819   
1820   sprintf(sam_group_name, "%s_group", av[L_NAME]);
1821
1822   if (!updateGroup)
1823     {
1824
1825       sprintf(groupTypeControlStr, "%ld", groupTypeControl);
1826       groupTypeControl_v[0] = groupTypeControlStr;
1827
1828       strcpy(cn_group_name, av[L_NAME]);
1829
1830       samAccountName_v[0] = sam_group_name;
1831       name_v[0] = new_group_name;
1832       cn_v[0] = new_group_name;
1833
1834       n = 0;
1835       ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
1836       ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
1837       ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
1838       ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
1839       ADD_ATTR("name", name_v, LDAP_MOD_ADD);
1840       if (strlen(av[L_DESC]) != 0)
1841         {
1842           desc_v[0] = av[L_DESC];
1843           ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
1844         }
1845       ADD_ATTR("groupType", groupTypeControl_v, LDAP_MOD_ADD);
1846       if (strlen(av[L_ACE_NAME]) != 0)
1847         {
1848           sprintf(info, "The Administrator of this list is: %s", av[L_ACE_NAME]);
1849           info_v[0] = info;
1850           ADD_ATTR("info", info_v, LDAP_MOD_ADD);
1851         }
1852       if (strlen(call_args[5]) != 0)
1853         {
1854           mitMoiraId_v[0] = call_args[5];
1855           ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_ADD);
1856         }
1857       mods[n] = NULL;
1858
1859       rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
1860
1861       for (i = 0; i < n; i++)
1862         free(mods[i]);
1863       if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
1864         {
1865           com_err(whoami, 0, "Unable to create/update list %s in AD : %s",
1866                   av[L_NAME], ldap_err2string(rc));
1867           callback_rc = rc;
1868           return(rc);
1869         }
1870     }
1871   if ((rc == LDAP_ALREADY_EXISTS) || (updateGroup))
1872     {
1873       n = 0;
1874       desc_v[0] = NULL;
1875       if (strlen(av[L_DESC]) != 0)
1876         desc_v[0] = av[L_DESC];
1877       ADD_ATTR("description", desc_v, LDAP_MOD_REPLACE);
1878       info_v[0] = NULL;
1879       if (strlen(av[L_ACE_NAME]) != 0)
1880         {
1881           sprintf(info, "The Administrator of this list is: %s", av[L_ACE_NAME]);
1882           info_v[0] = info;
1883         }
1884       ADD_ATTR("info", info_v, LDAP_MOD_REPLACE);
1885       if (strlen(call_args[5]) != 0)
1886         {
1887           mitMoiraId_v[0] = call_args[5];
1888           ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
1889         }
1890       if (!(atoi(av[L_ACTIVE])))
1891         {
1892           member_v[0] = NULL;
1893           ADD_ATTR("member", member_v, LDAP_MOD_REPLACE);
1894         }
1895       mods[n] = NULL;
1896       rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
1897       for (i = 0; i < n; i++)
1898         free(mods[i]);
1899     }
1900
1901   sprintf(filter, "(sAMAccountName=%s)", sam_group_name);
1902   if (strlen(call_args[5]) != 0)
1903     sprintf(filter, "(mitMoiraId=%s)", call_args[5]);
1904   attr_array[0] = "objectSid";
1905   attr_array[1] = NULL;
1906   group_count = 0;
1907   group_base = NULL;
1908   if ((rc = linklist_build((LDAP *)call_args[0], call_args[1], filter, attr_array, 
1909                            &group_base, &group_count)) == LDAP_SUCCESS)
1910     {
1911       if (group_count == 1)
1912         {
1913           (*sid_ptr) = group_base;
1914           (*sid_ptr)->member = strdup(av[L_NAME]);
1915           (*sid_ptr)->type = (char *)GROUPS;
1916           sid_ptr = &(*sid_ptr)->next;
1917         }
1918       else
1919         {
1920           if (group_base != NULL)
1921             linklist_free(group_base);
1922         }
1923     }
1924   else
1925     {
1926       if (group_base != NULL)
1927         linklist_free(group_base);
1928     }
1929   return(LDAP_SUCCESS);
1930 }
1931
1932 int group_delete(LDAP *ldap_handle, char *dn_path, char *group_name, 
1933                  char *group_membership, char *MoiraId)
1934 {
1935   LK_ENTRY  *group_base;
1936   char      temp[512];
1937   char      filter[128];
1938   int       group_count;
1939   int       rc;
1940
1941   if (!check_string(group_name))
1942     {
1943       com_err(whoami, 0, "invalid LDAP list name %s", group_name);
1944       return(AD_INVALID_NAME);
1945     }
1946
1947   memset(filter, '\0', sizeof(filter));
1948   group_count = 0;
1949   group_base = NULL;
1950   sprintf(temp, "%s,%s", group_ou_root, dn_path);
1951   if (rc = ad_get_group(ldap_handle, temp, group_name, 
1952                         group_membership, MoiraId, 
1953                         "distinguishedName", &group_base, 
1954                         &group_count, filter))
1955     return(rc);
1956
1957   if (group_count == 1)
1958     {
1959       if ((rc = ldap_delete_s(ldap_handle, group_base->value)) != LDAP_SUCCESS)
1960         {
1961           linklist_free(group_base);
1962           com_err(whoami, 0, "Unable to delete list %s from AD : %s",
1963                   group_name, ldap_err2string(rc));
1964           return(rc);
1965         }
1966       linklist_free(group_base);
1967     }
1968   else
1969     {
1970       linklist_free(group_base);
1971       com_err(whoami, 0, "Unable to find list %s in AD.", group_name);
1972       return(AD_NO_GROUPS_FOUND);
1973     }
1974
1975   return(0);
1976 }
1977
1978 int process_lists(int ac, char **av, void *ptr)
1979 {
1980   int   rc;
1981   int   security_flag;
1982   char  group_ou[256];
1983   char  group_membership[2];
1984   char  **call_args;
1985
1986   call_args = ptr;
1987
1988   security_flag = 0;
1989   memset(group_ou, '\0', sizeof(group_ou));
1990   memset(group_membership, '\0', sizeof(group_membership));
1991   get_group_membership(group_membership, group_ou, &security_flag, av);
1992   rc = member_add((LDAP *)call_args[0], (char *)call_args[1], av[L_NAME],
1993                   group_ou, group_membership, call_args[2], 
1994                   (char *)call_args[3], "");
1995   return(0);
1996 }
1997
1998 int member_list_build(int ac, char **av, void *ptr)
1999 {
2000   LK_ENTRY  *linklist;
2001   char      temp[1024];
2002   char      **call_args;
2003
2004   call_args = ptr;
2005
2006   strcpy(temp, av[ACE_NAME]);
2007   if (!check_string(temp))
2008     return(0);
2009   if (!strcmp(av[ACE_TYPE], "USER"))
2010     {
2011       if (!((int)call_args[3] & MOIRA_USERS))
2012         return(0);
2013     }
2014   else if (!strcmp(av[ACE_TYPE], "STRING"))
2015     {
2016       if (!((int)call_args[3] & MOIRA_STRINGS))
2017         return(0);
2018       if (contact_create((LDAP *)call_args[0], call_args[1], temp, contact_ou))
2019         return(0);
2020     }
2021   else if (!strcmp(av[ACE_TYPE], "LIST"))
2022     {
2023       if (!((int)call_args[3] & MOIRA_LISTS))
2024         return(0);
2025     }
2026   else if (!strcmp(av[ACE_TYPE], "KERBEROS"))
2027     {
2028       if (!((int)call_args[3] & MOIRA_KERBEROS))
2029         return(0);
2030       if (contact_create((LDAP *)call_args[0], call_args[1], temp, kerberos_ou))
2031         return(0);
2032     }
2033   else
2034     return(0);
2035
2036   linklist = member_base;
2037   while (linklist)
2038     {
2039     if (!strcasecmp(temp, linklist->member))
2040       return(0);
2041     linklist = linklist->next;
2042     }
2043   linklist = calloc(1, sizeof(LK_ENTRY));
2044   linklist->op = 1;
2045   linklist->dn = NULL;
2046   linklist->list = calloc(1, strlen(call_args[2]) + 1);
2047   strcpy(linklist->list, call_args[2]);
2048   linklist->type = calloc(1, strlen(av[ACE_TYPE]) + 1);
2049   strcpy(linklist->type, av[ACE_TYPE]);
2050   linklist->member = calloc(1, strlen(temp) + 1);
2051   strcpy(linklist->member, temp);
2052   linklist->next = member_base;
2053   member_base = linklist;
2054   return(0);
2055 }
2056
2057 int member_remove(LDAP *ldap_handle, char *dn_path, char *group_name, 
2058                   char *group_ou, char *group_membership, char *user_name,
2059                   char *UserOu, char *MoiraId)
2060 {
2061   char        distinguished_name[1024];
2062   char        *modvalues[2];
2063   char        temp[256];
2064   char        filter[128];
2065   int         group_count;
2066   int         i;
2067   int         n;
2068   LDAPMod     *mods[20];
2069   LK_ENTRY    *group_base;
2070   ULONG       rc;
2071
2072   if (!check_string(group_name))
2073     return(AD_INVALID_NAME);
2074
2075   memset(filter, '\0', sizeof(filter));
2076   group_base = NULL;
2077   group_count = 0;
2078   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
2079                         group_membership, MoiraId, 
2080                         "distinguishedName", &group_base, 
2081                         &group_count, filter))
2082     return(rc);
2083
2084   if (group_count != 1)
2085     {
2086       com_err(whoami, 0, "LDAP server unable to find list %s in AD",
2087               group_name);
2088       linklist_free(group_base);
2089       group_base = NULL;
2090       group_count = 0;
2091       goto cleanup;
2092     }
2093   strcpy(distinguished_name, group_base->value);
2094   linklist_free(group_base);
2095   group_base = NULL;
2096   group_count = 0;
2097
2098   sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
2099   modvalues[0] = temp;
2100   modvalues[1] = NULL;
2101
2102   n = 0;
2103   ADD_ATTR("member", modvalues, LDAP_MOD_DELETE);
2104   mods[n] = NULL;
2105   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
2106   for (i = 0; i < n; i++)
2107     free(mods[i]);
2108   if ((!strcmp(UserOu, kerberos_ou)) || (!strcmp(UserOu, contact_ou)))
2109     {
2110       if (rc == LDAP_UNWILLING_TO_PERFORM)
2111         rc = LDAP_SUCCESS;
2112     }
2113   if (rc != LDAP_SUCCESS)
2114     {
2115       com_err(whoami, 0, "LDAP server unable to modify list %s members : %s",
2116               group_name, ldap_err2string(rc));
2117       goto cleanup;
2118     }
2119
2120 cleanup:
2121   return(rc);
2122 }
2123
2124 int member_add(LDAP *ldap_handle, char *dn_path, char *group_name, 
2125                char *group_ou, char *group_membership, char *user_name, 
2126                char *UserOu, char *MoiraId)
2127 {
2128   char        distinguished_name[1024];
2129   char        *modvalues[2];
2130   char        temp[256];
2131   char        filter[128];
2132   int         group_count;
2133   int         n;
2134   int         i;
2135   LDAPMod     *mods[20];
2136   LK_ENTRY    *group_base;
2137   ULONG       rc;
2138
2139   if (!check_string(group_name))
2140     return(AD_INVALID_NAME);
2141
2142   rc = 0;
2143   memset(filter, '\0', sizeof(filter));
2144   group_base = NULL;
2145   group_count = 0;
2146   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
2147                         group_membership, MoiraId, 
2148                         "distinguishedName", &group_base, 
2149                         &group_count, filter))
2150     return(rc);
2151
2152   if (group_count != 1)
2153     {
2154       linklist_free(group_base);
2155       group_base = NULL;
2156       group_count = 0;
2157       com_err(whoami, 0, "LDAP server unable to find list %s in AD",
2158               group_name);
2159       return(AD_MULTIPLE_GROUPS_FOUND);
2160     }
2161
2162   strcpy(distinguished_name, group_base->value);
2163   linklist_free(group_base);
2164   group_base = NULL;
2165   group_count = 0;
2166
2167   sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
2168   modvalues[0] = temp;
2169   modvalues[1] = NULL;
2170
2171   n = 0;
2172   ADD_ATTR("member", modvalues, LDAP_MOD_ADD);
2173   mods[n] = NULL;
2174   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
2175   if (rc == LDAP_ALREADY_EXISTS)
2176     rc = LDAP_SUCCESS;
2177   if ((!strcmp(UserOu, contact_ou)) || (!strcmp(UserOu, kerberos_ou)))
2178     {
2179       if (rc == LDAP_UNWILLING_TO_PERFORM)
2180         rc = LDAP_SUCCESS;
2181     }
2182   for (i = 0; i < n; i++)
2183     free(mods[i]);
2184   if (rc != LDAP_SUCCESS)
2185     {
2186       com_err(whoami, 0, "LDAP server unable to add %s to list %s as a member : %s",
2187               user_name, group_name, ldap_err2string(rc));
2188     }
2189
2190   return(rc);
2191 }
2192
2193 int contact_create(LDAP *ld, char *bind_path, char *user, char *group_ou)
2194 {
2195   LDAPMod *mods[20];
2196   char new_dn[256];
2197   char cn_user_name[256];
2198   char contact_name[256];
2199   char *email_v[] = {NULL, NULL};
2200   char *cn_v[] = {NULL, NULL};
2201   char *contact_v[] = {NULL, NULL};
2202   char *objectClass_v[] = {"top", "person", 
2203                            "organizationalPerson", 
2204                            "contact", NULL};
2205   char *name_v[] = {NULL, NULL};
2206   char *desc_v[] = {NULL, NULL};
2207   int  n;
2208   int  rc;
2209   int  i;
2210
2211   if (!check_string(user))
2212     {
2213       com_err(whoami, 0, "invalid LDAP name %s", user);
2214       return(AD_INVALID_NAME);
2215     }
2216   strcpy(contact_name, user);
2217   sprintf(cn_user_name,"CN=%s,%s,%s", contact_name, group_ou, bind_path);
2218   cn_v[0] = cn_user_name;
2219   contact_v[0] = contact_name;
2220   name_v[0] = user;
2221   desc_v[0] = "Auto account created by Moira";
2222   email_v[0] = user;
2223
2224   strcpy(new_dn, cn_user_name);
2225   n = 0;
2226   ADD_ATTR("cn", contact_v, LDAP_MOD_ADD);
2227   ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2228   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2229   ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2230   ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2231   if (!strcmp(group_ou, contact_ou))
2232     {
2233       ADD_ATTR("mail", email_v, LDAP_MOD_ADD);
2234     }
2235   mods[n] = NULL;
2236
2237   rc = ldap_add_ext_s(ld, new_dn, mods, NULL, NULL);
2238   for (i = 0; i < n; i++)
2239     free(mods[i]);
2240   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2241     {
2242       n = 0;
2243       ADD_ATTR("cn", contact_v, LDAP_MOD_ADD);
2244       ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2245       ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2246       ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2247       ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2248       mods[n] = NULL;
2249       rc = ldap_add_ext_s(ld, new_dn, mods, NULL, NULL);
2250       for (i = 0; i < n; i++)
2251         free(mods[i]);
2252     }
2253   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2254     {
2255       com_err(whoami, 0, "could not create contact %s : %s",
2256               user, ldap_err2string(rc));
2257       return(rc);
2258     }
2259   return(0);
2260 }
2261
2262 int user_update(LDAP *ldap_handle, char *dn_path, char *user_name,
2263                 char *Uid, char *MitId, char *MoiraId, int State)
2264 {
2265   LDAPMod   *mods[20];
2266   LK_ENTRY  *group_base;
2267   int  group_count;
2268   char distinguished_name[256];
2269   char *mitMoiraId_v[] = {NULL, NULL};
2270   char *uid_v[] = {NULL, NULL};
2271   char *mitid_v[] = {NULL, NULL};
2272   char *homedir_v[] = {NULL, NULL};
2273   char *winProfile_v[] = {NULL, NULL};
2274   char *drives_v[] = {NULL, NULL};
2275   char *userAccountControl_v[] = {NULL, NULL};
2276   char userAccountControlStr[80];
2277   int  n;
2278   int  rc;
2279   int  i;
2280   u_int userAccountControl = UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD | UF_PASSWD_CANT_CHANGE;
2281   char filter[128];
2282   char *attr_array[3];
2283   char **hp;
2284   char path[256];
2285   char winPath[256];
2286   char winProfile[256];
2287
2288   if (!check_string(user_name))
2289     {
2290       com_err(whoami, 0, "invalid LDAP user name %s", user_name);
2291       return(AD_INVALID_NAME);
2292     }
2293
2294   group_count = 0;
2295   group_base = NULL;
2296
2297   if (strlen(MoiraId) != 0)
2298     {
2299       sprintf(filter, "(mitMoiraId=%s)", MoiraId);
2300       attr_array[0] = "cn";
2301       attr_array[1] = NULL;
2302       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
2303                                &group_base, &group_count)) != 0)
2304         {
2305           com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
2306                   user_name, ldap_err2string(rc));
2307           return(rc);
2308         }
2309     }
2310   if (group_count == 0)
2311     {
2312       sprintf(filter, "(sAMAccountName=%s)", user_name);
2313       attr_array[0] = "cn";
2314       attr_array[1] = NULL;
2315       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
2316                                &group_base, &group_count)) != 0)
2317         {
2318           com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
2319                   user_name, ldap_err2string(rc));
2320           return(rc);
2321         }
2322     }
2323
2324   if (group_count != 1)
2325     {
2326       com_err(whoami, 0, "LDAP server unable to find user %s in AD",
2327               user_name);
2328       linklist_free(group_base);
2329       return(AD_NO_USER_FOUND);
2330     }
2331   strcpy(distinguished_name, group_base->dn);
2332
2333   linklist_free(group_base);
2334   group_count = 0;
2335   n = 0;
2336   if ((hp = hes_resolve(user_name, "filsys")) != NULL)
2337     {
2338       memset(path, 0, sizeof(path));
2339       memset(winPath, 0, sizeof(winPath));
2340       sscanf(hp[0], "%*s %s", path);
2341       if (strlen(path) && strnicmp(path, AFS, strlen(AFS)) == 0)
2342         {
2343           AfsToWinAfs(path, winPath);
2344           homedir_v[0] = winPath;
2345           ADD_ATTR("homeDirectory", homedir_v, LDAP_MOD_REPLACE);
2346           strcpy(winProfile, winPath);
2347           strcat(winProfile, "\\.winprofile");
2348           winProfile_v[0] = winProfile;
2349           ADD_ATTR("profilePath", winProfile_v, LDAP_MOD_REPLACE);
2350           drives_v[0] = "H:";
2351           ADD_ATTR("homeDrive", drives_v, LDAP_MOD_REPLACE);
2352         }
2353     }
2354   uid_v[0] = Uid;
2355   if (strlen(Uid) == 0)
2356     uid_v[0] = NULL;
2357   ADD_ATTR("uid", uid_v, LDAP_MOD_REPLACE);
2358   ADD_ATTR("uidNumber", uid_v, LDAP_MOD_REPLACE);
2359   mitid_v[0] = MitId;
2360   if (strlen(MitId) == 0)
2361     mitid_v[0] = NULL;
2362   ADD_ATTR("employeeID", mitid_v, LDAP_MOD_REPLACE);
2363   mitMoiraId_v[0] = MoiraId;
2364   if (strlen(MoiraId) == 0)
2365     mitMoiraId_v[0] = NULL;
2366   ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
2367   if ((State != US_NO_PASSWD) && (State != US_REGISTERED))
2368     userAccountControl |= UF_ACCOUNTDISABLE;
2369   sprintf(userAccountControlStr, "%ld", userAccountControl);
2370   userAccountControl_v[0] = userAccountControlStr;
2371   ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_REPLACE);
2372   mods[n] = NULL;
2373   if ((rc = ldap_modify_s(ldap_handle, distinguished_name, mods)) != LDAP_SUCCESS)
2374     {
2375       com_err(whoami, 0, "Couldn't modify user data for %s : %s",
2376               user_name, ldap_err2string(rc));
2377     }
2378   for (i = 0; i < n; i++)
2379     free(mods[i]);
2380
2381   if (hp != NULL)
2382     {
2383       i = 0;
2384       while (hp[i])
2385         {
2386           free(hp[i]);
2387           i++;
2388         }
2389     }
2390
2391   return(rc);
2392 }
2393
2394 int user_rename(LDAP *ldap_handle, char *dn_path, char *before_user_name, 
2395                 char *user_name)
2396 {
2397   LDAPMod *mods[20];
2398   char new_dn[256];
2399   char old_dn[256];
2400   char upn[256];
2401   char temp[128];
2402   char *userPrincipalName_v[] = {NULL, NULL};
2403   char *altSecurityIdentities_v[] = {NULL, NULL};
2404   char *name_v[] = {NULL, NULL};
2405   char *samAccountName_v[] = {NULL, NULL};
2406   int  n;
2407   int  rc;
2408   int  i;
2409
2410   if (!check_string(before_user_name))
2411     {
2412       com_err(whoami, 0, "invalid LDAP user name %s", before_user_name);
2413       return(AD_INVALID_NAME);
2414     }
2415   if (!check_string(user_name))
2416     {
2417       com_err(whoami, 0, "invalid LDAP user name %s", user_name);
2418       return(AD_INVALID_NAME);
2419     }
2420
2421   strcpy(user_name, user_name);
2422   sprintf(old_dn, "cn=%s,%s,%s", before_user_name, user_ou, dn_path);
2423   sprintf(new_dn, "cn=%s", user_name);
2424   if ((rc = ldap_rename_s(ldap_handle, old_dn, new_dn, NULL, TRUE, 
2425                            NULL, NULL)) != LDAP_SUCCESS)
2426     {
2427       com_err(whoami, 0, "Couldn't rename user from %s to %s : %s",
2428               before_user_name, user_name, ldap_err2string(rc));
2429       return(rc);
2430     }
2431
2432   name_v[0] = user_name;
2433   sprintf(upn, "%s@%s", user_name, ldap_domain);
2434   userPrincipalName_v[0] = upn;
2435   sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
2436   altSecurityIdentities_v[0] = temp;
2437   samAccountName_v[0] = user_name;
2438
2439   n = 0;
2440   ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_REPLACE);
2441   ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_REPLACE);
2442   ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
2443   ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_REPLACE);
2444   mods[n] = NULL;
2445   sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, dn_path);
2446   if ((rc = ldap_modify_s(ldap_handle, new_dn, mods)) != LDAP_SUCCESS)
2447     {
2448       com_err(whoami, 0, "After renaming, couldn't modify user data for %s : %s",
2449               user_name, ldap_err2string(rc));
2450     }
2451   for (i = 0; i < n; i++)
2452     free(mods[i]);
2453   return(rc);
2454 }
2455
2456 int filesys_process(LDAP *ldap_handle, char *dn_path, char *fs_name, 
2457                     char *fs_type, char *fs_pack, int operation)
2458 {
2459   char  distinguished_name[256];
2460   char  winPath[256];
2461   char  winProfile[256];
2462   char  filter[128];
2463   char  *attr_array[3];
2464   char  *homedir_v[] = {NULL, NULL};
2465   char  *winProfile_v[] = {NULL, NULL};
2466   char  *drives_v[] = {NULL, NULL};
2467   int   group_count;
2468   int   n;
2469   int   rc;
2470   int   i;
2471   LDAPMod   *mods[20];
2472   LK_ENTRY  *group_base;
2473
2474   if (!check_string(fs_name))
2475     {
2476       com_err(whoami, 0, "invalid filesys name %s", fs_name);
2477       return(AD_INVALID_NAME);
2478     }
2479
2480   if (strcmp(fs_type, "AFS"))
2481     {
2482       com_err(whoami, 0, "invalid filesys type %s", fs_type);
2483       return(AD_INVALID_FILESYS);
2484     }
2485
2486   group_count = 0;
2487   group_base = NULL;
2488   sprintf(filter, "(sAMAccountName=%s)", fs_name);
2489   attr_array[0] = "cn";
2490   attr_array[1] = NULL;
2491   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
2492                            &group_base, &group_count)) != 0)
2493     {
2494       com_err(whoami, 0, "LDAP server couldn't process filesys %s : %s",
2495               fs_name, ldap_err2string(rc));
2496       return(rc);
2497     }
2498
2499   if (group_count != 1)
2500     {
2501       linklist_free(group_base);
2502       com_err(whoami, 0, "LDAP server unable to find user %s in AD",
2503               fs_name);
2504       return(LDAP_NO_SUCH_OBJECT);
2505     }
2506   strcpy(distinguished_name, group_base->dn);
2507   linklist_free(group_base);
2508   group_count = 0;
2509
2510   n = 0;
2511   if (operation == LDAP_MOD_ADD)
2512     {
2513       memset(winPath, 0, sizeof(winPath));
2514       AfsToWinAfs(fs_pack, winPath);
2515       homedir_v[0] = winPath;
2516       drives_v[0] = "H:";
2517       memset(winProfile, 0, sizeof(winProfile));
2518       strcpy(winProfile, winPath);
2519       strcat(winProfile, "\\.winprofile");
2520       winProfile_v[0] = winProfile;
2521     }
2522   else
2523     {
2524       homedir_v[0] = NULL;
2525       drives_v[0] = NULL;
2526       winProfile_v[0] = NULL;
2527     }
2528   ADD_ATTR("profilePath", winProfile_v, operation);
2529   ADD_ATTR("homeDrive", drives_v, operation);
2530   ADD_ATTR("homeDirectory", homedir_v, operation);
2531   mods[n] = NULL;
2532
2533   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
2534   if (rc != LDAP_SUCCESS)
2535     {
2536       com_err(whoami, 0, "Couldn't modify user data for filesys %s : %s",
2537               fs_name, ldap_err2string(rc));
2538     }
2539   for (i = 0; i < n; i++)
2540     free(mods[i]);
2541
2542   return(rc);
2543 }
2544
2545 int user_create(int ac, char **av, void *ptr)
2546 {
2547   LK_ENTRY  *group_base;
2548   LDAPMod *mods[20];
2549   char new_dn[256];
2550   char user_name[256];
2551   char sam_name[256];
2552   char upn[256];
2553   char *cn_v[] = {NULL, NULL};
2554   char *objectClass_v[] = {"top", "person", 
2555                            "organizationalPerson", 
2556                            "user", NULL};
2557
2558   char *samAccountName_v[] = {NULL, NULL};
2559   char *altSecurityIdentities_v[] = {NULL, NULL};
2560   char *mitMoiraId_v[] = {NULL, NULL};
2561   char *name_v[] = {NULL, NULL};
2562   char *desc_v[] = {NULL, NULL};
2563   char *userPrincipalName_v[] = {NULL, NULL};
2564   char *userAccountControl_v[] = {NULL, NULL};
2565   char *uid_v[] = {NULL, NULL};
2566   char *mitid_v[] = {NULL, NULL};
2567   char userAccountControlStr[80];
2568   char temp[128];
2569   u_int userAccountControl = UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD | UF_PASSWD_CANT_CHANGE;
2570   int  n;
2571   int  rc;
2572   int  i;
2573   int  group_count;
2574   char filter[128];
2575   char *attr_array[3];
2576   char **call_args;
2577
2578   call_args = ptr;
2579
2580   if (!check_string(av[U_NAME]))
2581     {
2582       callback_rc = AD_INVALID_NAME;
2583       com_err(whoami, 0, "invalid LDAP user name %s", av[U_NAME]);
2584       return(AD_INVALID_NAME);
2585     }
2586
2587   strcpy(user_name, av[U_NAME]);
2588   sprintf(upn, "%s@%s", user_name, ldap_domain);
2589   sprintf(sam_name, "%s", av[U_NAME]);
2590   samAccountName_v[0] = sam_name;
2591   if ((atoi(av[U_STATE]) != US_NO_PASSWD) && (atoi(av[U_STATE]) != US_REGISTERED))
2592     userAccountControl |= UF_ACCOUNTDISABLE;
2593   sprintf(userAccountControlStr, "%ld", userAccountControl);
2594   userAccountControl_v[0] = userAccountControlStr;
2595   userPrincipalName_v[0] = upn;
2596
2597   cn_v[0] = user_name;
2598   name_v[0] = user_name;
2599   desc_v[0] = "Auto account created by Moira";
2600   sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
2601   altSecurityIdentities_v[0] = temp;    
2602   sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, call_args[1]);
2603
2604   n = 0;
2605   ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
2606   ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2607   ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
2608   ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_ADD);
2609   ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_ADD);
2610   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2611   ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2612   ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2613   if (strlen(call_args[2]) != 0)
2614     {
2615       mitMoiraId_v[0] = call_args[2];
2616       ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_ADD);
2617     }
2618   ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_ADD);
2619   if (strlen(av[U_UID]) != 0)
2620     {
2621       uid_v[0] = av[U_UID];
2622       ADD_ATTR("uid", uid_v, LDAP_MOD_ADD);
2623       ADD_ATTR("uidNumber", uid_v, LDAP_MOD_ADD);
2624     }
2625   if (strlen(av[U_MITID]) != 0)
2626       mitid_v[0] = av[U_MITID];
2627   else
2628       mitid_v[0] = "none";
2629   ADD_ATTR("employeeID", mitid_v, LDAP_MOD_ADD);
2630   mods[n] = NULL;
2631
2632   rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
2633   for (i = 0; i < n; i++)
2634     free(mods[i]);
2635   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2636     {
2637       com_err(whoami, 0, "could not create user %s : %s",
2638               user_name, ldap_err2string(rc));
2639       callback_rc = rc;
2640       return(rc);
2641     }
2642   if (rc == LDAP_SUCCESS)
2643     {
2644       if ((rc = set_password(sam_name, "", ldap_domain)) != 0)
2645         {
2646           com_err(whoami, 0, "Couldn't set password for user %s : %ld",
2647                   user_name, rc);
2648         }
2649     }
2650   sprintf(filter, "(sAMAccountName=%s)", av[U_NAME]);
2651   if (strlen(call_args[2]) != 0)
2652     sprintf(filter, "(mitMoiraId=%s)", call_args[2]);
2653   attr_array[0] = "objectSid";
2654   attr_array[1] = NULL;
2655   group_count = 0;
2656   group_base = NULL;
2657   if ((rc = linklist_build((LDAP *)call_args[0], call_args[1], filter, attr_array, 
2658                            &group_base, &group_count)) == LDAP_SUCCESS)
2659     {
2660       if (group_count == 1)
2661         {
2662           (*sid_ptr) = group_base;
2663           (*sid_ptr)->member = strdup(av[L_NAME]);
2664           (*sid_ptr)->type = (char *)GROUPS;
2665           sid_ptr = &(*sid_ptr)->next;
2666         }
2667       else
2668         {
2669           if (group_base != NULL)
2670             linklist_free(group_base);
2671         }
2672     }
2673   else
2674     {
2675       if (group_base != NULL)
2676         linklist_free(group_base);
2677     }
2678   return(0);
2679 }
2680
2681 int user_change_status(LDAP *ldap_handle, char *dn_path, 
2682                        char *user_name, char *MoiraId,
2683                        int operation)
2684 {
2685   char      filter[128];
2686   char      *attr_array[3];
2687   char      temp[256];
2688   char      distinguished_name[1024];
2689   char      **modvalues;
2690   char      *mitMoiraId_v[] = {NULL, NULL};
2691   LDAPMod   *mods[20];
2692   LK_ENTRY  *group_base;
2693   int       group_count;
2694   int       rc;
2695   int       i;
2696   int       n;
2697   ULONG     ulongValue;
2698
2699   if (!check_string(user_name))
2700     {
2701       com_err(whoami, 0, "invalid LDAP user name %s", user_name);
2702       return(AD_INVALID_NAME);
2703     }
2704
2705   group_count = 0;
2706   group_base = NULL;
2707
2708   if (strlen(MoiraId) != 0)
2709     {
2710       sprintf(filter, "(mitMoiraId=%s)", MoiraId);
2711       attr_array[0] = "UserAccountControl";
2712       attr_array[1] = NULL;
2713       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
2714                                &group_base, &group_count)) != 0)
2715         {
2716           com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
2717                   user_name, ldap_err2string(rc));
2718           return(rc);
2719         }
2720     }
2721   if (group_count == 0)
2722     {
2723       sprintf(filter, "(sAMAccountName=%s)", user_name);
2724       attr_array[0] = "UserAccountControl";
2725       attr_array[1] = NULL;
2726       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
2727                                &group_base, &group_count)) != 0)
2728         {
2729           com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
2730                   user_name, ldap_err2string(rc));
2731           return(rc);
2732         }
2733     }
2734
2735   if (group_count != 1)
2736     {
2737       linklist_free(group_base);
2738       com_err(whoami, 0, "LDAP server unable to find user %s in AD",
2739               user_name);
2740       return(LDAP_NO_SUCH_OBJECT);
2741     }
2742
2743   strcpy(distinguished_name, group_base->dn);
2744   ulongValue = atoi((*group_base).value);
2745   if (operation == MEMBER_DEACTIVATE)
2746     ulongValue |= UF_ACCOUNTDISABLE;
2747   else    
2748     ulongValue &= ~UF_ACCOUNTDISABLE;
2749   sprintf(temp, "%ld", ulongValue);
2750   if ((rc = construct_newvalues(group_base, group_count, (*group_base).value, 
2751                                 temp, &modvalues, REPLACE)) == 1)
2752     goto cleanup;
2753   linklist_free(group_base);
2754   group_base = NULL;
2755   group_count = 0;
2756   n = 0;
2757   ADD_ATTR("UserAccountControl", modvalues, LDAP_MOD_REPLACE);
2758   if (strlen(MoiraId) != 0)
2759     {
2760     mitMoiraId_v[0] = MoiraId;
2761     ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
2762     }
2763   mods[n] = NULL;
2764   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
2765   for (i = 0; i < n; i++)
2766     free(mods[i]);
2767   free_values(modvalues);
2768   if (rc != LDAP_SUCCESS)
2769     {
2770       com_err(whoami, 0, "LDAP server could not change status of user %s : %s",
2771               user_name, ldap_err2string(rc));
2772     }
2773 cleanup:
2774   return(rc);
2775 }
2776
2777 int user_delete(LDAP *ldap_handle, char *dn_path, 
2778                 char *u_name, char *MoiraId)
2779 {
2780   char      filter[128];
2781   char      *attr_array[3];
2782   char      distinguished_name[1024];
2783   char      user_name[512];
2784   LK_ENTRY  *group_base;
2785   int       group_count;
2786   int       rc;
2787
2788   if (!check_string(u_name))
2789     return(AD_INVALID_NAME);
2790
2791   strcpy(user_name, u_name);
2792   group_count = 0;
2793   group_base = NULL;
2794
2795   if (strlen(MoiraId) != 0)
2796     {
2797       sprintf(filter, "(mitMoiraId=%s)", MoiraId);
2798       attr_array[0] = "name";
2799       attr_array[1] = NULL;
2800       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
2801                                &group_base, &group_count)) != 0)
2802         {
2803           com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
2804                   user_name, ldap_err2string(rc));
2805           goto cleanup;
2806         }
2807     }
2808   if (group_count == 0)
2809     {
2810       sprintf(filter, "(sAMAccountName=%s)", user_name);
2811       attr_array[0] = "name";
2812       attr_array[1] = NULL;
2813       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
2814                                &group_base, &group_count)) != 0)
2815         {
2816           com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
2817                   user_name, ldap_err2string(rc));
2818           goto cleanup;
2819         }
2820     }
2821
2822   if (group_count != 1)
2823     {
2824       com_err(whoami, 0, "LDAP server unable to find user %s in AD",
2825               user_name);
2826       goto cleanup;
2827     }
2828
2829   strcpy(distinguished_name, group_base->dn);
2830   if (rc = ldap_delete_s(ldap_handle, distinguished_name))
2831     {
2832       com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
2833               user_name, ldap_err2string(rc));
2834     }
2835
2836 cleanup:
2837   linklist_free(group_base);
2838   return(0);
2839 }
2840
2841 void linklist_free(LK_ENTRY *linklist_base)
2842 {
2843   LK_ENTRY *linklist_previous;
2844
2845   while (linklist_base != NULL)
2846     {
2847       if (linklist_base->dn != NULL)
2848         free(linklist_base->dn);
2849       if (linklist_base->attribute != NULL)
2850         free(linklist_base->attribute);
2851       if (linklist_base->value != NULL)
2852         free(linklist_base->value);
2853       if (linklist_base->member != NULL)
2854         free(linklist_base->member);
2855       if (linklist_base->type != NULL)
2856         free(linklist_base->type);
2857       if (linklist_base->list != NULL)
2858         free(linklist_base->list);
2859       linklist_previous = linklist_base;
2860       linklist_base = linklist_previous->next;
2861       free(linklist_previous);
2862     }
2863 }
2864
2865 void free_values(char **modvalues)
2866 {
2867   int i;
2868
2869   i = 0;
2870   if (modvalues != NULL)
2871     {
2872     while (modvalues[i] != NULL)
2873       {
2874         free(modvalues[i]);
2875         modvalues[i] = NULL;
2876         ++i;
2877       }
2878     free(modvalues);
2879   }
2880 }
2881
2882 int sid_update(LDAP *ldap_handle, char *dn_path)
2883 {
2884   LK_ENTRY      *ptr;
2885   int           rc;
2886   unsigned char temp[126];
2887   char          *av[3];
2888
2889   ptr = sid_base;
2890
2891   while (ptr != NULL)
2892     {
2893       memset(temp, 0, sizeof(temp));
2894       convert_b_to_a(temp, ptr->value, ptr->length);
2895       if (!ptr->member)
2896         continue;
2897       av[0] = ptr->member;
2898       av[1] = temp;
2899       if (ptr->type == (char *)GROUPS)
2900         {
2901           ptr->type = NULL;
2902           rc = mr_query("add_list_sid_by_name", 2, av, NULL, NULL);
2903         }
2904       else if (ptr->type == (char *)USERS)
2905         {
2906           ptr->type = NULL;
2907           rc = mr_query("add_user_sid_by_login", 2, av, NULL, NULL);
2908         }
2909       ptr = ptr->next;
2910     }
2911   return(0);
2912 }
2913
2914 void convert_b_to_a(char *string, UCHAR *binary, int length)
2915 {
2916   int   i;
2917   int   j;
2918   UCHAR tmp;
2919
2920   j = 0;
2921   for (i = 0; i < length; i++)
2922     {
2923       tmp = binary[i];
2924       string[j] = tmp;
2925       string[j] >>= 4;
2926       string[j] &= 0x0f;
2927       string[j] += 0x30;
2928       if (string[j] > '9')
2929         string[j] += 0x27;
2930       ++j;
2931       string[j] = tmp & 0x0f;
2932       string[j] += 0x30;
2933       if (string[j] > '9')
2934         string[j] += 0x27;
2935       j++;
2936     }
2937   string[j] = 0;
2938 }
2939
2940 static int illegalchars[] = {
2941   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
2942   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
2943   1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, /* SPACE - / */
2944   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 0 - ? */
2945   0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
2946   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* P - _ */
2947   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
2948   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
2949   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2950   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2951   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2952   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2953   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2954   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2955   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2956   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2957 };
2958
2959 int check_string(char *s)
2960 {
2961   char  character;
2962
2963   for (; *s; s++)
2964     {
2965       character = *s;
2966       if (isupper(character))
2967         character = tolower(character);
2968       if (illegalchars[(unsigned) character])
2969         return 0;
2970     }
2971   return 1;
2972 }
2973
2974 int mr_connect_cl(char *server, char *client, int version, int auth)
2975 {
2976   int   status;
2977   char  *motd;
2978   char  temp[128];
2979
2980   status = mr_connect(server);
2981   if (status)
2982     {
2983       com_err(whoami, status, "while connecting to Moira");
2984       return status;
2985     }
2986
2987   status = mr_motd(&motd);
2988   if (status)
2989     {
2990       mr_disconnect();
2991       com_err(whoami, status, "while checking server status");
2992       return status;
2993     }
2994   if (motd)
2995     {
2996       sprintf(temp, "The Moira server is currently unavailable: %s", motd);
2997       com_err(whoami, status, temp);
2998       mr_disconnect();
2999       return status;
3000     }
3001
3002   status = mr_version(version);
3003   if (status)
3004     {
3005       if (status == MR_UNKNOWN_PROC)
3006         {
3007           if (version > 2)
3008             status = MR_VERSION_HIGH;
3009           else
3010             status = MR_SUCCESS;
3011         }
3012
3013       if (status == MR_VERSION_HIGH)
3014         {
3015           com_err(whoami, 0, "Warning: This client is running newer code than the server.");
3016                   com_err(whoami, 0, "Some operations may not work.");
3017         }
3018       else if (status && status != MR_VERSION_LOW)
3019         {
3020           com_err(whoami, status, "while setting query version number.");
3021           mr_disconnect();
3022           return status;
3023         }
3024     }
3025
3026   if (auth)
3027     {
3028       status = mr_auth(client);
3029       if (status)
3030         {
3031           com_err(whoami, status, "while authenticating to Moira.");
3032           mr_disconnect();
3033           return status;
3034         }
3035     }
3036
3037   return MR_SUCCESS;
3038 }
3039
3040 void AfsToWinAfs(char* path, char* winPath)
3041 {
3042     char* pathPtr;
3043     char* winPathPtr;
3044     strcpy(winPath, WINAFS);
3045     pathPtr = path + strlen(AFS);
3046     winPathPtr = winPath + strlen(WINAFS);
3047
3048     while (*pathPtr)
3049     {
3050         if (*pathPtr == '/')
3051           *winPathPtr = '\\';
3052         else
3053           *winPathPtr = *pathPtr;
3054
3055         pathPtr++;
3056         winPathPtr++;
3057     }
3058 }
3059
3060 int make_new_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
3061                    char *group_name, char *group_ou, char *group_membership, 
3062                    int group_security_flag, int updateGroup)
3063 {
3064   char  *av[3];
3065   char  *call_args[7];
3066   int   rc;
3067
3068   av[0] = group_name;
3069   call_args[0] = (char *)ldap_handle;
3070   call_args[1] = dn_path;
3071   call_args[2] = group_name;
3072   call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
3073   call_args[4] = (char *)updateGroup;
3074   call_args[5] = MoiraId;
3075   call_args[6] = NULL;
3076   sid_base = NULL;
3077   sid_ptr = &sid_base;
3078   callback_rc = 0;
3079   if (rc = mr_query("get_list_info", 1, av, group_create, call_args))
3080     {
3081       moira_disconnect();
3082       com_err(whoami, 0, "Couldn't create list %s : %s", group_name, error_message(rc));
3083       return(rc);
3084     }
3085   if (callback_rc)
3086     {
3087       moira_disconnect();
3088       com_err(whoami, 0, "Couldn't create list %s", group_name);
3089       return(callback_rc);
3090     }
3091
3092   if (sid_base != NULL)
3093     {
3094       sid_update(ldap_handle, dn_path);
3095       linklist_free(sid_base);
3096       sid_base = NULL;
3097     }
3098   return(0);
3099 }
3100
3101 int populate_group(LDAP *ldap_handle, char *dn_path, char *group_name, 
3102                    char *group_ou, char *group_membership, 
3103                    int group_security_flag, char *MoiraId)
3104 {
3105   char      *av[3];
3106   char      *call_args[7];
3107   char      *pUserOu;
3108   LK_ENTRY  *ptr;
3109   int       rc;
3110
3111   com_err(whoami, 0, "Populating group %s", group_name);
3112   av[0] = group_name;
3113   call_args[0] = (char *)ldap_handle;
3114   call_args[1] = dn_path;
3115   call_args[2] = group_name;
3116   call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
3117   call_args[4] = NULL;
3118   member_base = NULL;
3119   if (rc = mr_query("get_end_members_of_list", 1, av,
3120                     member_list_build, call_args))
3121     {
3122       com_err(whoami, 0, "Couldn't populate list %s : %s", 
3123               group_name, error_message(rc));
3124       return(3);
3125     }
3126   if (member_base != NULL)
3127     {
3128       ptr = member_base;
3129       while (ptr != NULL)
3130         {
3131           if (!strcasecmp(ptr->type, "LIST"))
3132             {
3133               ptr = ptr->next;
3134               continue;
3135             }
3136           pUserOu = user_ou;
3137           if (!strcasecmp(ptr->type, "STRING"))
3138             {
3139               if (contact_create(ldap_handle, dn_path, ptr->member, contact_ou))
3140                 return(3);
3141               pUserOu = contact_ou;
3142             }
3143           else if (!strcasecmp(ptr->type, "KERBEROS"))
3144             {
3145               if (contact_create(ldap_handle, dn_path, ptr->member, kerberos_ou))
3146                 return(3);
3147               pUserOu = kerberos_ou;
3148             }
3149           rc = member_add(ldap_handle, dn_path, group_name,
3150                           group_ou, group_membership, ptr->member, 
3151                           pUserOu, MoiraId);
3152           ptr = ptr->next;
3153         }
3154       linklist_free(member_base);
3155       member_base = NULL;
3156     }
3157   return(0);
3158 }
3159
3160 int process_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
3161                   char *group_name, char *group_ou, char *group_membership, 
3162                   int group_security_flag, int type)
3163 {
3164   char      before_desc[512];
3165   char      before_name[256];
3166   char      before_group_ou[256];
3167   char      before_group_membership[2];
3168   char      distinguishedName[256];
3169   char      ad_distinguishedName[256];
3170   char      filter[128];
3171   char      *attr_array[3];
3172   int       before_security_flag;
3173   int       group_count;
3174   int       rc;
3175   LK_ENTRY  *group_base;
3176   LK_ENTRY  *ptr;
3177   char      ou_both[512];
3178   char      ou_security[512];
3179   char      ou_distribution[512];
3180   char      ou_neither[512];
3181
3182   memset(ad_distinguishedName, '\0', sizeof(ad_distinguishedName));
3183   sprintf(distinguishedName, "CN=%s,%s,%s", group_name, group_ou, dn_path);
3184
3185
3186   memset(filter, '\0', sizeof(filter));
3187   group_base = NULL;
3188   group_count = 0;
3189   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
3190                         "*", MoiraId, 
3191                         "distinguishedName", &group_base, 
3192                         &group_count, filter))
3193     return(rc);
3194
3195   if (type == CHECK_GROUPS)
3196     {
3197       if (group_count == 1)
3198         {
3199           if (!strcasecmp(group_base->value, distinguishedName))
3200             {
3201               linklist_free(group_base);
3202               return(0);
3203             }
3204         }
3205       linklist_free(group_base);
3206       if (group_count == 0)
3207         return(AD_NO_GROUPS_FOUND);
3208       if (group_count == 1)
3209         return(AD_WRONG_GROUP_DN_FOUND);
3210       return(AD_MULTIPLE_GROUPS_FOUND);
3211     }
3212   if (group_count == 0)
3213     {
3214       return(AD_NO_GROUPS_FOUND);
3215     }
3216   if (group_count > 1)
3217     {
3218       ptr = group_base;
3219       while (ptr != NULL)
3220         {
3221           if (!strcasecmp(distinguishedName, ptr->value))
3222             break;
3223           ptr = ptr->next;
3224         }
3225       if (ptr == NULL)
3226         {
3227           com_err(whoami, 0, "%d groups with moira id = %s", group_count, MoiraId);
3228           ptr = group_base;
3229           while (ptr != NULL)
3230             {
3231               com_err(whoami, 0, "%s with moira id = %s", ptr->value, MoiraId);
3232               ptr = ptr->next;
3233             }
3234           linklist_free(group_base);
3235           return(AD_MULTIPLE_GROUPS_FOUND);
3236         } 
3237       ptr = group_base;
3238       while (ptr != NULL)
3239         {
3240           if (strcasecmp(distinguishedName, ptr->value))
3241             rc = ldap_delete_s(ldap_handle, ptr->value);
3242           ptr = ptr->next;
3243         }
3244       linklist_free(group_base);
3245       memset(filter, '\0', sizeof(filter));
3246       group_base = NULL;
3247       group_count = 0;
3248       if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
3249                             "*", MoiraId, 
3250                             "distinguishedName", &group_base, 
3251                             &group_count, filter))
3252         return(rc);
3253       if (group_count == 0)
3254         return(AD_NO_GROUPS_FOUND);
3255       if (group_count > 1)
3256         return(AD_MULTIPLE_GROUPS_FOUND);
3257     }
3258
3259   strcpy(ad_distinguishedName, group_base->value);
3260   linklist_free(group_base);
3261   group_base = NULL;
3262   group_count = 0;
3263
3264   attr_array[0] = "sAMAccountName";
3265   attr_array[1] = NULL;
3266   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3267                            &group_base, &group_count)) != 0)
3268     {
3269       com_err(whoami, 0, "LDAP server unable to get list info with MoiraId = %s: %s",
3270                MoiraId, ldap_err2string(rc));
3271       return(rc);
3272     }
3273   sprintf(filter, "(sAMAccountName=%s)", group_base->value);
3274
3275   if (!strcasecmp(ad_distinguishedName, distinguishedName))
3276     {
3277       linklist_free(group_base);
3278       group_base = NULL;
3279       group_count = 0;
3280       return(0);
3281     }
3282   linklist_free(group_base);
3283   group_base = NULL;
3284   group_count = 0;
3285   memset(ou_both, '\0', sizeof(ou_both));
3286   memset(ou_security, '\0', sizeof(ou_security));
3287   memset(ou_distribution, '\0', sizeof(ou_distribution));
3288   memset(ou_neither, '\0', sizeof(ou_neither));
3289   memset(before_name, '\0', sizeof(before_name));
3290   memset(before_desc, '\0', sizeof(before_desc));
3291   memset(before_group_membership, '\0', sizeof(before_group_membership));
3292   attr_array[0] = "name";
3293   attr_array[1] = NULL;
3294   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3295                            &group_base, &group_count)) != 0)
3296     {
3297       com_err(whoami, 0, "LDAP server unable to get list name with MoiraId = %s: %s",
3298               MoiraId, ldap_err2string(rc));
3299       return(rc);
3300     }
3301   strcpy(before_name, group_base->value);
3302   linklist_free(group_base);
3303   group_base = NULL;
3304   group_count = 0;
3305   attr_array[0] = "description";
3306   attr_array[1] = NULL;
3307   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3308                            &group_base, &group_count)) != 0)
3309     {
3310       com_err(whoami, 0, 
3311               "LDAP server unable to get list description with MoiraId = %s: %s",
3312               MoiraId, ldap_err2string(rc));
3313       return(rc);
3314     }
3315   strcpy(before_desc, group_base->value);
3316   linklist_free(group_base);
3317   group_base = NULL;
3318   group_count = 0;
3319   change_to_lower_case(ad_distinguishedName);  
3320   strcpy(ou_both, group_ou_both);
3321   change_to_lower_case(ou_both);
3322   strcpy(ou_security, group_ou_security);
3323   change_to_lower_case(ou_security);
3324   strcpy(ou_distribution, group_ou_distribution);
3325   change_to_lower_case(ou_distribution);
3326   strcpy(ou_neither, group_ou_neither);
3327   change_to_lower_case(ou_neither);
3328   if (strstr(ad_distinguishedName, ou_both))
3329     {
3330       strcpy(before_group_ou, group_ou_both);
3331       before_group_membership[0] = 'B';
3332       before_security_flag = 1;
3333     }
3334   else if (strstr(ad_distinguishedName, ou_security))
3335     {
3336       strcpy(before_group_ou, group_ou_security);
3337       before_group_membership[0] = 'S';
3338       before_security_flag = 1;
3339     }
3340   else if (strstr(ad_distinguishedName, ou_distribution))
3341     {
3342       strcpy(before_group_ou, group_ou_distribution);
3343       before_group_membership[0] = 'D';
3344       before_security_flag = 0;
3345     }
3346   else if (strstr(ad_distinguishedName, ou_neither))
3347     {
3348       strcpy(before_group_ou, group_ou_neither);
3349       before_group_membership[0] = 'N';
3350       before_security_flag = 0;
3351     }
3352   else
3353     return(AD_NO_OU_FOUND);
3354   rc = group_rename(ldap_handle, dn_path, before_name, before_group_membership, 
3355                     before_group_ou, before_security_flag, before_desc,
3356                     group_name, group_membership, group_ou, group_security_flag,
3357                     before_desc, MoiraId, filter);
3358   return(rc);
3359 }
3360
3361 void change_to_lower_case(char *ptr)
3362 {
3363   int i;
3364
3365   for (i = 0; i < (int)strlen(ptr); i++)
3366     {
3367       ptr[i] = tolower(ptr[i]);
3368     }
3369 }
3370
3371 int ad_get_group(LDAP *ldap_handle, char *dn_path, 
3372                  char *group_name, char *group_membership, 
3373                  char *MoiraId, char *attribute,
3374                  LK_ENTRY **linklist_base, int *linklist_count,
3375                  char *rFilter)
3376 {
3377   char      filter[128];
3378   char      *attr_array[3];
3379   int   rc;
3380
3381   (*linklist_base) = NULL;
3382   (*linklist_count) = 0;
3383   if (strlen(rFilter) != 0)
3384     {
3385       strcpy(filter, rFilter);
3386       attr_array[0] = attribute;
3387       attr_array[1] = NULL;
3388       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3389                                linklist_base, linklist_count)) != 0)
3390         {
3391           com_err(whoami, 0, "LDAP server unable to get list info with MoiraId = %s: %s",
3392                   MoiraId, ldap_err2string(rc));
3393          return(rc);
3394        }
3395     if ((*linklist_count) == 1)
3396       {
3397         strcpy(rFilter, filter);
3398         return(0);
3399       }
3400     }
3401
3402   linklist_free((*linklist_base));
3403   (*linklist_base) = NULL;
3404   (*linklist_count) = 0;
3405   if (strlen(MoiraId) != 0)
3406     {
3407       sprintf(filter, "(mitMoiraId=%s)", MoiraId);
3408       attr_array[0] = attribute;
3409       attr_array[1] = NULL;
3410       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3411                                linklist_base, linklist_count)) != 0)
3412         {
3413           com_err(whoami, 0, "LDAP server unable to get list info with MoiraId = %s: %s",
3414                   MoiraId, ldap_err2string(rc));
3415          return(rc);
3416        }
3417     }
3418   if ((*linklist_count) == 1)
3419     {
3420       strcpy(rFilter, filter);
3421       return(0);
3422     }
3423
3424   linklist_free((*linklist_base));
3425   (*linklist_base) = NULL;
3426   (*linklist_count) = 0;
3427   sprintf(filter, "(sAMAccountName=%s_group)", group_name);
3428   attr_array[0] = attribute;
3429   attr_array[1] = NULL;
3430   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3431                            linklist_base, linklist_count)) != 0)
3432     {
3433       com_err(whoami, 0, "LDAP server unable to get list info with MoiraId = %s: %s",
3434               MoiraId, ldap_err2string(rc));
3435       return(rc);
3436     }
3437   if ((*linklist_count) == 1)
3438     {
3439       strcpy(rFilter, filter);
3440       return(0);
3441     }
3442
3443   linklist_free((*linklist_base));
3444   (*linklist_base) = NULL;
3445   (*linklist_count) = 0;
3446   sprintf(filter, "(sAMAccountName=%s_zZx%c)", group_name, group_membership[0]);
3447   attr_array[0] = attribute;
3448   attr_array[1] = NULL;
3449   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3450                            linklist_base, linklist_count)) != 0)
3451     {
3452       com_err(whoami, 0, "LDAP server unable to get list info with MoiraId = %s: %s",
3453               MoiraId, ldap_err2string(rc));
3454       return(rc);
3455     }
3456   if ((*linklist_count) == 1)
3457       strcpy(rFilter, filter);
3458   return(0);
3459 }
3460
3461 int check_user(LDAP *ldap_handle, char *dn_path, char *UserName, char *MoiraId)
3462 {
3463   char filter[128];
3464   char *attr_array[3];
3465   char SamAccountName[64];
3466   int  group_count;
3467   int  rc;
3468   LK_ENTRY  *group_base;
3469
3470   group_count = 0;
3471   group_base = NULL;
3472
3473   if (strlen(MoiraId) != 0)
3474     {
3475       sprintf(filter, "(mitMoiraId=%s)", MoiraId);
3476       attr_array[0] = "sAMAccountName";
3477       attr_array[1] = NULL;
3478       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3479                                &group_base, &group_count)) != 0)
3480         {
3481           com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
3482                   UserName, ldap_err2string(rc));
3483           return(rc);
3484         }
3485     }
3486   if (group_count == 0)
3487     {
3488       sprintf(filter, "(sAMAccountName=%s)", UserName);
3489       attr_array[0] = "sAMAccountName";
3490       attr_array[1] = NULL;
3491       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3492                                &group_base, &group_count)) != 0)
3493         {
3494           com_err(whoami, 0, "LDAP server couldn't process user %s : %s",
3495                   UserName, ldap_err2string(rc));
3496           return(rc);
3497         }
3498     }
3499
3500   if (group_count != 1)
3501     {
3502       linklist_free(group_base);
3503       return(AD_NO_USER_FOUND);
3504     }
3505   strcpy(SamAccountName, group_base->value);
3506   linklist_free(group_base);
3507   group_count = 0;
3508   rc = 0;
3509   if (strcmp(SamAccountName, UserName))
3510     {
3511       rc = user_rename(ldap_handle, dn_path, SamAccountName, 
3512                        UserName);
3513     }
3514   return(0);
3515 }
This page took 0.318925 seconds and 3 git commands to generate.