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