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