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