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