]> andersk Git - moira.git/blob - incremental/winad/winad.c
Filter out things that aren't valid MIT IDs.
[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  PathToHomeDir PathToProfileDir username 45206 /bin/cmd cmd Last First Middle 1 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
10  * users 11 11 #45206 45206 /bin/cmd cmd Last First Middle 0 950000001 STAFF 121058  PathToHomeDir PathToProfileDir newuser 45206 /bin/cmd cmd Last First Middle 2 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
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  PathToHomeDir PathToProfileDir username 45206 /bin/cmd cmd Last First Middle 3 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
15  * users 11 11 username 45206 /bin/cmd cmd Last First Middle 2 950000001 STAFF 121058  PathToHomeDir PathToProfileDir username 45206 /bin/cmd cmd Last First Middle 3 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
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 PathToHomeDir PathToProfileDir newusername 45206 /bin/cmd cmd Last First Middle 1 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
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 8 machines/test/bottom description location contact USER 105316 2222 [none]
85  *
86  * arguments when moira deletes a container (OU).
87  * containers 8 0 machines/test/bottom description location contact USER 105316 2222 groupname
88  *
89  * arguments when moira modifies a container information (OU).
90  * containers 8 8 machines/test/bottom description location contact USER 105316 2222 groupname machines/test/bottom description1 location contact USER 105316 2222 groupname
91  *
92  * arguments when moira adds a machine from an OU
93  * table name, beforec, afterc, machine_name, container_name, mach_id, cnt_id
94  * mcntmap 0 5 DAVIDT.MIT.EDU dttest/dttest1 76767 46 groupname
95  *
96  * arguments when moira removes a machine from an OU
97  * table name, beforec, afterc, machine_name, container_name, mach_id, cnt_id
98  * mcntmap 0 5 DAVIDT.MIT.EDU dttest/dttest1 76767 46 groupname
99  *
100 */
101 #include <mit-copyright.h>
102 #ifdef _WIN32
103 #include <winsock2.h>
104 #include <windows.h>
105 #include <stdlib.h>
106 #include <malloc.h>
107 #include <lmaccess.h>
108 #endif
109 #include <hesiod.h>
110 #include <string.h>
111 #include <ldap.h>
112 #include <stdio.h>
113 #include <moira.h>
114 #include <moira_site.h>
115 #include <mrclient.h>
116 #include <krb5.h>
117 #include <krb.h>
118 #include <gsssasl.h>
119 #include <gssldap.h>
120 #include "kpasswd.h"
121
122 #ifdef _WIN32
123 #ifndef ECONNABORTED
124 #define ECONNABORTED WSAECONNABORTED
125 #endif
126 #ifndef ECONNREFUSED
127 #define ECONNREFUSED WSAECONNREFUSED
128 #endif
129 #ifndef EHOSTUNREACH
130 #define EHOSTUNREACH WSAEHOSTUNREACH
131 #endif
132 #define krb5_xfree free
133 #define F_OK 0
134 #define sleep(A) Sleep(A * 1000);
135 #endif /* _WIN32 */
136
137 #ifndef _WIN32
138 #include <sys/types.h>
139 #include <netinet/in.h>
140 #include <arpa/nameser.h>
141 #include <resolv.h>
142 #include <sys/utsname.h>
143 #include <unistd.h>
144
145 #define WINADCFG "/moira/winad/winad.cfg"
146 #define strnicmp(A,B,C) strncasecmp(A,B,C)
147 #define UCHAR unsigned char
148
149 #define UF_SCRIPT               0x0001
150 #define UF_ACCOUNTDISABLE       0x0002
151 #define UF_HOMEDIR_REQUIRED     0x0008
152 #define UF_LOCKOUT              0x0010
153 #define UF_PASSWD_NOTREQD       0x0020
154 #define UF_PASSWD_CANT_CHANGE   0x0040
155 #define UF_DONT_EXPIRE_PASSWD   0x10000
156
157 #define UF_TEMP_DUPLICATE_ACCOUNT       0x0100
158 #define UF_NORMAL_ACCOUNT               0x0200
159 #define UF_INTERDOMAIN_TRUST_ACCOUNT    0x0800
160 #define UF_WORKSTATION_TRUST_ACCOUNT    0x1000
161 #define UF_SERVER_TRUST_ACCOUNT         0x2000
162
163 #define OWNER_SECURITY_INFORMATION       (0x00000001L)
164 #define GROUP_SECURITY_INFORMATION       (0x00000002L)
165 #define DACL_SECURITY_INFORMATION        (0x00000004L)
166 #define SACL_SECURITY_INFORMATION        (0x00000008L)
167
168 #ifndef BYTE
169 #define BYTE unsigned char
170 #endif
171 typedef unsigned int DWORD;
172 typedef unsigned long ULONG;
173
174 typedef struct _GUID
175 {
176   unsigned long Data1;
177   unsigned short Data2;
178   unsigned short Data3;
179   unsigned char Data4[8];
180 } GUID;
181
182 typedef struct _SID_IDENTIFIER_AUTHORITY { 
183   BYTE Value[6]; 
184 } SID_IDENTIFIER_AUTHORITY, *PSID_IDENTIFIER_AUTHORITY; 
185
186 typedef struct _SID {
187   BYTE  Revision;
188   BYTE  SubAuthorityCount;
189   SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
190   DWORD SubAuthority[512];
191 } SID;
192 #endif/*!WIN32*/
193
194 #ifndef WINADCFG
195 #define WINADCFG "winad.cfg"
196 #endif
197
198 #define AFS "/afs/"
199 #define WINAFS "\\\\afs\\all\\"
200
201 #define ADS_GROUP_TYPE_GLOBAL_GROUP         0x00000002
202 #define ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP   0x00000004
203 #define ADS_GROUP_TYPE_LOCAL_GROUP          0x00000004
204 #define ADS_GROUP_TYPE_UNIVERSAL_GROUP      0x00000008
205 #define ADS_GROUP_TYPE_SECURITY_ENABLED     0x80000000
206
207 #define QUERY_VERSION -1
208 #define PRIMARY_REALM "ATHENA.MIT.EDU"
209
210 #define SUBSTITUTE  1
211 #define REPLACE     2
212
213 #define USERS         0
214 #define GROUPS        1
215
216 #define MEMBER_ADD          1
217 #define MEMBER_REMOVE       2
218 #define MEMBER_CHANGE_NAME  3
219 #define MEMBER_ACTIVATE     4
220 #define MEMBER_DEACTIVATE   5
221 #define MEMBER_CREATE       6
222
223 #define MOIRA_ALL       0x0
224 #define MOIRA_USERS     0x1
225 #define MOIRA_KERBEROS  0x2
226 #define MOIRA_STRINGS   0x4
227 #define MOIRA_LISTS     0x8
228
229 #define CHECK_GROUPS    1
230 #define CLEANUP_GROUPS  2
231
232 #define AD_NO_GROUPS_FOUND        -1
233 #define AD_WRONG_GROUP_DN_FOUND   -2
234 #define AD_MULTIPLE_GROUPS_FOUND  -3
235 #define AD_INVALID_NAME           -4
236 #define AD_LDAP_FAILURE           -5
237 #define AD_INVALID_FILESYS        -6
238 #define AD_NO_ATTRIBUTE_FOUND     -7
239 #define AD_NO_OU_FOUND            -8
240 #define AD_NO_USER_FOUND          -9
241
242 /* container arguments */
243 #define CONTAINER_NAME       0
244 #define CONTAINER_DESC       1
245 #define CONTAINER_LOCATION   2
246 #define CONTAINER_CONTACT    3
247 #define CONTAINER_TYPE       4
248 #define CONTAINER_ID         5
249 #define CONTAINER_ROWID      6
250 #define CONTAINER_GROUP_NAME 7
251
252 /*mcntmap arguments*/
253 #define OU_MACHINE_NAME        0
254 #define OU_CONTAINER_NAME      1
255 #define OU_MACHINE_ID          2
256 #define OU_CONTAINER_ID        3
257 #define OU_CONTAINER_GROUP     4
258
259 typedef struct lk_entry {
260   int     op;
261   int     length;
262   int     ber_value;
263   char    *dn;
264   char    *attribute;
265   char    *value;
266   char    *member;
267   char    *type;
268   char    *list;
269   struct  lk_entry *next;
270 } LK_ENTRY;
271
272 #define STOP_FILE "/moira/winad/nowinad"
273 #define file_exists(file) (access((file), F_OK) == 0)
274
275 #define N_SD_BER_BYTES   5
276 #define LDAP_BERVAL struct berval
277 #define MAX_SERVER_NAMES 32
278
279 #define HIDDEN_GROUP                "HiddenGroup.g"
280 #define HIDDEN_GROUP_WITH_ADMIN     "HiddenGroupWithAdmin.g"
281 #define NOT_HIDDEN_GROUP            "NotHiddenGroup.g"
282 #define NOT_HIDDEN_GROUP_WITH_ADMIN "NotHiddenGroupWithAdmin.g"
283
284 #define ADD_ATTR(t, v, o)               \
285   mods[n] = malloc(sizeof(LDAPMod));    \
286   mods[n]->mod_op = o;  \
287   mods[n]->mod_type = t;                \
288   mods[n++]->mod_values = v
289
290 #define DEL_ATTR(t, o)          \
291   DelMods[i] = malloc(sizeof(LDAPMod)); \
292   DelMods[i]->mod_op = o;       \
293   DelMods[i]->mod_type = t;             \
294   DelMods[i++]->mod_values = NULL
295
296 #define DOMAIN_SUFFIX   "MIT.EDU"
297 #define DOMAIN  "DOMAIN: "
298 #define SERVER  "SERVER: "
299 #define MSSFU   "SFU: "
300 #define SFUTYPE "30"
301
302 LK_ENTRY *member_base = NULL;
303 LK_ENTRY *sid_base = NULL;
304 LK_ENTRY **sid_ptr = NULL;
305 static char tbl_buf[1024];
306 char  kerberos_ou[] = "OU=kerberos,OU=moira";
307 char  contact_ou[] = "OU=strings,OU=moira";
308 char  user_ou[] = "OU=users,OU=moira";
309 char  group_ou_distribution[] = "OU=mail,OU=lists,OU=moira";
310 char  group_ou_root[] = "OU=lists,OU=moira";
311 char  group_ou_security[] = "OU=group,OU=lists,OU=moira";
312 char  group_ou_neither[] = "OU=special,OU=lists,OU=moira";
313 char  group_ou_both[] = "OU=mail,OU=group,OU=lists,OU=moira";
314 char  orphans_machines_ou[] = "OU=Machines,OU=Orphans";
315 char  orphans_other_ou[] = "OU=Other,OU=Orphans";
316 char  security_template_ou[] = "OU=security_templates";
317 char *whoami;
318 char ldap_domain[256];
319 char *ServerList[MAX_SERVER_NAMES];
320 int  mr_connections = 0;
321 int  callback_rc;
322 char default_server[256];
323 static char tbl_buf[1024];
324 int  UseSFU30 = 0;
325
326 extern int set_password(char *user, char *password, char *domain);
327
328 int ad_get_group(LDAP *ldap_handle, char *dn_path, char *group_name, 
329                 char *group_membership, char *MoiraId, char *attribute,
330                 LK_ENTRY **linklist_base, int *linklist_count,
331               char *rFilter);
332 void AfsToWinAfs(char* path, char* winPath);
333 int ad_connect(LDAP **ldap_handle, char *ldap_domain, char *dn_path, 
334                char *Win2kPassword, char *Win2kUser, char *default_server,
335                int connect_to_kdc, char **ServerList, int *IgnoreMasterSeverError);
336 void ad_kdc_disconnect();
337 int attribute_update(LDAP *ldap_handle, char *distinguished_name, 
338                       char *attribute_value, char *attribute, char *user_name);
339 int BEREncodeSecurityBits(ULONG uBits, char *pBuffer);
340 int checkADname(LDAP *ldap_handle, char *dn_path, char *Name);
341 void check_winad(void);
342 int check_user(LDAP *ldap_handle, char *dn_path, char *UserName, char *MoiraId);
343 /* containers */
344 int container_adupdate(LDAP *ldap_handle, char *dn_path, char *dName, 
345                        char *distinguishedName, int count, char **av);
346 void container_check(LDAP *ldap_handle, char *dn_path, char *name);
347 int container_create(LDAP *ldap_handle, char *dn_path, int count, char **av);
348 int container_delete(LDAP *ldap_handle, char *dn_path, int count, char **av);
349 int container_get_distinguishedName(LDAP *ldap_handle, char *dn_path, 
350                                      char *distinguishedName, int count, char **av);
351 void container_get_dn(char *src, char *dest);
352 void container_get_name(char *src, char *dest);
353 int container_move_objects(LDAP *ldap_handle, char *dn_path, char *dName);
354 int container_rename(LDAP *ldap_handle, char *dn_path, int beforec, char **before, 
355                      int afterc, char **after);
356 int container_update(LDAP *ldap_handle, char *dn_path, int beforec, char **before,
357                      int afterc, char **after);
358
359 int filesys_process(LDAP *ldap_handle, char *dn_path, char *fs_name, 
360                     char *fs_type, char *fs_pack, int operation);
361 int GetAceInfo(int ac, char **av, void *ptr);
362 int GetServerList(char *ldap_domain, char **MasterServe);
363 int get_group_membership(char *group_membership, char *group_ou, 
364                          int *security_flag, char **av);
365 int get_machine_ou(LDAP *ldap_handle, char *dn_path, char *member, char *machine_ou, char *pPtr);
366 int Moira_container_group_create(char **after);
367 int Moira_container_group_delete(char **before);
368 int Moira_groupname_create(char *GroupName, char *ContainerName,
369                            char *ContainerRowID);
370 int Moira_container_group_update(char **before, char **after);
371 int Moira_process_machine_container_group(char *MachineName, char* groupName,
372                                           int DeleteMachine);
373 int Moira_addGroupToParent(char *origContainerName, char *GroupName);
374 int Moira_getContainerGroup(int ac, char **av, void *ptr);
375 int Moira_getGroupName(char *origContainerName, char *GroupName,
376                        int ParentFlag);
377 int Moira_setContainerGroup(char *ContainerName, char *GroupName);
378 int ProcessAce(LDAP *ldap_handle, char *dn_path, char *group_name, char *Type,
379                int UpdateGroup, int *ProcessGroup);
380 int process_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
381                   char *group_name, char *group_ou, char *group_membership, 
382                   int group_security_flag, int type);
383 int process_lists(int ac, char **av, void *ptr);
384 int ProcessGroupSecurity(LDAP *ldap_handle, char *dn_path, char *TargetGroupName, 
385                          int HiddenGroup, char *AceType, char *AceName);
386 int ProcessMachineName(int ac, char **av, void *ptr);
387 int user_create(int ac, char **av, void *ptr);
388 int user_change_status(LDAP *ldap_handle, char *dn_path, 
389                        char *user_name, char *MoiraId, int operation);
390 int user_delete(LDAP *ldap_handle, char *dn_path, 
391                 char *u_name, char *MoiraId);
392 int user_rename(LDAP *ldap_handle, char *dn_path, char *before_user_name, 
393                 char *user_name);
394 int user_update(LDAP *ldap_handle, char *dn_path, char *user_name,
395                 char *uid, char *MitId, char *MoiraId, int State,
396                 char *WinHomeDir, char *WinProfileDir);
397 void change_to_lower_case(char *ptr);
398 int contact_create(LDAP *ld, char *bind_path, char *user, char *group_ou);
399 int group_create(int ac, char **av, void *ptr);
400 int group_delete(LDAP *ldap_handle, char *dn_path, 
401                  char *group_name, char *group_membership, char *MoiraId);
402 int group_rename(LDAP *ldap_handle, char *dn_path, 
403                  char *before_group_name, char *before_group_membership, 
404                  char *before_group_ou, int before_security_flag, char *before_desc,
405                  char *after_group_name, char *after_group_membership, 
406                  char *after_group_ou, int after_security_flag, char *after_desc,
407                  char *MoiraId, char *filter);
408 int machine_check(LDAP *ldap_handle, char *dn_path, char *machine_name);
409 int machine_GetMoiraContainer(int ac, char **av, void *ptr);
410 int machine_get_moira_container(LDAP *ldap_handle, char *dn_path, char *machine_name, char *container_name);
411 int machine_move_to_ou(LDAP *ldap_handle, char *dn_path, char *MoiraMachineName, char *DestinationOu);
412 int make_new_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
413                    char *group_name, char *group_ou, char *group_membership, 
414                    int group_security_flag, int updateGroup);
415 int member_list_build(int ac, char **av, void *ptr);
416 int member_add(LDAP *ldap_handle, char *dn_path, char *group_name, 
417                         char *group_ou, char *group_membership, 
418                         char *user_name, char *pUserOu, char *MoiraId);
419 int member_remove(LDAP *ldap_handle, char *dn_path, char *group_name, 
420                   char *group_ou, char *group_membership, char *user_name,
421                   char *pUserOu, char *MoiraId);
422 int populate_group(LDAP *ldap_handle, char *dn_path, char *group_name, 
423                    char *group_ou, char *group_membership, 
424                    int group_security_flag, char *MoiraId);
425 int SetHomeDirectory(LDAP *ldap_handle, char *user_name, char *DistinguishedName,
426                      char *WinHomeDir, char *WinProfileDir,
427                      char **homedir_v, char **winProfile_v,
428                      char **drives_v, LDAPMod **mods, 
429                      int OpType, int n);
430 int sid_update(LDAP *ldap_handle, char *dn_path);
431 void SwitchSFU(LDAPMod **mods, int *UseSFU30, int n);
432 int check_string(char *s);
433 int check_container_name(char* s);
434 void convert_b_to_a(char *string, UCHAR *binary, int length);
435 int mr_connect_cl(char *server, char *client, int version, int auth);
436
437 void do_container(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
438              char **before, int beforec, char **after, int afterc);
439 void do_filesys(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
440              char **before, int beforec, char **after, int afterc);
441 void do_list(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
442              char **before, int beforec, char **after, int afterc);
443 void do_user(LDAP *ldap_handle, char *dn_path, char *ldap_hostname, 
444              char **before, int beforec, char **after, int afterc);
445 void do_member(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
446                char **before, int beforec, char **after, int afterc);
447 void do_mcntmap(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
448                 char **before, int beforec, char **after, int afterc);
449 int linklist_create_entry(char *attribute, char *value,
450                           LK_ENTRY **linklist_entry);
451 int linklist_build(LDAP *ldap_handle, char *dn_path, char *search_exp, 
452                    char **attr_array, LK_ENTRY **linklist_base, 
453                    int *linklist_count, unsigned long ScopeType);
454 void linklist_free(LK_ENTRY *linklist_base);
455
456 int retrieve_attributes(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
457                         char *distinguished_name, LK_ENTRY **linklist_current);
458 int retrieve_entries(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
459                      LK_ENTRY **linklist_base, int *linklist_count);
460 int retrieve_values(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
461                     char *Attribute, char *distinguished_name, 
462                     LK_ENTRY **linklist_current);
463
464 int construct_newvalues(LK_ENTRY *linklist_base, int modvalue_count, 
465                         char *oldValue, char *newValue,
466                         char ***modvalues, int type);
467 void free_values(char **modvalues);
468
469 int convert_domain_to_dn(char *domain, char **bind_path);
470 void get_distinguished_name(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
471                             char *distinguished_name);
472 int moira_disconnect(void);
473 int moira_connect(void);
474 void print_to_screen(const char *fmt, ...);
475 int GetMachineName(char *MachineName);
476
477 int main(int argc, char **argv)
478 {
479   unsigned long   rc;
480   int             beforec;
481   int             afterc;
482   int             i;
483   int             j;
484   int             Count;
485   int             k;
486   int             OldUseSFU30;
487   int             IgnoreServerListError;
488   char            *table;
489   char            **before;
490   char            **after;
491   LDAP            *ldap_handle;
492   FILE            *fptr;
493   char            dn_path[256];
494   char            temp[32];
495
496   whoami = ((whoami = (char *)strrchr(argv[0], '/')) ? whoami+1 : argv[0]);
497
498   if (argc < 4)
499     {
500       com_err(whoami, 0, "Unable to process %s", "argc < 4");
501       exit(1);
502     }
503   beforec = atoi(argv[2]);
504   afterc = atoi(argv[3]);
505
506   if (argc < (4 + beforec + afterc))
507     {
508       com_err(whoami, 0, "Unable to process %s", "argc < (4 + breforec + afterc)");
509       exit(1);
510     }
511
512   table = argv[1];
513   before = &argv[4];
514   after = &argv[4 + beforec];
515
516   if (afterc == 0)
517     after = NULL;
518   if (beforec == 0)
519     before = NULL;
520
521   for (i = 1; i < argc; i++)
522     {
523       strcat(tbl_buf, argv[i]);
524       strcat(tbl_buf, " ");
525     }
526   com_err(whoami, 0, "%s", tbl_buf);
527
528   check_winad();
529
530   memset(ldap_domain, '\0', sizeof(ldap_domain));
531   memset(ServerList, '\0', sizeof(ServerList[0]) * MAX_SERVER_NAMES);
532   memset(temp, '\0', sizeof(temp));
533   UseSFU30 = 0;
534   OldUseSFU30 = 0;
535   Count = 0;
536
537   if ((fptr = fopen(WINADCFG, "r")) != NULL)
538     {
539       while (fgets(temp, sizeof(temp), fptr) != 0)
540         {
541           for (i = 0; i < (int)strlen(temp); i++)
542               temp[i] = toupper(temp[i]);
543           if (temp[strlen(temp) - 1] == '\n')
544               temp[strlen(temp) - 1] = '\0';
545           if (!strncmp(temp, DOMAIN, strlen(DOMAIN)))
546             {
547               if (strlen(temp) > (strlen(DOMAIN)))
548                 {
549                   strcpy(ldap_domain, &temp[strlen(DOMAIN)]);
550                 }
551             }
552           else if (!strncmp(temp, SERVER, strlen(SERVER)))
553             {
554               if (strlen(temp) > (strlen(SERVER)))
555                 {
556                   ServerList[Count] = calloc(1, 256);
557                   strcpy(ServerList[Count], &temp[strlen(SERVER)]);
558                   ++Count;
559                 }
560             }
561           else if (!strncmp(temp, MSSFU, strlen(MSSFU)))
562             {
563               if (strlen(temp) > (strlen(MSSFU)))
564                 {
565                   if (!strcmp(&temp[strlen(MSSFU)], SFUTYPE))
566                       UseSFU30 = 1;
567                 }
568             }
569           else
570             {
571               strcpy(ldap_domain, temp);
572             }
573         }
574       fclose(fptr);
575     }
576
577   if (strlen(ldap_domain) == 0)
578     strcpy(ldap_domain, "win.mit.edu");
579   /* zero trailing newline, if there is one. */
580   if (ldap_domain[strlen(ldap_domain) - 1] == '\n')
581     ldap_domain[strlen(ldap_domain) - 1] = '\0';
582
583   initialize_sms_error_table();
584   initialize_krb_error_table();
585
586   IgnoreServerListError = 0;
587   if (ServerList[0] == NULL)
588     {
589       IgnoreServerListError = 1;
590       GetServerList(ldap_domain, ServerList);
591     }
592   for (i = 0; i < MAX_SERVER_NAMES; i++)
593     {
594       if (ServerList[i] != 0)
595         {
596           if (ServerList[i][strlen(ServerList[i]) - 1] == '\n')
597                 ServerList[i][strlen(ServerList[i]) - 1] = '\0';
598           strcat(ServerList[i], ".");
599           strcat(ServerList[i], ldap_domain);
600           for (k = 0; k < (int)strlen(ServerList[i]); k++)
601               ServerList[i][k] = toupper(ServerList[i][k]);
602         }
603     }
604
605   memset(default_server, '\0', sizeof(default_server));
606   memset(dn_path, '\0', sizeof(dn_path));
607   for (i = 0; i < 5; i++)
608     {
609       if (!(rc = ad_connect(&ldap_handle, ldap_domain, dn_path, "", "", 
610                             default_server, 1, ServerList, &IgnoreServerListError)))
611          break;
612       if (IgnoreServerListError < 0)
613         {
614           GetServerList(ldap_domain, ServerList);
615           for (j = 0; j < MAX_SERVER_NAMES; j++)
616             {
617               if (ServerList[j] != NULL)
618                 {
619                   if (ServerList[j][strlen(ServerList[j]) - 1] == '\n')
620                         ServerList[j][strlen(ServerList[j]) - 1] = '\0';
621                   strcat(ServerList[j], ".");
622                   strcat(ServerList[j], ldap_domain);
623                   for (k = 0; k < (int)strlen(ServerList[j]); k++)
624                       ServerList[j][k] = toupper(ServerList[j][k]);
625                 }
626             }
627           IgnoreServerListError = 1;
628           --i;
629         }
630       sleep(2);
631     }
632   if (rc)
633     {
634           critical_alert("incremental", "winad.incr cannot connect to any server in domain %s", ldap_domain);
635       exit(1);
636     }
637
638   for (i = 0; i < (int)strlen(table); i++)
639     table[i] = tolower(table[i]);
640
641   if (!strcmp(table, "users"))
642     do_user(ldap_handle, dn_path, ldap_domain, before, beforec, after,
643             afterc);
644   else if (!strcmp(table, "list"))
645     do_list(ldap_handle, dn_path, ldap_domain, before, beforec, after,
646             afterc);
647   else if (!strcmp(table, "imembers"))
648     do_member(ldap_handle, dn_path, ldap_domain, before, beforec, after,
649               afterc);
650   else if (!strcmp(table, "filesys"))
651     do_filesys(ldap_handle, dn_path, ldap_domain, before, beforec, after,
652                afterc);
653   else if (!strcmp(table, "containers"))
654     do_container(ldap_handle, dn_path, ldap_domain, before, beforec, after,
655                  afterc);
656   else if (!strcmp(table, "mcntmap"))
657     do_mcntmap(ldap_handle, dn_path, ldap_domain, before, beforec, after,
658                afterc);
659   if (OldUseSFU30 != UseSFU30)
660     {
661       GetServerList(ldap_domain, ServerList);
662     }
663   ad_kdc_disconnect();
664   for (i = 0; i < MAX_SERVER_NAMES; i++)
665     {
666       if (ServerList[i] != NULL)
667         {
668           free(ServerList[i]);
669           ServerList[i] = NULL;
670         }
671     }
672   rc = ldap_unbind_s(ldap_handle);
673   exit(0);
674 }
675
676 void do_mcntmap(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
677                 char **before, int beforec, char **after, int afterc)
678 {
679     char    MoiraContainerName[128];
680     char    ADContainerName[128];
681     char    MachineName[1024];
682     char    OriginalMachineName[1024];
683     long    rc;
684     int     DeleteMachine;
685     char    MoiraContainerGroup[64];
686
687     DeleteMachine = 0;
688     memset(ADContainerName, '\0', sizeof(ADContainerName));
689     memset(MoiraContainerName, '\0', sizeof(MoiraContainerName));
690
691     if ((beforec == 0) && (afterc == 0))
692         return;
693
694     if (rc = moira_connect())
695     {
696         critical_alert("AD incremental",
697                        "Error contacting Moira server : %s",
698                        error_message(rc));
699         return;
700     }
701
702     if ((beforec != 0) && (afterc == 0)) /*remove a machine*/
703     {
704         strcpy(OriginalMachineName, before[OU_MACHINE_NAME]);
705         strcpy(MachineName, before[OU_MACHINE_NAME]);
706         strcpy(MoiraContainerGroup, before[OU_CONTAINER_GROUP]);
707         DeleteMachine = 1;
708         com_err(whoami, 0, "removing machine %s from %s", OriginalMachineName, before[OU_CONTAINER_NAME]);
709     }
710     else if ((beforec == 0) && (afterc != 0)) /*add a machine*/
711     {
712         strcpy(OriginalMachineName, after[OU_MACHINE_NAME]);
713         strcpy(MachineName, after[OU_MACHINE_NAME]);
714         strcpy(MoiraContainerGroup, after[OU_CONTAINER_GROUP]);
715         com_err(whoami, 0, "adding machine %s to container %s", OriginalMachineName, after[OU_CONTAINER_NAME]);
716     }
717     else
718       {
719         moira_disconnect();
720         return;
721       }
722
723     rc = GetMachineName(MachineName);
724     if (strlen(MachineName) == 0)
725     {
726         moira_disconnect();
727         com_err(whoami, 0, "Unable to find alais for machine %s in Moira", OriginalMachineName);
728         return;
729     }
730     Moira_process_machine_container_group(MachineName, MoiraContainerGroup,
731                                           DeleteMachine);
732     if (machine_check(ldap_handle, dn_path, MachineName))
733     {
734         com_err(whoami, 0, "Unable to find machine %s (alias %s) in AD.", OriginalMachineName, MachineName);
735         moira_disconnect();
736         return;
737     }
738     memset(MoiraContainerName, '\0', sizeof(MoiraContainerName));
739     machine_get_moira_container(ldap_handle, dn_path, MachineName, MoiraContainerName);
740     if (strlen(MoiraContainerName) == 0)
741     {
742         com_err(whoami, 0, "Unable to fine machine %s (alias %s) container in Moira - moving to orphans OU.",
743                 OriginalMachineName, MachineName);
744         machine_move_to_ou(ldap_handle, dn_path, MachineName, orphans_machines_ou);
745         moira_disconnect();
746         return;
747     }
748     container_get_dn(MoiraContainerName, ADContainerName);
749     if (MoiraContainerName[strlen(MoiraContainerName) - 1] != '/')
750        strcat(MoiraContainerName, "/");
751     container_check(ldap_handle, dn_path, MoiraContainerName);
752     machine_move_to_ou(ldap_handle, dn_path, MachineName, ADContainerName);
753     moira_disconnect();
754     return;
755 }
756
757 void do_container(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
758              char **before, int beforec, char **after, int afterc)
759 {
760   long rc;
761
762   if ((beforec == 0) && (afterc == 0))
763     return;
764
765   if (rc = moira_connect())
766     {
767       critical_alert("AD incremental", "Error contacting Moira server : %s",
768                      error_message(rc));
769       return;
770     }
771
772   if ((beforec != 0) && (afterc == 0)) /*delete a new container*/
773     {
774       com_err(whoami, 0, "deleting container %s", before[CONTAINER_NAME]);
775       container_delete(ldap_handle, dn_path, beforec, before);
776       Moira_container_group_delete(before);
777       moira_disconnect();
778       return;
779     }
780   if ((beforec == 0) && (afterc != 0)) /*create a container*/
781     {
782       com_err(whoami, 0, "creating container %s", after[CONTAINER_NAME]);
783       container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
784       container_create(ldap_handle, dn_path, afterc, after);
785       Moira_container_group_create(after);
786       moira_disconnect();
787       return;
788     }
789
790   if (strcasecmp(before[CONTAINER_NAME], after[CONTAINER_NAME]))
791     {
792       com_err(whoami, 0, "renaming container %s to %s", before[CONTAINER_NAME], after[CONTAINER_NAME]);
793       container_rename(ldap_handle, dn_path, beforec, before, afterc, after);
794       Moira_container_group_update(before, after);
795       moira_disconnect();
796       return;
797     }
798   com_err(whoami, 0, "updating container %s information", after[CONTAINER_NAME]);
799   container_update(ldap_handle, dn_path, beforec, before, afterc, after);
800   Moira_container_group_update(before, after);
801   moira_disconnect();
802   return;
803 }
804
805 void do_filesys(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
806              char **before, int beforec, char **after, int afterc)
807 {
808   long  rc;
809   char  *av[3];
810   char  *call_args[7];
811   int   acreate;
812   int   atype;
813   int   bcreate;
814   int   btype;
815   int   abort_flag;
816
817   abort_flag = 0;
818
819   if (afterc < FS_CREATE)
820     atype = acreate = 0;
821   else
822     {
823       atype = !strcmp(after[FS_TYPE], "AFS");
824       acreate = atoi(after[FS_CREATE]);
825     }
826
827   if (beforec < FS_CREATE)
828     {
829       if (acreate == 0 || atype == 0)
830         goto cleanup;
831       com_err(whoami, 0, "Processing filesys %s", after[FS_NAME]);
832       abort_flag = 0;
833       while (1)
834       {
835         if ((rc = filesys_process(ldap_handle, dn_path, after[FS_NAME], 
836                     after[FS_TYPE], after[FS_PACK], LDAP_MOD_ADD)) != LDAP_NO_SUCH_OBJECT)
837           {
838             if (rc != LDAP_SUCCESS)
839               com_err(whoami, 0, "Unable to process filesys %s", after[FS_NAME]);
840             break;
841           }
842         if (abort_flag == 1)
843           break;
844         sleep(1);
845         abort_flag = 1;
846         if (rc = moira_connect())
847           {
848             critical_alert("AD incremental",
849                            "Error contacting Moira server : %s",
850                            error_message(rc));
851             return;
852           }
853         av[0] = after[FS_NAME];
854         call_args[0] = (char *)ldap_handle;
855         call_args[1] = dn_path;
856         call_args[2] = "";
857         call_args[3] = NULL;
858         sid_base = NULL;
859         sid_ptr = &sid_base;
860         callback_rc = 0;
861         if (rc = mr_query("get_user_account_by_login", 1, av, user_create,
862                           call_args))
863           {
864             moira_disconnect();
865             com_err(whoami, 0, "Unable to process filesys %s", after[FS_NAME]);
866             break;
867           }
868         if (callback_rc)
869           {
870             moira_disconnect();
871             com_err(whoami, 0, "Unable to process filesys %s", after[FS_NAME]);
872             break;
873           }
874         if (sid_base != NULL)
875           {
876             sid_update(ldap_handle, dn_path);
877             linklist_free(sid_base);
878             sid_base = NULL;
879           }
880         moira_disconnect();
881       }
882       goto cleanup;
883     }
884
885   btype = !strcmp(before[FS_TYPE], "AFS");
886   bcreate = atoi(before[FS_CREATE]);
887   if (afterc < FS_CREATE)
888     {
889       if (btype && bcreate)
890         {
891           if (rc = filesys_process(ldap_handle, dn_path, before[FS_NAME], 
892                       before[FS_TYPE], before[FS_PACK], LDAP_MOD_DELETE))
893             {
894               com_err(whoami, 0, "Unable to delete filesys %s", before[FS_NAME]);
895             }
896         }
897       return;
898     }
899
900   if (!acreate)
901     return;
902
903   if (!atype && !btype)
904     {
905       if (strcmp(before[FS_TYPE], "ERR") || strcmp(after[FS_TYPE], "ERR"))
906         {
907           com_err(whoami, 0, "Unable to process Filesystem %s or %s is not AFS",
908                   before[FS_NAME], after[FS_NAME]);
909           return;
910         }
911     }
912   com_err(whoami, 0, "Processing filesys %s", after[FS_NAME]);
913   abort_flag = 0;
914   while (1)
915   {
916     if ((rc = filesys_process(ldap_handle, dn_path, after[FS_NAME], 
917                     after[FS_TYPE], after[FS_PACK], LDAP_MOD_ADD)) != LDAP_NO_SUCH_OBJECT)
918       {
919         if (rc != LDAP_SUCCESS)
920           com_err(whoami, 0, "Unable to process filesys %s", after[FS_NAME]);
921         break;
922       }
923     if (abort_flag == 1)
924       break;
925     sleep(1);
926     abort_flag = 1;
927     if (rc = moira_connect())
928       {
929         critical_alert("AD incremental",
930                        "Error contacting Moira server : %s",
931                        error_message(rc));
932         return;
933       }
934     av[0] = after[FS_NAME];
935     call_args[0] = (char *)ldap_handle;
936     call_args[1] = dn_path;
937     call_args[2] = "";
938     call_args[3] = NULL;
939     sid_base = NULL;
940     sid_ptr = &sid_base;
941     callback_rc = 0;
942     if (rc = mr_query("get_user_account_by_login", 1, av, user_create,
943                       call_args))
944       {
945         moira_disconnect();
946         com_err(whoami, 0, "Unable to process filesys %s", after[FS_NAME]);
947         break;
948       }
949     if (callback_rc)
950       {
951         moira_disconnect();
952         com_err(whoami, 0, "Unable to process filesys %s", after[FS_NAME]);
953         break;
954       }
955     if (sid_base != NULL)
956       {
957         sid_update(ldap_handle, dn_path);
958         linklist_free(sid_base);
959         sid_base = NULL;
960       }
961     moira_disconnect();
962   }
963
964 cleanup:
965   return;
966 }
967
968 #define L_LIST_DESC 9
969 #define L_LIST_ID   10
970
971 void do_list(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
972              char **before, int beforec, char **after, int afterc)
973 {
974   int   updateGroup;
975   int   ProcessGroup;
976   long  rc;
977   char  group_membership[6];
978   char  list_id[32];
979   int   security_flag;
980   char  filter[128];
981   char  group_ou[256];
982   char  before_list_id[32];
983   char  before_group_membership[1];
984   int   before_security_flag;
985   char  before_group_ou[256];
986   LK_ENTRY *ptr = NULL;
987
988   if (beforec == 0 && afterc == 0)
989     return;
990
991   memset(list_id, '\0', sizeof(list_id));
992   memset(before_list_id, '\0', sizeof(before_list_id));
993   memset(before_group_ou, '\0', sizeof(before_group_ou));
994   memset(before_group_membership, '\0', sizeof(before_group_membership));
995   memset(group_ou, '\0', sizeof(group_ou));
996   memset(group_membership, '\0', sizeof(group_membership));
997   updateGroup = 0;
998
999   if (beforec > L_GID)
1000     {
1001       if (beforec < L_LIST_ID)
1002         return;
1003       if (beforec > L_LIST_DESC)
1004         {
1005           strcpy(before_list_id, before[L_LIST_ID]);
1006         }
1007       before_security_flag = 0;
1008       get_group_membership(before_group_membership, before_group_ou, &before_security_flag, before);
1009     }
1010   if (afterc > L_GID)
1011     {
1012       if (afterc < L_LIST_ID)
1013         return;
1014       if (afterc > L_LIST_DESC)
1015         {
1016           strcpy(list_id, after[L_LIST_ID]);
1017         }
1018       security_flag = 0;
1019       get_group_membership(group_membership, group_ou, &security_flag, after);
1020     }
1021
1022   if ((beforec == 0) && (afterc == 0)) /*this case should never happen*/
1023     return;
1024
1025   updateGroup = 0;
1026   if (beforec)
1027     {
1028       updateGroup = 1;
1029       if ((rc = process_group(ldap_handle, dn_path, before_list_id, before[L_NAME], 
1030                               before_group_ou, before_group_membership, 
1031                               before_security_flag, CHECK_GROUPS)))
1032         {
1033           if (rc == AD_NO_GROUPS_FOUND)
1034             updateGroup = 0;
1035           else
1036             {
1037               if ((rc == AD_WRONG_GROUP_DN_FOUND) || (rc == AD_MULTIPLE_GROUPS_FOUND))
1038                 {
1039                   rc = process_group(ldap_handle, dn_path, before_list_id, before[L_NAME], 
1040                                      before_group_ou, before_group_membership, 
1041                                      before_security_flag, CLEANUP_GROUPS);
1042                 }
1043               if ((rc != AD_NO_GROUPS_FOUND) && (rc != 0))
1044                 {
1045                   com_err(whoami, 0, "Unable to process list %s",
1046                           before[L_NAME]);
1047                   return;
1048                 }
1049               if (rc == AD_NO_GROUPS_FOUND)
1050                 updateGroup = 0;
1051             }
1052         }
1053     }
1054   
1055   if ((beforec != 0) && (afterc != 0))
1056     {
1057       if (((strcmp(after[L_NAME], before[L_NAME])) || 
1058           ((!strcmp(after[L_NAME], before[L_NAME])) && 
1059            (strcmp(before_group_ou, group_ou)))) &&
1060           (updateGroup == 1))
1061         {
1062           com_err(whoami, 0, "Changing list name from %s to %s",
1063                   before[L_NAME], after[L_NAME]);
1064           if ((strlen(before_group_ou) == 0) || (strlen(before_group_membership) == 0) ||
1065               (strlen(group_ou) == 0) || (strlen(group_membership) == 0))
1066             {
1067               com_err(whoami, 0, "%s", "Unable to find the group OU's");
1068               return;
1069             }
1070           memset(filter, '\0', sizeof(filter));
1071           if ((rc = group_rename(ldap_handle, dn_path, 
1072                                  before[L_NAME], before_group_membership, 
1073                                  before_group_ou, before_security_flag, before[L_LIST_DESC],
1074                                  after[L_NAME], group_membership, 
1075                                  group_ou, security_flag, after[L_LIST_DESC],
1076                                  list_id, filter)))
1077             {
1078               if (rc != AD_NO_GROUPS_FOUND)
1079                 {
1080                   com_err(whoami, 0, "Unable to change list name from %s to %s",
1081                           before[L_NAME], after[L_NAME]);
1082                   return;
1083                 }
1084               updateGroup = 0;
1085             }
1086           beforec = 0;
1087         }
1088       else
1089         beforec = 0;
1090     }
1091
1092   if (beforec)
1093     {
1094       if ((strlen(before_group_ou) == 0) || (strlen(before_group_membership) == 0))
1095         {
1096           com_err(whoami, 0, "Unable to find the group OU for group %s", before[L_NAME]);
1097           return;
1098         }
1099       com_err(whoami, 0, "Deleting group %s", before[L_NAME]);
1100       rc = group_delete(ldap_handle, dn_path, before[L_NAME], 
1101                         before_group_membership, before_list_id);
1102       return;
1103     }
1104   if (afterc)
1105     {
1106       if (!updateGroup)
1107         {
1108           com_err(whoami, 0, "Creating group %s", after[L_NAME]);
1109           if (rc = process_group(ldap_handle, dn_path, list_id, after[L_NAME], 
1110                                   group_ou, group_membership, 
1111                                   security_flag, CHECK_GROUPS))
1112             {
1113               if (rc != AD_NO_GROUPS_FOUND)
1114                 {
1115                   if ((rc == AD_WRONG_GROUP_DN_FOUND) || (rc == AD_MULTIPLE_GROUPS_FOUND))
1116                     {
1117                       rc = process_group(ldap_handle, dn_path, list_id, after[L_NAME], 
1118                                          group_ou, group_membership, 
1119                                          security_flag, CLEANUP_GROUPS);
1120                     }
1121                   if (rc)
1122                     {
1123                       com_err(whoami, 0, "Unable to create list %s", after[L_NAME]);
1124                       return;
1125                     }
1126                 }
1127             }
1128         }
1129       else
1130         com_err(whoami, 0, "Updating group %s information", after[L_NAME]);
1131
1132       if (rc = moira_connect())
1133         {
1134           critical_alert("AD incremental",
1135                          "Error contacting Moira server : %s",
1136                          error_message(rc));
1137           return;
1138         }
1139
1140       ProcessGroup = 0;
1141       if (ProcessAce(ldap_handle, dn_path, after[L_NAME], "LIST", 0, &ProcessGroup))
1142         return;
1143       if (ProcessGroup)
1144         {
1145           if (ProcessAce(ldap_handle, dn_path, after[L_NAME], "LIST", 1, &ProcessGroup))
1146             return;
1147         }
1148       if (make_new_group(ldap_handle, dn_path, list_id, after[L_NAME], 
1149                          group_ou, group_membership, security_flag, updateGroup))
1150         {
1151           moira_disconnect();
1152           return;
1153         }
1154       if (atoi(after[L_ACTIVE]))
1155         {
1156           populate_group(ldap_handle, dn_path, after[L_NAME], group_ou, 
1157                          group_membership, security_flag, list_id);
1158         }
1159       moira_disconnect();
1160     }
1161   return;
1162 }
1163
1164 #define LM_EXTRA_ACTIVE   (LM_END)
1165 #define LM_EXTRA_PUBLIC   (LM_END+1)
1166 #define LM_EXTRA_HIDDEN   (LM_END+2)
1167 #define LM_EXTRA_MAILLIST (LM_END+3)
1168 #define LM_EXTRA_GROUP    (LM_END+4)
1169 #define LM_EXTRA_GID      (LM_END+5)
1170 #define LMN_LIST_ID       (LM_END+6)
1171 #define LM_LIST_ID        (LM_END+7)
1172 #define LM_USER_ID        (LM_END+8)
1173 #define LM_EXTRA_END      (LM_END+9)
1174
1175 void do_member(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
1176                char **before, int beforec, char **after, int afterc)
1177 {
1178   char  group_name[128];
1179   char  user_name[128];
1180   char  user_type[128];
1181   char  moira_list_id[32];
1182   char  moira_user_id[32];
1183   char  group_membership[1];
1184   char  group_ou[256];
1185   char  machine_ou[256];
1186   char  *args[16];
1187   char  **ptr;
1188   char  *av[7];
1189   char  *call_args[7];
1190   char  *pUserOu;
1191   char  NewMachineName[1024];
1192   int   security_flag;
1193   int   rc;
1194   int   ProcessGroup;
1195
1196   pUserOu = NULL;
1197   ptr = NULL;
1198   memset(moira_list_id, '\0', sizeof(moira_list_id));
1199   memset(moira_user_id, '\0', sizeof(moira_user_id));
1200   if (afterc)
1201     {
1202       if (afterc < LM_EXTRA_GID)
1203         return;
1204       if (!atoi(after[LM_EXTRA_ACTIVE]))
1205         {
1206         com_err(whoami, 0, "Unable to add %s to group %s : group not active", after[2], after[0]);
1207         return;
1208         }
1209       ptr = after;
1210       if (!strcasecmp(ptr[LM_TYPE], "LIST"))
1211         {
1212           com_err(whoami, 0, "Unable to add %s to group %s : %s is not a group", 
1213                   after[2], after[0], after[0]);
1214           return;
1215         }
1216       strcpy(user_name, after[LM_MEMBER]);
1217       strcpy(group_name, after[LM_LIST]);
1218       strcpy(user_type, after[LM_TYPE]);
1219       if (!strcasecmp(ptr[LM_TYPE], "MACHINE"))
1220         {
1221           if (afterc > LM_EXTRA_GROUP)
1222             {
1223               strcpy(moira_list_id, after[LMN_LIST_ID]);
1224               strcpy(moira_user_id, after[LM_LIST_ID]);
1225             }
1226         }
1227       else if (!strcasecmp(ptr[LM_TYPE], "USER"))
1228         {
1229           if (afterc > LMN_LIST_ID)
1230             {
1231               strcpy(moira_list_id, after[LM_LIST_ID]);
1232               strcpy(moira_user_id, after[LM_USER_ID]);
1233             }
1234         }
1235       else
1236         {
1237           if (afterc > LM_EXTRA_GID)
1238             strcpy(moira_list_id, after[LMN_LIST_ID]);
1239         }
1240     }
1241   else if (beforec)
1242     {
1243       if (beforec < LM_EXTRA_GID)
1244         return;
1245       if (!atoi(before[LM_EXTRA_ACTIVE]))
1246         {
1247           com_err(whoami, 0, "Unable to add %s to group %s : group not active", before[2], before[0]);
1248           return;
1249         }
1250       ptr = before;
1251       if (!strcasecmp(ptr[LM_TYPE], "LIST"))
1252         {
1253           com_err(whoami, 0, "Unable to add %s to group %s : %s is not a group", 
1254                   before[2], before[0], before[0]);
1255           return;
1256         }
1257       strcpy(user_name, before[LM_MEMBER]);
1258       strcpy(group_name, before[LM_LIST]);
1259       strcpy(user_type, before[LM_TYPE]);
1260       if (!strcasecmp(ptr[LM_TYPE], "MACHINE"))
1261         {
1262           if (beforec > LM_EXTRA_GROUP)
1263             {
1264               strcpy(moira_list_id, before[LMN_LIST_ID]);
1265               strcpy(moira_user_id, before[LM_LIST_ID]);
1266             }
1267         }
1268       else if (!strcasecmp(ptr[LM_TYPE], "USER"))
1269         {
1270           if (beforec > LMN_LIST_ID)
1271             {
1272               strcpy(moira_list_id, before[LM_LIST_ID]);
1273               strcpy(moira_user_id, before[LM_USER_ID]);
1274             }
1275         }
1276       else
1277         {
1278           if (beforec > LM_EXTRA_GID)
1279             strcpy(moira_list_id, before[LMN_LIST_ID]);
1280         }
1281     }
1282
1283   if (ptr == NULL)
1284     {
1285       com_err(whoami, 0, "Unable to process group : beforec = %d, afterc = %d", beforec, afterc);
1286       return;
1287     }
1288
1289   args[L_NAME] = ptr[LM_LIST];
1290   args[L_ACTIVE] = ptr[LM_EXTRA_ACTIVE];
1291   args[L_PUBLIC] = ptr[LM_EXTRA_PUBLIC];
1292   args[L_HIDDEN] = ptr[LM_EXTRA_HIDDEN];
1293   args[L_MAILLIST] = ptr[LM_EXTRA_MAILLIST];
1294   args[L_GROUP] = ptr[LM_EXTRA_GROUP];
1295   args[L_GID] = ptr[LM_EXTRA_GID];
1296
1297   security_flag = 0;
1298   memset(group_ou, '\0', sizeof(group_ou));
1299   get_group_membership(group_membership, group_ou, &security_flag, args);
1300   if (strlen(group_ou) == 0)
1301     {
1302       com_err(whoami, 0, "Unable to find the group OU for group %s", group_name);
1303       return;
1304     }
1305   if (rc = process_group(ldap_handle, dn_path, moira_list_id, group_name, group_ou, group_membership, security_flag, CHECK_GROUPS))
1306     {
1307       if (rc != AD_NO_GROUPS_FOUND)
1308         {
1309           if (rc = process_group(ldap_handle, dn_path, moira_list_id, group_name, group_ou, group_membership, security_flag, CLEANUP_GROUPS))
1310             {
1311               if (rc != AD_NO_GROUPS_FOUND)
1312                 {
1313                   if (afterc)
1314                     com_err(whoami, 0, "Unable to add %s to group %s - unable to process group", user_name, group_name);
1315                   else
1316                     com_err(whoami, 0, "Unable to remove %s from group %s - unable to process group", user_name, group_name);
1317                   return;
1318                 }
1319             }
1320         }
1321     }
1322   if (rc == AD_NO_GROUPS_FOUND)
1323     {
1324       if (rc = moira_connect())
1325         {
1326           critical_alert("AD incremental",
1327                          "Error contacting Moira server : %s",
1328                          error_message(rc));
1329           return;
1330         }
1331
1332       com_err(whoami, 0, "creating group %s", group_name);
1333       ProcessGroup = 0;
1334       if (ProcessAce(ldap_handle, dn_path, ptr[LM_LIST], "LIST", 0, &ProcessGroup))
1335         return;
1336       if (ProcessGroup)
1337         {
1338           if (ProcessAce(ldap_handle, dn_path, ptr[LM_LIST], "LIST", 1, &ProcessGroup))
1339             return;
1340         }
1341       if (make_new_group(ldap_handle, dn_path, moira_list_id, ptr[LM_LIST], 
1342                          group_ou, group_membership, security_flag, 0))
1343         {
1344           moira_disconnect();
1345           return;
1346         }
1347       if (atoi(ptr[LM_EXTRA_ACTIVE]))
1348         {
1349           populate_group(ldap_handle, dn_path, ptr[LM_LIST], group_ou, 
1350                          group_membership, security_flag, moira_list_id);
1351         }
1352       moira_disconnect();
1353     }
1354   rc = 0;
1355   if (beforec)
1356     {
1357       com_err(whoami, 0, "removing user %s from list %s", user_name, group_name);
1358       pUserOu = user_ou;
1359       if (!strcasecmp(ptr[LM_TYPE], "MACHINE"))
1360         {
1361           memset(machine_ou, '\0', sizeof(machine_ou));
1362           memset(NewMachineName, '\0', sizeof(NewMachineName));
1363           if (get_machine_ou(ldap_handle, dn_path, ptr[LM_MEMBER], machine_ou, NewMachineName))
1364             return;
1365           ptr[LM_MEMBER] = NewMachineName;
1366           pUserOu = machine_ou;
1367         }
1368       if (!strcasecmp(ptr[LM_TYPE], "STRING"))
1369         {
1370           if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], contact_ou))
1371             return;
1372           pUserOu = contact_ou;
1373         }
1374       else if (!strcasecmp(ptr[LM_TYPE], "KERBEROS"))
1375         {
1376           if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], kerberos_ou))
1377             return;
1378           pUserOu = kerberos_ou;
1379         }
1380       if (rc = member_remove(ldap_handle, dn_path, group_name,
1381                              group_ou, group_membership, ptr[LM_MEMBER], 
1382                              pUserOu, moira_list_id))
1383           com_err(whoami, 0, "Unable to remove %s from group %s", user_name, group_name);
1384       return;
1385     }
1386
1387   com_err(whoami, 0, "Adding %s to list %s", user_name, group_name);
1388   pUserOu = user_ou;
1389
1390   if (!strcasecmp(ptr[LM_TYPE], "MACHINE"))
1391     {
1392       memset(machine_ou, '\0', sizeof(machine_ou));
1393       memset(NewMachineName, '\0', sizeof(NewMachineName));
1394       if (get_machine_ou(ldap_handle, dn_path, ptr[LM_MEMBER], machine_ou, NewMachineName))
1395         return;
1396       ptr[LM_MEMBER] = NewMachineName;
1397       pUserOu = machine_ou;
1398     }
1399   else if (!strcasecmp(ptr[LM_TYPE], "STRING"))
1400     {
1401       if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], contact_ou))
1402         return;
1403       pUserOu = contact_ou;
1404     }
1405   else if (!strcasecmp(ptr[LM_TYPE], "KERBEROS"))
1406     {
1407       if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], kerberos_ou))
1408         return;
1409       pUserOu = kerberos_ou;
1410     }
1411   else if (!strcasecmp(ptr[LM_TYPE], "USER"))
1412     {
1413       if ((rc = check_user(ldap_handle, dn_path, ptr[LM_MEMBER], 
1414                            moira_user_id)) == AD_NO_USER_FOUND)
1415         {
1416           if (rc = moira_connect())
1417             {
1418               critical_alert("AD incremental", 
1419                              "Error connection to Moira : %s",
1420                              error_message(rc));
1421               return;
1422             }
1423           com_err(whoami, 0, "creating user %s", after[U_NAME]);
1424           av[0] = ptr[LM_MEMBER];
1425           call_args[0] = (char *)ldap_handle;
1426           call_args[1] = dn_path;
1427           call_args[2] = moira_user_id;
1428           call_args[3] = NULL;
1429           sid_base = NULL;
1430           sid_ptr = &sid_base;
1431           callback_rc = 0;
1432           if (rc = mr_query("get_user_account_by_login", 1, av, user_create,
1433                             call_args))
1434             {
1435               moira_disconnect();
1436               com_err(whoami, 0, "Unable to create user %s : %s",
1437                       ptr[LM_MEMBER], error_message(rc));
1438               return;
1439             }
1440           if (callback_rc)
1441             {
1442               moira_disconnect();
1443               com_err(whoami, 0, "Unable to create user %s", ptr[LM_MEMBER]);
1444               return;
1445             }
1446           sleep(1);
1447           if (sid_base != NULL)
1448             {
1449               sid_update(ldap_handle, dn_path);
1450               linklist_free(sid_base);
1451             }
1452         }
1453       else
1454         {
1455           if (rc != 0)
1456             return;
1457         }
1458       pUserOu = user_ou;
1459     }
1460
1461   if (rc = member_add(ldap_handle, dn_path, group_name,
1462                   group_ou, group_membership, ptr[LM_MEMBER],
1463                   pUserOu, moira_list_id))
1464     {
1465       com_err(whoami, 0, "Unable to add %s to group %s", user_name, group_name);
1466     }
1467   return;
1468 }
1469
1470
1471 #define U_USER_ID    10
1472 #define U_HOMEDIR    11
1473 #define U_PROFILEDIR 12
1474
1475 void do_user(LDAP *ldap_handle, char *dn_path, char *ldap_hostname, 
1476              char **before, int beforec, char **after, 
1477              int afterc)
1478 {
1479   int   rc;
1480   char  *av[7];
1481   char  after_user_id[32];
1482   char  before_user_id[32];
1483   char  *call_args[7];
1484
1485   if ((beforec == 0) && (afterc == 0))
1486     return;
1487
1488   memset(after_user_id, '\0', sizeof(after_user_id));
1489   memset(before_user_id, '\0', sizeof(before_user_id));
1490   if (beforec > U_USER_ID)
1491     strcpy(before_user_id, before[U_USER_ID]);
1492   if (afterc > U_USER_ID)
1493     strcpy(after_user_id, after[U_USER_ID]);
1494
1495   if ((beforec == 0) && (afterc == 0)) /*this case should never happen */
1496     return;
1497
1498   if ((beforec == 0) && (afterc != 0)) 
1499     {
1500       /*this case only happens when the account*/
1501       /*account is first created but not usable*/
1502       com_err(whoami, 0, "Unable to process user %s because the user account is not yet usable", after[U_NAME]);
1503       return;
1504     }
1505   if ((beforec != 0) && (afterc == 0)) /*this case only happens when the account*/
1506     {                                  /*is expunged*/
1507       if (atoi(before[U_STATE]) == 0)
1508         {
1509           com_err(whoami, 0, "expunging user %s from AD", before[U_NAME]);
1510           user_delete(ldap_handle, dn_path, before[U_NAME], before_user_id);
1511         }
1512       else
1513         {
1514           com_err(whoami, 0, "Unable to process because user %s has been previously expungeded", before[U_NAME]);
1515         }
1516       return;
1517     }
1518
1519   /*process anything that gets here*/
1520   if ((rc = check_user(ldap_handle, dn_path, before[U_NAME], 
1521                        before_user_id)) == AD_NO_USER_FOUND)
1522     {
1523       if (!check_string(after[U_NAME]))
1524         return;
1525       if (rc = moira_connect())
1526         {
1527           critical_alert("AD incremental", 
1528                          "Error connection to Moira : %s",
1529                          error_message(rc));
1530           return;
1531         }
1532       com_err(whoami, 0, "creating user %s", after[U_NAME]);
1533
1534       av[0] = after[U_NAME];
1535       call_args[0] = (char *)ldap_handle;
1536       call_args[1] = dn_path;
1537       call_args[2] = after_user_id;
1538       call_args[3] = NULL;
1539       sid_base = NULL;
1540       sid_ptr = &sid_base;
1541       callback_rc = 0;
1542       if (rc = mr_query("get_user_account_by_login", 1, av, user_create,
1543                         call_args))
1544         {
1545           moira_disconnect();
1546           com_err(whoami, 0, "Unable to create user %s : %s",
1547                   after[U_NAME], error_message(rc));
1548           return;
1549         }
1550       if (callback_rc)
1551         {
1552           moira_disconnect();
1553           com_err(whoami, 0, "Unable to create user %s", after[U_NAME]);
1554           return;
1555         }
1556       sleep(1);
1557       if (sid_base != NULL)
1558         {
1559           sid_update(ldap_handle, dn_path);
1560           linklist_free(sid_base);
1561         }
1562       return;
1563     }
1564   else
1565     {
1566       if (rc != 0)
1567         return;
1568     }
1569   if (strcmp(before[U_NAME], after[U_NAME]))
1570     {
1571       if ((check_string(before[U_NAME])) && (check_string(after[U_NAME])))
1572         {
1573           com_err(whoami, 0, "changing user %s to %s", 
1574                   before[U_NAME], after[U_NAME]);
1575           if ((rc = user_rename(ldap_handle, dn_path, before[U_NAME], 
1576                                 after[U_NAME])) != LDAP_SUCCESS)
1577             {
1578               return;
1579             }
1580         }
1581     }
1582   com_err(whoami, 0, "updating user %s information", after[U_NAME]);
1583   rc = user_update(ldap_handle, dn_path, after[U_NAME],
1584                    after[U_UID], after[U_MITID], 
1585                    after_user_id, atoi(after[U_STATE]),
1586                    after[U_HOMEDIR], after[U_PROFILEDIR]);
1587   return;
1588 }
1589
1590 int construct_newvalues(LK_ENTRY *linklist_base, int modvalue_count, 
1591                         char *oldValue, char *newValue,
1592                         char ***modvalues, int type)
1593 {
1594   LK_ENTRY    *linklist_ptr;
1595   int         i;
1596   char        *cPtr;
1597
1598   if (((*modvalues) = calloc(1, (modvalue_count + 1) * sizeof(char *)))
1599       == NULL)
1600     {
1601       return(1);
1602     }
1603   for (i = 0; i < (modvalue_count + 1); i++)
1604     (*modvalues)[i] = NULL;
1605   if (modvalue_count != 0)
1606     {
1607       linklist_ptr = linklist_base;
1608       for (i = 0; i < modvalue_count; i++)
1609         {
1610           if ((oldValue != NULL) && (newValue != NULL))
1611             {
1612               if ((cPtr = (char *)strstr(linklist_ptr->value, oldValue))
1613                  != (char *)NULL)
1614                 {
1615                   if (type == REPLACE)
1616                     {
1617                       if (((*modvalues)[i] = calloc(1, strlen(newValue) + 1))
1618                           == NULL)
1619                         return(1);
1620                       memset((*modvalues)[i], '\0', strlen(newValue) + 1);
1621                       strcpy((*modvalues)[i], newValue);
1622                     }
1623                   else
1624                     {
1625                       if (((*modvalues)[i] = calloc(1, 
1626                                         (int)(cPtr - linklist_ptr->value) + 
1627                                         (linklist_ptr->length - strlen(oldValue)) + 
1628                                         strlen(newValue) + 1)) == NULL)
1629                         return(1);
1630                       memset((*modvalues)[i], '\0', 
1631                              (int)(cPtr - linklist_ptr->value) + 
1632                              (linklist_ptr->length - strlen(oldValue)) + 
1633                              strlen(newValue) + 1);
1634                       memcpy((*modvalues)[i], linklist_ptr->value, 
1635                              (int)(cPtr - linklist_ptr->value));
1636                       strcat((*modvalues)[i], newValue);
1637                       strcat((*modvalues)[i], 
1638      &linklist_ptr->value[(int)(cPtr - linklist_ptr->value) + strlen(oldValue)]);
1639                     }
1640                 }
1641               else
1642                 {
1643                   (*modvalues)[i] = calloc(1, linklist_ptr->length + 1);
1644                   memset((*modvalues)[i], '\0', linklist_ptr->length + 1);
1645                   memcpy((*modvalues)[i], linklist_ptr->value,
1646                          linklist_ptr->length);
1647                 }
1648             }
1649         else
1650             {
1651               (*modvalues)[i] = calloc(1, linklist_ptr->length + 1);
1652               memset((*modvalues)[i], '\0', linklist_ptr->length + 1);
1653               memcpy((*modvalues)[i], linklist_ptr->value,
1654                      linklist_ptr->length);
1655             }
1656           linklist_ptr = linklist_ptr->next;
1657         }
1658       (*modvalues)[i] = NULL;
1659     }
1660   return(0);
1661 }
1662
1663
1664 int linklist_build(LDAP *ldap_handle, char *dn_path, char *search_exp, 
1665                    char **attr_array, LK_ENTRY **linklist_base,
1666                    int *linklist_count, unsigned long ScopeType)
1667 {
1668   ULONG       rc;
1669   LDAPMessage *ldap_entry;
1670
1671   rc = 0;
1672   ldap_entry = NULL;
1673   (*linklist_base) = NULL;
1674   (*linklist_count) = 0;
1675   if ((rc = ldap_search_s(ldap_handle, dn_path, ScopeType, 
1676                           search_exp, attr_array, 0, &ldap_entry))
1677       != LDAP_SUCCESS)
1678       {
1679         if (rc != LDAP_SIZELIMIT_EXCEEDED)
1680           return(0);
1681       }
1682
1683   rc = retrieve_entries(ldap_handle, ldap_entry, linklist_base, linklist_count);
1684
1685   ldap_msgfree(ldap_entry);
1686   return(rc);
1687 }
1688
1689
1690 int retrieve_entries(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
1691                      LK_ENTRY **linklist_base, int *linklist_count)
1692 {
1693   char        distinguished_name[1024];
1694   LK_ENTRY    *linklist_ptr;
1695   int         rc;
1696
1697   if ((ldap_entry = ldap_first_entry(ldap_handle, ldap_entry)) == NULL)
1698     return(0);
1699
1700   memset(distinguished_name, '\0', sizeof(distinguished_name));
1701   get_distinguished_name(ldap_handle, ldap_entry, distinguished_name);
1702
1703   if ((rc = retrieve_attributes(ldap_handle, ldap_entry, distinguished_name,
1704                                 linklist_base)) != 0)
1705     return(rc);
1706
1707   while ((ldap_entry = ldap_next_entry(ldap_handle, ldap_entry)) != NULL)
1708     {
1709       memset(distinguished_name, '\0', sizeof(distinguished_name));
1710       get_distinguished_name(ldap_handle, ldap_entry, distinguished_name);
1711
1712       if ((rc = retrieve_attributes(ldap_handle, ldap_entry, distinguished_name,
1713                                     linklist_base)) != 0)
1714         return(rc);
1715     }
1716
1717   linklist_ptr = (*linklist_base);
1718   (*linklist_count) = 0;
1719   while (linklist_ptr != NULL)
1720     {
1721       ++(*linklist_count);
1722       linklist_ptr = linklist_ptr->next;
1723     }
1724   return(0);
1725 }
1726
1727 int retrieve_attributes(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
1728                         char *distinguished_name, LK_ENTRY **linklist_current)
1729 {
1730   char        *Attribute;
1731   BerElement  *ptr;
1732
1733   ptr = NULL;
1734   if ((Attribute = ldap_first_attribute(ldap_handle, ldap_entry, &ptr)) != NULL)
1735     {
1736       retrieve_values(ldap_handle, ldap_entry, Attribute, distinguished_name,
1737                       linklist_current);
1738       ldap_memfree(Attribute);
1739       while ((Attribute = ldap_next_attribute(ldap_handle, ldap_entry, 
1740                                               ptr)) != NULL)
1741         {
1742           retrieve_values(ldap_handle, ldap_entry, Attribute,
1743                           distinguished_name, linklist_current);
1744           ldap_memfree(Attribute);
1745         }
1746     }
1747   ldap_ber_free(ptr, 0);
1748   return(0);
1749 }
1750
1751 int retrieve_values(LDAP *ldap_handle, LDAPMessage *ldap_entry,
1752                     char *Attribute, char *distinguished_name,
1753                     LK_ENTRY **linklist_current)
1754 {
1755   char        **str_value;
1756   char        temp[256];
1757   void        **Ptr;
1758   int         use_bervalue;
1759   LK_ENTRY    *linklist_previous;
1760   LDAP_BERVAL **ber_value;
1761   DWORD       ber_length;
1762 #ifdef LDAP_DEBUG
1763   SID         *sid;
1764   GUID        *guid;
1765   int         i;
1766   int         intValue;
1767   DWORD       *subauth;
1768   SID_IDENTIFIER_AUTHORITY    *sid_auth;
1769   unsigned char   *subauth_count;
1770 #endif /*LDAP_BEGUG*/
1771
1772   use_bervalue = 0;
1773   memset(temp, '\0', sizeof(temp));
1774   if ((!strcmp(Attribute, "objectSid")) ||
1775       (!strcmp(Attribute, "objectGUID")))
1776     use_bervalue = 1;
1777
1778   if (use_bervalue)
1779     {
1780       ber_value = ldap_get_values_len(ldap_handle, ldap_entry, Attribute);
1781       Ptr = (void **)ber_value;
1782       str_value = NULL;
1783       }
1784   else
1785     {
1786       str_value = ldap_get_values(ldap_handle, ldap_entry, Attribute);
1787       Ptr = (void **)str_value;
1788       ber_value = NULL;
1789     }
1790   if (Ptr != NULL)
1791     {
1792       for (; *Ptr; Ptr++) 
1793         {
1794           if ((linklist_previous = calloc(1, sizeof(LK_ENTRY))) == NULL)
1795             return(1);
1796           memset(linklist_previous, '\0', sizeof(LK_ENTRY));
1797           linklist_previous->next = (*linklist_current);
1798           (*linklist_current) = linklist_previous;
1799
1800           if (((*linklist_current)->attribute = calloc(1, 
1801                                                strlen(Attribute) + 1)) == NULL)
1802             return(1);
1803           memset((*linklist_current)->attribute, '\0', strlen(Attribute) + 1);
1804           strcpy((*linklist_current)->attribute, Attribute);
1805           if (use_bervalue)
1806             {
1807               ber_length = (*(LDAP_BERVAL **)Ptr)->bv_len;
1808               if (((*linklist_current)->value = calloc(1, ber_length)) == NULL)
1809                 return(1);
1810               memset((*linklist_current)->value, '\0', ber_length);
1811               memcpy((*linklist_current)->value, (*(LDAP_BERVAL **)Ptr)->bv_val, 
1812                                                   ber_length);
1813               (*linklist_current)->length = ber_length;
1814             }
1815           else
1816             {
1817               if (((*linklist_current)->value = calloc(1, 
1818                                                   strlen(*Ptr) + 1)) == NULL)
1819                 return(1);
1820               memset((*linklist_current)->value, '\0', strlen(*Ptr) + 1);
1821               (*linklist_current)->length = strlen(*Ptr);
1822               strcpy((*linklist_current)->value, *Ptr);
1823             }
1824           (*linklist_current)->ber_value = use_bervalue;
1825           if (((*linklist_current)->dn = calloc(1, 
1826                                       strlen(distinguished_name) + 1)) == NULL)
1827             return(1);
1828           memset((*linklist_current)->dn, '\0', strlen(distinguished_name) + 1);
1829           strcpy((*linklist_current)->dn, distinguished_name);
1830
1831 #ifdef LDAP_DEBUG
1832           if (!strcmp(Attribute, "objectGUID"))
1833             {
1834               guid = (GUID *)((*linklist_current)->value);
1835               sprintf(temp, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 
1836                       guid->Data1, guid->Data2, guid->Data3, 
1837                       guid->Data4[0], guid->Data4[1], guid->Data4[2], 
1838                       guid->Data4[3], guid->Data4[4], guid->Data4[5], 
1839                       guid->Data4[6], guid->Data4[7]);
1840               print_to_screen("     %20s : {%s}\n", Attribute, temp);
1841             }
1842           else if (!strcmp(Attribute, "objectSid"))
1843             {
1844               sid = (SID *)((*(LDAP_BERVAL **)Ptr)->bv_val);
1845 #ifdef _WIN32
1846               print_to_screen("        Revision = %d\n", sid->Revision);
1847               print_to_screen("        SID Identifier Authority:\n");
1848               sid_auth = &sid->IdentifierAuthority;
1849               if (sid_auth->Value[0])
1850                 print_to_screen("            SECURITY_NULL_SID_AUTHORITY\n");
1851               else if (sid_auth->Value[1])
1852                 print_to_screen("            SECURITY_WORLD_SID_AUTHORITY\n");
1853               else if (sid_auth->Value[2])
1854                 print_to_screen("            SECURITY_LOCAL_SID_AUTHORITY\n");
1855               else if (sid_auth->Value[3])
1856                 print_to_screen("            SECURITY_CREATOR_SID_AUTHORITY\n");
1857               else if (sid_auth->Value[5])
1858                 print_to_screen("            SECURITY_NT_AUTHORITY\n");
1859               else
1860                 print_to_screen("            UNKNOWN SID AUTHORITY\n");
1861               subauth_count = GetSidSubAuthorityCount(sid);
1862               print_to_screen("        SidSubAuthorityCount = %d\n", 
1863                               *subauth_count);
1864               print_to_screen("        SidSubAuthority:\n");
1865               for (i = 0; i < *subauth_count; i++)
1866                 {
1867                   if ((subauth = GetSidSubAuthority(sid, i)) != NULL)
1868                     print_to_screen("            %u\n", *subauth);
1869                 }
1870 #endif
1871             }
1872           else if ((!memcmp(Attribute, "userAccountControl", 
1873                             strlen("userAccountControl"))) ||
1874                    (!memcmp(Attribute, "sAMAccountType", 
1875                             strlen("sAmAccountType"))))
1876             {
1877               intValue = atoi(*Ptr);
1878               print_to_screen("     %20s : %ld\n",Attribute, intValue);
1879               if (!memcmp(Attribute, "userAccountControl", 
1880                           strlen("userAccountControl")))
1881                 {
1882                   if (intValue & UF_ACCOUNTDISABLE)
1883                     print_to_screen("     %20s :    %s\n", 
1884                                     "", "Account disabled");
1885                   else
1886                     print_to_screen("     %20s :    %s\n", 
1887                                     "", "Account active");
1888                   if (intValue & UF_HOMEDIR_REQUIRED)
1889                     print_to_screen("     %20s :    %s\n", 
1890                                     "", "Home directory required");
1891                   if (intValue & UF_LOCKOUT)
1892                     print_to_screen("     %20s :    %s\n", 
1893                                     "", "Account locked out");
1894                   if (intValue & UF_PASSWD_NOTREQD)
1895                     print_to_screen("     %20s :    %s\n", 
1896                                     "", "No password required");
1897                   if (intValue & UF_PASSWD_CANT_CHANGE)
1898                     print_to_screen("     %20s :    %s\n",
1899                                     "", "Cannot change password");
1900                   if (intValue & UF_TEMP_DUPLICATE_ACCOUNT)
1901                     print_to_screen("     %20s :    %s\n", 
1902                                     "", "Temp duplicate account");
1903                   if (intValue & UF_NORMAL_ACCOUNT)
1904                     print_to_screen("     %20s :    %s\n", 
1905                                     "", "Normal account");
1906                   if (intValue & UF_INTERDOMAIN_TRUST_ACCOUNT)
1907                     print_to_screen("     %20s :    %s\n", 
1908                                     "", "Interdomain trust account");
1909                   if (intValue & UF_WORKSTATION_TRUST_ACCOUNT)
1910                     print_to_screen("     %20s :    %s\n", 
1911                                     "", "Workstation trust account");
1912                   if (intValue & UF_SERVER_TRUST_ACCOUNT)
1913                     print_to_screen("     %20s :    %s\n", 
1914                                     "", "Server trust account");
1915                 }
1916             }
1917           else
1918             {
1919               print_to_screen("     %20s : %s\n",Attribute, *Ptr);
1920             }
1921 #endif /*LDAP_DEBUG*/
1922         }
1923       if (str_value != NULL)
1924         ldap_value_free(str_value);
1925       if (ber_value != NULL)
1926         ldap_value_free_len(ber_value);
1927     }
1928   (*linklist_current) = linklist_previous;
1929   return(0);
1930 }
1931
1932 int moira_connect(void)
1933 {
1934   long    rc;
1935   char    HostName[64];
1936
1937   if (!mr_connections++)
1938     {
1939 #ifdef _WIN32
1940       memset(HostName, '\0', sizeof(HostName));
1941       strcpy(HostName, "ttsp");
1942       rc = mr_connect_cl(HostName, "winad.incr", QUERY_VERSION, 1);
1943 /*det
1944       rc = mr_connect(HostName);
1945 */
1946 #else
1947       struct utsname uts;
1948       uname(&uts);
1949       rc = mr_connect_cl(uts.nodename, "winad.incr", QUERY_VERSION, 1);
1950 /*
1951       rc = mr_connect(uts.nodename);
1952 */
1953 #endif /*WIN32*/
1954 /*det
1955       if (!rc)
1956         rc = mr_auth("winad.incr");
1957 */
1958       return rc;
1959     }
1960   return 0;
1961 }
1962
1963 void check_winad(void)
1964 {
1965   int i;
1966   
1967   for (i = 0; file_exists(STOP_FILE); i++)
1968     {
1969       if (i > 30)
1970         {
1971           critical_alert("AD incremental",
1972                          "WINAD incremental failed (%s exists): %s",
1973                          STOP_FILE, tbl_buf);
1974           exit(1);
1975         }
1976       sleep(60);
1977     }
1978 }
1979
1980 int moira_disconnect(void)
1981 {
1982
1983   if (!--mr_connections)
1984     {
1985       mr_disconnect();
1986     }
1987   return 0;
1988 }
1989
1990 void get_distinguished_name(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
1991                             char *distinguished_name)
1992 {
1993   char    *CName;
1994
1995   CName = ldap_get_dn(ldap_handle, ldap_entry);
1996   if (CName == NULL)
1997     return;
1998   strcpy(distinguished_name, CName);
1999   ldap_memfree(CName);
2000 }
2001
2002 int linklist_create_entry(char *attribute, char *value, 
2003                           LK_ENTRY **linklist_entry)
2004 {
2005   (*linklist_entry) = calloc(1, sizeof(LK_ENTRY));
2006   if (!(*linklist_entry))
2007     {
2008       return(1);
2009     }
2010   memset((*linklist_entry), '\0', sizeof(LK_ENTRY));
2011   (*linklist_entry)->attribute = calloc(1, strlen(attribute) + 1);
2012   memset((*linklist_entry)->attribute, '\0', strlen(attribute) + 1);
2013   strcpy((*linklist_entry)->attribute, attribute);
2014   (*linklist_entry)->value = calloc(1, strlen(value) + 1);
2015   memset((*linklist_entry)->value, '\0', strlen(value) + 1);
2016   strcpy((*linklist_entry)->value, value);
2017   (*linklist_entry)->length = strlen(value);
2018   (*linklist_entry)->next = NULL;
2019   return(0);
2020 }
2021
2022 void print_to_screen(const char *fmt, ...)
2023 {
2024   va_list pvar;
2025
2026   va_start(pvar, fmt);
2027   vfprintf(stderr, fmt, pvar);
2028   fflush(stderr);
2029   va_end(pvar);
2030 }
2031
2032 int get_group_membership(char *group_membership, char *group_ou, 
2033                          int *security_flag, char **av)
2034 {
2035   int  maillist_flag;
2036   int  group_flag;
2037
2038   maillist_flag = atoi(av[L_MAILLIST]);
2039   group_flag = atoi(av[L_GROUP]);
2040   if (security_flag != NULL)
2041     (*security_flag) = 0;
2042
2043   if ((maillist_flag) && (group_flag))
2044     {
2045       if (group_membership != NULL)
2046         group_membership[0] = 'B';
2047       if (security_flag != NULL)
2048         (*security_flag) = 1;
2049       if (group_ou != NULL)
2050         strcpy(group_ou, group_ou_both);
2051     }
2052   else if ((!maillist_flag) && (group_flag))
2053     {
2054       if (group_membership != NULL)
2055         group_membership[0] = 'S';
2056       if (security_flag != NULL)
2057         (*security_flag) = 1;
2058       if (group_ou != NULL)
2059         strcpy(group_ou, group_ou_security);
2060     }
2061   else if ((maillist_flag) && (!group_flag))
2062     {
2063       if (group_membership != NULL)
2064         group_membership[0] = 'D';
2065       if (group_ou != NULL)
2066         strcpy(group_ou, group_ou_distribution);
2067     }
2068   else
2069     {
2070       if (group_membership != NULL)
2071         group_membership[0] = 'N';
2072       if (group_ou != NULL)
2073         strcpy(group_ou, group_ou_neither);
2074     }
2075   return(0);
2076 }
2077
2078 int group_rename(LDAP *ldap_handle, char *dn_path, 
2079                  char *before_group_name, char *before_group_membership, 
2080                  char *before_group_ou, int before_security_flag, char *before_desc,
2081                  char *after_group_name, char *after_group_membership, 
2082                  char *after_group_ou, int after_security_flag, char *after_desc,
2083                  char *MoiraId, char *filter)
2084 {
2085   LDAPMod   *mods[20];
2086   char      old_dn[512];
2087   char      new_dn[512];
2088   char      new_dn_path[512];
2089   char      sam_name[256];
2090   char      *attr_array[3];
2091   char      *mitMoiraId_v[] = {NULL, NULL};
2092   char      *name_v[] = {NULL, NULL};
2093   char      *samAccountName_v[] = {NULL, NULL};
2094   char      *groupTypeControl_v[] = {NULL, NULL};
2095   u_int     groupTypeControl = ADS_GROUP_TYPE_GLOBAL_GROUP;
2096   char      groupTypeControlStr[80];
2097   int       n;
2098   int       i;
2099   int       rc;
2100   LK_ENTRY  *group_base;
2101   int       group_count;
2102
2103   if (!check_string(before_group_name))
2104     {
2105       com_err(whoami, 0, "Unable to process invalid LDAP list name %s", before_group_name);
2106       return(AD_INVALID_NAME);
2107     }
2108   if (!check_string(after_group_name))
2109     {
2110       com_err(whoami, 0, "Unable to process invalid LDAP list name %s", after_group_name);
2111       return(AD_INVALID_NAME);
2112     }
2113
2114   group_count = 0;
2115   group_base = NULL;
2116   if (rc = ad_get_group(ldap_handle, dn_path, before_group_name, 
2117                         before_group_membership, 
2118                         MoiraId, "distinguishedName", &group_base, 
2119                         &group_count, filter))
2120     return(rc);
2121
2122   if (group_count == 0)
2123     {
2124       return(AD_NO_GROUPS_FOUND);
2125     }
2126   if (group_count != 1)
2127     {
2128       com_err(whoami, 0,
2129               "Unable to process multiple groups with MoiraId = %s exist in the AD",
2130               MoiraId);
2131       return(AD_MULTIPLE_GROUPS_FOUND);
2132     }
2133   strcpy(old_dn, group_base->value);
2134
2135   linklist_free(group_base);
2136   group_base = NULL;
2137   group_count = 0;
2138   attr_array[0] = "sAMAccountName";
2139   attr_array[1] = NULL;
2140   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
2141                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
2142     {
2143       com_err(whoami, 0, "Unable to get list %s dn : %s",
2144               after_group_name, ldap_err2string(rc));
2145       return(rc);
2146     }
2147   if (group_count != 1)
2148     {
2149       com_err(whoami, 0,
2150               "Unable to get sAMAccountName for group %s", 
2151               before_group_name);
2152       return(AD_LDAP_FAILURE);
2153     }
2154
2155   strcpy(sam_name, group_base->value);
2156   linklist_free(group_base);
2157   group_base = NULL;
2158   group_count = 0;
2159
2160   sprintf(new_dn_path, "%s,%s", after_group_ou, dn_path);
2161   sprintf(new_dn, "cn=%s", after_group_name);
2162   if ((rc = ldap_rename_s(ldap_handle, old_dn, new_dn, new_dn_path,
2163                           TRUE, NULL, NULL)) != LDAP_SUCCESS)
2164     {
2165       com_err(whoami, 0, "Unable to rename list from %s to %s : %s",
2166               before_group_name, after_group_name, ldap_err2string(rc));
2167       return(rc);
2168     }
2169
2170   name_v[0] = after_group_name;
2171   if (!strncmp(&sam_name[strlen(sam_name) - strlen("_group")], "_group", strlen("_group")))
2172     {
2173       sprintf(sam_name, "%s_group", after_group_name);
2174     }
2175   else
2176     {
2177       com_err(whoami, 0, "Unable to rename list from %s to %s : sAMAccountName not found",
2178               before_group_name, after_group_name);
2179       return(rc);
2180     }
2181   samAccountName_v[0] = sam_name;
2182   if (after_security_flag)
2183     groupTypeControl |= ADS_GROUP_TYPE_SECURITY_ENABLED;
2184   sprintf(groupTypeControlStr, "%ld", groupTypeControl);
2185   groupTypeControl_v[0] = groupTypeControlStr;
2186   mitMoiraId_v[0] = MoiraId;
2187
2188   sprintf(new_dn, "cn=%s,%s,%s", after_group_name, after_group_ou, dn_path);
2189   rc = attribute_update(ldap_handle, new_dn, after_desc, "description", after_group_name);
2190   n = 0;
2191   ADD_ATTR("samAccountName", samAccountName_v, LDAP_MOD_REPLACE);
2192   ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
2193   ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
2194   ADD_ATTR("groupType", groupTypeControl_v, LDAP_MOD_REPLACE);
2195   mods[n] = NULL;
2196   if ((rc = ldap_modify_s(ldap_handle, new_dn, mods)) != LDAP_SUCCESS)
2197     {
2198       com_err(whoami, 0, "Unable to modify list data for %s after renaming: %s",
2199               after_group_name, ldap_err2string(rc));
2200     }
2201   for (i = 0; i < n; i++)
2202     free(mods[i]);
2203   return(rc);
2204 }
2205
2206 int group_create(int ac, char **av, void *ptr)
2207 {
2208   LDAPMod *mods[20];
2209   LK_ENTRY  *group_base;
2210   char new_dn[256];
2211   char group_ou[256];
2212   char new_group_name[256];
2213   char sam_group_name[256];
2214   char cn_group_name[256];
2215   char *cn_v[] = {NULL, NULL};
2216   char *objectClass_v[] = {"top", "group", NULL};
2217   char info[256];
2218   char *samAccountName_v[] = {NULL, NULL};
2219   char *altSecurityIdentities_v[] = {NULL, NULL};
2220   char *member_v[] = {NULL, NULL};
2221   char *name_v[] = {NULL, NULL};
2222   char *desc_v[] = {NULL, NULL};
2223   char *info_v[] = {NULL, NULL};
2224   char *mitMoiraId_v[] = {NULL, NULL};
2225   char *groupTypeControl_v[] = {NULL, NULL};
2226   char groupTypeControlStr[80];
2227   char group_membership[1];
2228   int  i;
2229   int  security_flag;
2230   u_int groupTypeControl = ADS_GROUP_TYPE_GLOBAL_GROUP;
2231   int  n;
2232   int  rc;
2233   int  group_count;
2234   int  updateGroup;
2235   char filter[128];
2236   char *attr_array[3];
2237   char **call_args;
2238
2239   call_args = ptr;
2240
2241   if (!check_string(av[L_NAME]))
2242     {
2243       com_err(whoami, 0, "Unable to process invalid LDAP list name %s", av[L_NAME]);
2244       return(AD_INVALID_NAME);
2245     }
2246
2247   updateGroup = (int)call_args[4];
2248   memset(group_ou, 0, sizeof(group_ou));
2249   memset(group_membership, 0, sizeof(group_membership));
2250   security_flag = 0;
2251   get_group_membership(group_membership, group_ou, &security_flag, av);
2252   strcpy(new_group_name, av[L_NAME]);
2253   sprintf(new_dn, "cn=%s,%s,%s", new_group_name, group_ou, call_args[1]);
2254   if (security_flag)
2255     groupTypeControl |= ADS_GROUP_TYPE_SECURITY_ENABLED;
2256   
2257   sprintf(sam_group_name, "%s_group", av[L_NAME]);
2258
2259   if (!updateGroup)
2260     {
2261
2262       sprintf(groupTypeControlStr, "%ld", groupTypeControl);
2263       groupTypeControl_v[0] = groupTypeControlStr;
2264
2265       strcpy(cn_group_name, av[L_NAME]);
2266
2267       samAccountName_v[0] = sam_group_name;
2268       name_v[0] = new_group_name;
2269       cn_v[0] = new_group_name;
2270
2271       n = 0;
2272       ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
2273       ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2274       ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
2275       ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2276       ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2277       if (strlen(av[L_DESC]) != 0)
2278         {
2279           desc_v[0] = av[L_DESC];
2280           ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2281         }
2282       ADD_ATTR("groupType", groupTypeControl_v, LDAP_MOD_ADD);
2283       if (strlen(av[L_ACE_NAME]) != 0)
2284         {
2285           sprintf(info, "The Administrator of this list is: %s", av[L_ACE_NAME]);
2286           info_v[0] = info;
2287           ADD_ATTR("info", info_v, LDAP_MOD_ADD);
2288         }
2289       if (strlen(call_args[5]) != 0)
2290         {
2291           mitMoiraId_v[0] = call_args[5];
2292           ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_ADD);
2293         }
2294       mods[n] = NULL;
2295
2296       rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
2297
2298       for (i = 0; i < n; i++)
2299         free(mods[i]);
2300       if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2301         {
2302           com_err(whoami, 0, "Unable to create list %s in AD : %s",
2303                   av[L_NAME], ldap_err2string(rc));
2304           callback_rc = rc;
2305           return(rc);
2306         }
2307     }
2308   if ((rc == LDAP_ALREADY_EXISTS) || (updateGroup))
2309     {
2310       rc = attribute_update((LDAP *)call_args[0], new_dn, av[L_DESC], "description", av[L_NAME]);
2311       sprintf(info, "The Administrator of this list is: %s", av[L_ACE_NAME]);
2312       rc = attribute_update((LDAP *)call_args[0], new_dn, info, "info", av[L_NAME]);
2313       n = 0;
2314       if (strlen(call_args[5]) != 0)
2315         {
2316           mitMoiraId_v[0] = call_args[5];
2317           ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
2318         }
2319       if (!(atoi(av[L_ACTIVE])))
2320         {
2321           member_v[0] = NULL;
2322           ADD_ATTR("member", member_v, LDAP_MOD_REPLACE);
2323         }
2324       mods[n] = NULL;
2325       rc = LDAP_SUCCESS;
2326       if (n != 0)
2327         {
2328           rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
2329           for (i = 0; i < n; i++)
2330               free(mods[i]);
2331           if (rc != LDAP_SUCCESS)
2332             {
2333               com_err(whoami, 0, "Unable to update list %s in AD : %s",
2334                       av[L_NAME], ldap_err2string(rc));
2335               callback_rc = rc;
2336               return(rc);
2337             }
2338         }
2339     }
2340
2341   ProcessGroupSecurity((LDAP *)call_args[0], call_args[1], av[L_NAME], 
2342                        atoi(av[L_HIDDEN]),  av[L_ACE_TYPE], av[L_ACE_NAME]);
2343
2344   sprintf(filter, "(sAMAccountName=%s)", sam_group_name);
2345   if (strlen(call_args[5]) != 0)
2346     sprintf(filter, "(&(objectClass=group)(mitMoiraId=%s))", call_args[5]);
2347   attr_array[0] = "objectSid";
2348   attr_array[1] = NULL;
2349   group_count = 0;
2350   group_base = NULL;
2351   if ((rc = linklist_build((LDAP *)call_args[0], call_args[1], filter, attr_array, 
2352                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
2353     {
2354       if (group_count != 1)
2355         {
2356           if (strlen(call_args[5]) != 0)
2357             {
2358               linklist_free(group_base);
2359               group_count = 0;
2360               group_base = NULL;
2361               sprintf(filter, "(sAMAccountName=%s)", sam_group_name);
2362               rc = linklist_build((LDAP *)call_args[0], call_args[1], filter, 
2363                                   attr_array, &group_base, &group_count, LDAP_SCOPE_SUBTREE);
2364             }
2365         }
2366       if (group_count == 1)
2367         {
2368           (*sid_ptr) = group_base;
2369           (*sid_ptr)->member = strdup(av[L_NAME]);
2370           (*sid_ptr)->type = (char *)GROUPS;
2371           sid_ptr = &(*sid_ptr)->next;
2372         }
2373       else
2374         {
2375           if (group_base != NULL)
2376             linklist_free(group_base);
2377         }
2378     }
2379   else
2380     {
2381       if (group_base != NULL)
2382         linklist_free(group_base);
2383     }
2384   return(LDAP_SUCCESS);
2385 }
2386
2387 int ProcessGroupSecurity(LDAP *ldap_handle, char *dn_path, char *TargetGroupName, 
2388                          int HiddenGroup, char *AceType, char *AceName)
2389 {
2390   char          filter_exp[1024];
2391   char          *attr_array[5];
2392   char          search_path[512];
2393   char          root_ou[128];
2394   char          TemplateDn[512];
2395   char          TemplateSamName[128];
2396   char          TargetDn[512];
2397   char          TargetSamName[128];
2398   char          AceSamAccountName[128];
2399   char          AceDn[256];
2400   unsigned char AceSid[128];
2401   unsigned char UserTemplateSid[128];
2402   char          acBERBuf[N_SD_BER_BYTES];
2403   char          GroupSecurityTemplate[256];
2404   int           AceSidCount;
2405   int           UserTemplateSidCount;
2406   int           group_count;
2407   int           n;
2408   int           i;
2409   int           rc;
2410   int           nVal;
2411   ULONG         dwInfo;
2412   int           array_count = 0;
2413   LDAPMod       *mods[20];
2414   LK_ENTRY      *group_base;
2415   LDAP_BERVAL   **ppsValues;
2416   LDAPControl sControl = {"1.2.840.113556.1.4.801",
2417                           { N_SD_BER_BYTES, acBERBuf },
2418                           TRUE
2419                          };
2420   LDAPControl *apsServerControls[] = {&sControl, NULL};
2421   LDAPMessage *psMsg;
2422
2423   dwInfo = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION;
2424   BEREncodeSecurityBits(dwInfo, acBERBuf);
2425
2426   sprintf(search_path, "%s,%s", group_ou_root, dn_path);
2427   sprintf(filter_exp, "(sAMAccountName=%s_group)", TargetGroupName);
2428   attr_array[0] = "sAMAccountName";
2429   attr_array[1] = NULL;
2430   group_count = 0;
2431   group_base = NULL;
2432   if ((rc = linklist_build(ldap_handle, search_path, filter_exp, attr_array, 
2433                                &group_base, &group_count, LDAP_SCOPE_SUBTREE) != 0))
2434     return(1);
2435   if (group_count != 1)
2436     {
2437       linklist_free(group_base);
2438       return(1);
2439     }
2440   strcpy(TargetDn, group_base->dn);
2441   strcpy(TargetSamName, group_base->value);
2442   linklist_free(group_base);
2443   group_base = NULL;
2444   group_count = 0;
2445
2446   UserTemplateSidCount = 0;
2447   memset(UserTemplateSid, '\0', sizeof(UserTemplateSid));
2448   memset(AceSamAccountName, '\0', sizeof(AceSamAccountName));
2449   memset(AceSid, '\0', sizeof(AceSid));
2450   AceSidCount = 0;
2451   group_base = NULL;
2452   group_count = 0;
2453   if (strlen(AceName) != 0)
2454     {
2455       if (!strcmp(AceType, "LIST"))
2456         {
2457           sprintf(AceSamAccountName, "%s_group", AceName);
2458           strcpy(root_ou, group_ou_root);
2459         }
2460       else if (!strcmp(AceType, "USER"))
2461         {
2462           sprintf(AceSamAccountName, "%s", AceName);
2463           strcpy(root_ou, user_ou);
2464         }
2465       if (strlen(AceSamAccountName) != 0)
2466         {
2467           sprintf(search_path, "%s", dn_path);
2468           sprintf(filter_exp, "(sAMAccountName=%s)", AceSamAccountName);
2469           attr_array[0] = "objectSid";
2470           attr_array[1] = NULL;
2471           group_count = 0;
2472           group_base = NULL;
2473           if ((rc = linklist_build(ldap_handle, search_path, filter_exp, attr_array, 
2474                                    &group_base, &group_count, LDAP_SCOPE_SUBTREE) != 0))
2475             return(1);
2476           if (group_count == 1)
2477             {
2478               strcpy(AceDn, group_base->dn);
2479               AceSidCount = group_base->length;
2480               memcpy(AceSid, group_base->value, AceSidCount);
2481             }
2482           linklist_free(group_base);
2483           group_base = NULL;
2484           group_count = 0;
2485         }
2486     }
2487   if (AceSidCount == 0)
2488     {
2489       com_err(whoami, 0, "Group %s: Administrator: %s, Type: %s - does not have an AD SID.", TargetGroupName, AceName, AceType);
2490       com_err(whoami, 0, "   Non-admin security group template will be used.");
2491     }
2492   else
2493     {
2494       sprintf(search_path, "%s,%s", security_template_ou, dn_path);
2495       sprintf(filter_exp, "(sAMAccountName=%s)", "UserTemplate.u");
2496       attr_array[0] = "objectSid";
2497       attr_array[1] = NULL;
2498
2499       group_count = 0;
2500       group_base = NULL;
2501       if ((rc = linklist_build(ldap_handle, search_path, filter_exp, attr_array, 
2502                                    &group_base, &group_count, LDAP_SCOPE_SUBTREE) != 0))
2503         return(1);
2504       if ((rc != 0) || (group_count != 1))
2505         {
2506           com_err(whoami, 0, "Unable to process user security template: %s", "UserTemplate");
2507           AceSidCount = 0;
2508         }
2509       else
2510         {
2511           UserTemplateSidCount = group_base->length;
2512           memcpy(UserTemplateSid, group_base->value, UserTemplateSidCount);
2513         }
2514       linklist_free(group_base);
2515       group_base = NULL;
2516       group_count = 0;
2517     }
2518
2519   if (HiddenGroup)
2520     {
2521       if (AceSidCount == 0)
2522         {
2523           strcpy(GroupSecurityTemplate, HIDDEN_GROUP);
2524           sprintf(filter_exp, "(sAMAccountName=%s)", HIDDEN_GROUP);
2525         }
2526       else
2527         {
2528           strcpy(GroupSecurityTemplate, HIDDEN_GROUP_WITH_ADMIN);
2529           sprintf(filter_exp, "(sAMAccountName=%s)", HIDDEN_GROUP_WITH_ADMIN);
2530         }
2531     }
2532   else
2533     {
2534       if (AceSidCount == 0)
2535         {
2536           strcpy(GroupSecurityTemplate, NOT_HIDDEN_GROUP);
2537           sprintf(filter_exp, "(sAMAccountName=%s)", NOT_HIDDEN_GROUP);
2538         }
2539       else
2540         {
2541           strcpy(GroupSecurityTemplate, NOT_HIDDEN_GROUP_WITH_ADMIN);
2542           sprintf(filter_exp, "(sAMAccountName=%s)", NOT_HIDDEN_GROUP_WITH_ADMIN);
2543         }
2544     }
2545
2546   sprintf(search_path, "%s,%s", security_template_ou, dn_path);
2547   attr_array[0] = "sAMAccountName";
2548   attr_array[1] = NULL;
2549   group_count = 0;
2550   group_base = NULL;
2551   if ((rc = linklist_build(ldap_handle, search_path, filter_exp, attr_array, 
2552                                &group_base, &group_count, LDAP_SCOPE_SUBTREE) != 0))
2553     return(1);
2554   if (group_count != 1)
2555     {
2556       linklist_free(group_base);
2557       com_err(whoami, 0, "Unable to process group security template: %s - security not set", GroupSecurityTemplate);
2558       return(1);
2559     }
2560   strcpy(TemplateDn, group_base->dn);
2561   strcpy(TemplateSamName, group_base->value);
2562   linklist_free(group_base);
2563   group_base = NULL;
2564   group_count = 0;
2565
2566   sprintf(filter_exp, "(sAMAccountName=%s)", TemplateSamName);
2567   rc = ldap_search_ext_s(ldap_handle,
2568                          TemplateDn,
2569                          LDAP_SCOPE_SUBTREE,
2570                          filter_exp,
2571                          NULL,
2572                          0,
2573                          apsServerControls,
2574                          NULL,
2575                          NULL,
2576                          0,
2577                          &psMsg);
2578
2579   if ((psMsg = ldap_first_entry(ldap_handle, psMsg)) == NULL)
2580     {
2581       com_err(whoami, 0, "Unable to find group security template: %s - security not set", GroupSecurityTemplate);
2582       return(1);
2583     }
2584   ppsValues = ldap_get_values_len(ldap_handle, psMsg, "ntSecurityDescriptor");
2585   if (ppsValues == NULL)
2586     {
2587       com_err(whoami, 0, "Unable to find group security descriptor for group %s - security not set", GroupSecurityTemplate);
2588       return(1);
2589     }
2590
2591   if (AceSidCount != 0)
2592     {
2593       for (nVal = 0; ppsValues[nVal] != NULL; nVal++)
2594         {
2595           for (i = 0; i < (int)(ppsValues[nVal]->bv_len - UserTemplateSidCount); i++)
2596             {
2597               if (!memcmp(&ppsValues[nVal]->bv_val[i], UserTemplateSid, UserTemplateSidCount))
2598                 {
2599                   memcpy(&ppsValues[nVal]->bv_val[i], AceSid, AceSidCount);
2600                   break;
2601                 }
2602             }
2603         }
2604     }
2605
2606   n = 0;
2607   ADD_ATTR("ntSecurityDescriptor", (char **)ppsValues, LDAP_MOD_REPLACE | LDAP_MOD_BVALUES);
2608   mods[n] = NULL;
2609
2610   rc = ldap_modify_s(ldap_handle, TargetDn, mods);
2611   for (i = 0; i < n; i++)
2612     free(mods[i]);
2613   ldap_value_free_len(ppsValues);
2614   ldap_msgfree(psMsg);
2615   if (rc != LDAP_SUCCESS)
2616     {
2617       com_err(whoami, 0, "Unable to set security settings for group %s : %s",
2618               TargetGroupName, ldap_err2string(rc));
2619       if (AceSidCount != 0)
2620         {
2621           com_err(whoami, 0, "Trying to set security for group %s without admin.",
2622                   TargetGroupName);
2623           if (rc = ProcessGroupSecurity(ldap_handle, dn_path, TargetGroupName, 
2624                                         HiddenGroup, "", ""))
2625             {
2626               com_err(whoami, 0, "Unable to set security for group %s.",
2627                       TargetGroupName);
2628               return(rc);
2629             }
2630         }
2631       return(rc);
2632     }
2633   return(rc);
2634 }
2635
2636 int group_delete(LDAP *ldap_handle, char *dn_path, char *group_name, 
2637                  char *group_membership, char *MoiraId)
2638 {
2639   LK_ENTRY  *group_base;
2640   char      temp[512];
2641   char      filter[128];
2642   int       group_count;
2643   int       rc;
2644
2645   if (!check_string(group_name))
2646     {
2647       com_err(whoami, 0, "Unable to process invalid LDAP list name %s", group_name);
2648       return(AD_INVALID_NAME);
2649     }
2650
2651   memset(filter, '\0', sizeof(filter));
2652   group_count = 0;
2653   group_base = NULL;
2654   sprintf(temp, "%s,%s", group_ou_root, dn_path);
2655   if (rc = ad_get_group(ldap_handle, temp, group_name, 
2656                         group_membership, MoiraId, 
2657                         "distinguishedName", &group_base, 
2658                         &group_count, filter))
2659     return(rc);
2660
2661   if (group_count == 1)
2662     {
2663       if ((rc = ldap_delete_s(ldap_handle, group_base->value)) != LDAP_SUCCESS)
2664         {
2665           linklist_free(group_base);
2666           com_err(whoami, 0, "Unable to delete list %s from AD : %s",
2667                   group_name, ldap_err2string(rc));
2668           return(rc);
2669         }
2670       linklist_free(group_base);
2671     }
2672   else
2673     {
2674       linklist_free(group_base);
2675       com_err(whoami, 0, "Unable to find list %s in AD.", group_name);
2676       return(AD_NO_GROUPS_FOUND);
2677     }
2678
2679   return(0);
2680 }
2681
2682 int BEREncodeSecurityBits(ULONG uBits, char *pBuffer)
2683 {
2684     *pBuffer++ = 0x30;
2685     *pBuffer++ = 0x03;
2686     *pBuffer++ = 0x02;
2687     *pBuffer++ = 0x00;
2688     return(N_SD_BER_BYTES);
2689 }
2690
2691 int process_lists(int ac, char **av, void *ptr)
2692 {
2693   int   rc;
2694   int   security_flag;
2695   char  group_ou[256];
2696   char  group_membership[2];
2697   char  **call_args;
2698
2699   call_args = ptr;
2700
2701   security_flag = 0;
2702   memset(group_ou, '\0', sizeof(group_ou));
2703   memset(group_membership, '\0', sizeof(group_membership));
2704   get_group_membership(group_membership, group_ou, &security_flag, av);
2705   rc = member_add((LDAP *)call_args[0], (char *)call_args[1], av[L_NAME],
2706                   group_ou, group_membership, call_args[2], 
2707                   (char *)call_args[3], "");
2708   return(0);
2709 }
2710
2711 int member_list_build(int ac, char **av, void *ptr)
2712 {
2713   LK_ENTRY  *linklist;
2714   char      temp[1024];
2715   char      **call_args;
2716
2717   call_args = ptr;
2718
2719   strcpy(temp, av[ACE_NAME]);
2720   if (!check_string(temp))
2721     return(0);
2722   if (!strcmp(av[ACE_TYPE], "USER"))
2723     {
2724       if (!((int)call_args[3] & MOIRA_USERS))
2725         return(0);
2726     }
2727   else if (!strcmp(av[ACE_TYPE], "STRING"))
2728     {
2729       if (!((int)call_args[3] & MOIRA_STRINGS))
2730         return(0);
2731       if (contact_create((LDAP *)call_args[0], call_args[1], temp, contact_ou))
2732         return(0);
2733     }
2734   else if (!strcmp(av[ACE_TYPE], "LIST"))
2735     {
2736       if (!((int)call_args[3] & MOIRA_LISTS))
2737         return(0);
2738     }
2739   else if (!strcmp(av[ACE_TYPE], "KERBEROS"))
2740     {
2741       if (!((int)call_args[3] & MOIRA_KERBEROS))
2742         return(0);
2743       if (contact_create((LDAP *)call_args[0], call_args[1], temp, kerberos_ou))
2744         return(0);
2745     }
2746   else
2747     return(0);
2748
2749   linklist = member_base;
2750   while (linklist)
2751     {
2752     if (!strcasecmp(temp, linklist->member))
2753       return(0);
2754     linklist = linklist->next;
2755     }
2756   linklist = calloc(1, sizeof(LK_ENTRY));
2757   linklist->op = 1;
2758   linklist->dn = NULL;
2759   linklist->list = calloc(1, strlen(call_args[2]) + 1);
2760   strcpy(linklist->list, call_args[2]);
2761   linklist->type = calloc(1, strlen(av[ACE_TYPE]) + 1);
2762   strcpy(linklist->type, av[ACE_TYPE]);
2763   linklist->member = calloc(1, strlen(temp) + 1);
2764   strcpy(linklist->member, temp);
2765   linklist->next = member_base;
2766   member_base = linklist;
2767   return(0);
2768 }
2769
2770 int member_remove(LDAP *ldap_handle, char *dn_path, char *group_name, 
2771                   char *group_ou, char *group_membership, char *user_name,
2772                   char *UserOu, char *MoiraId)
2773 {
2774   char        distinguished_name[1024];
2775   char        *modvalues[2];
2776   char        temp[256];
2777   char        filter[128];
2778   int         group_count;
2779   int         i;
2780   int         n;
2781   LDAPMod     *mods[20];
2782   LK_ENTRY    *group_base;
2783   ULONG       rc;
2784
2785   if (!check_string(group_name))
2786     return(AD_INVALID_NAME);
2787
2788   memset(filter, '\0', sizeof(filter));
2789   group_base = NULL;
2790   group_count = 0;
2791   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
2792                         group_membership, MoiraId, 
2793                         "distinguishedName", &group_base, 
2794                         &group_count, filter))
2795     return(rc);
2796
2797   if (group_count != 1)
2798     {
2799       com_err(whoami, 0, "Unable to find list %s in AD",
2800               group_name);
2801       linklist_free(group_base);
2802       group_base = NULL;
2803       group_count = 0;
2804       goto cleanup;
2805     }
2806   strcpy(distinguished_name, group_base->value);
2807   linklist_free(group_base);
2808   group_base = NULL;
2809   group_count = 0;
2810
2811   sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
2812   modvalues[0] = temp;
2813   modvalues[1] = NULL;
2814
2815   n = 0;
2816   ADD_ATTR("member", modvalues, LDAP_MOD_DELETE);
2817   mods[n] = NULL;
2818   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
2819   for (i = 0; i < n; i++)
2820     free(mods[i]);
2821   if (rc == LDAP_UNWILLING_TO_PERFORM)
2822     rc = LDAP_SUCCESS;
2823   if (rc != LDAP_SUCCESS)
2824     {
2825       com_err(whoami, 0, "Unable to modify list %s members : %s",
2826               group_name, ldap_err2string(rc));
2827       goto cleanup;
2828     }
2829
2830 cleanup:
2831   return(rc);
2832 }
2833
2834 int member_add(LDAP *ldap_handle, char *dn_path, char *group_name, 
2835                char *group_ou, char *group_membership, char *user_name, 
2836                char *UserOu, char *MoiraId)
2837 {
2838   char        distinguished_name[1024];
2839   char        *modvalues[2];
2840   char        temp[256];
2841   char        filter[128];
2842   int         group_count;
2843   int         n;
2844   int         i;
2845   LDAPMod     *mods[20];
2846   LK_ENTRY    *group_base;
2847   ULONG       rc;
2848
2849   if (!check_string(group_name))
2850     return(AD_INVALID_NAME);
2851
2852   rc = 0;
2853   memset(filter, '\0', sizeof(filter));
2854   group_base = NULL;
2855   group_count = 0;
2856   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
2857                         group_membership, MoiraId, 
2858                         "distinguishedName", &group_base, 
2859                         &group_count, filter))
2860     return(rc);
2861
2862   if (group_count != 1)
2863     {
2864       linklist_free(group_base);
2865       group_base = NULL;
2866       group_count = 0;
2867       com_err(whoami, 0, "Unable to find list %s in AD",
2868               group_name);
2869       return(AD_MULTIPLE_GROUPS_FOUND);
2870     }
2871
2872   strcpy(distinguished_name, group_base->value);
2873   linklist_free(group_base);
2874   group_base = NULL;
2875   group_count = 0;
2876
2877   sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
2878   modvalues[0] = temp;
2879   modvalues[1] = NULL;
2880
2881   n = 0;
2882   ADD_ATTR("member", modvalues, LDAP_MOD_ADD);
2883   mods[n] = NULL;
2884   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
2885   if (rc == LDAP_ALREADY_EXISTS)
2886     rc = LDAP_SUCCESS;
2887   if ((!strcmp(UserOu, contact_ou)) || (!strcmp(UserOu, kerberos_ou)))
2888     {
2889       if (rc == LDAP_UNWILLING_TO_PERFORM)
2890         rc = LDAP_SUCCESS;
2891     }
2892   for (i = 0; i < n; i++)
2893     free(mods[i]);
2894   if (rc != LDAP_SUCCESS)
2895     {
2896       com_err(whoami, 0, "Unable to add %s to list %s as a member : %s",
2897               user_name, group_name, ldap_err2string(rc));
2898     }
2899
2900   return(rc);
2901 }
2902
2903 int contact_create(LDAP *ld, char *bind_path, char *user, char *group_ou)
2904 {
2905   LDAPMod *mods[20];
2906   char new_dn[256];
2907   char cn_user_name[256];
2908   char contact_name[256];
2909   char *email_v[] = {NULL, NULL};
2910   char *cn_v[] = {NULL, NULL};
2911   char *contact_v[] = {NULL, NULL};
2912   char *objectClass_v[] = {"top", "person", 
2913                            "organizationalPerson", 
2914                            "contact", NULL};
2915   char *name_v[] = {NULL, NULL};
2916   char *desc_v[] = {NULL, NULL};
2917   int  n;
2918   int  rc;
2919   int  i;
2920
2921   if (!check_string(user))
2922     {
2923       com_err(whoami, 0, "Unable to process invalid LDAP name %s", user);
2924       return(AD_INVALID_NAME);
2925     }
2926   strcpy(contact_name, user);
2927   sprintf(cn_user_name,"CN=%s,%s,%s", contact_name, group_ou, bind_path);
2928   cn_v[0] = cn_user_name;
2929   contact_v[0] = contact_name;
2930   name_v[0] = user;
2931   desc_v[0] = "Auto account created by Moira";
2932   email_v[0] = user;
2933
2934   strcpy(new_dn, cn_user_name);
2935   n = 0;
2936   ADD_ATTR("cn", contact_v, LDAP_MOD_ADD);
2937   ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2938   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2939   ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2940   ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2941   if (!strcmp(group_ou, contact_ou))
2942     {
2943       ADD_ATTR("mail", email_v, LDAP_MOD_ADD);
2944     }
2945   mods[n] = NULL;
2946
2947   rc = ldap_add_ext_s(ld, new_dn, mods, NULL, NULL);
2948   for (i = 0; i < n; i++)
2949     free(mods[i]);
2950   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2951     {
2952       n = 0;
2953       ADD_ATTR("cn", contact_v, LDAP_MOD_ADD);
2954       ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2955       ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2956       ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2957       ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2958       mods[n] = NULL;
2959       rc = ldap_add_ext_s(ld, new_dn, mods, NULL, NULL);
2960       for (i = 0; i < n; i++)
2961         free(mods[i]);
2962     }
2963   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2964     {
2965       com_err(whoami, 0, "Unable to create contact %s : %s",
2966               user, ldap_err2string(rc));
2967       return(rc);
2968     }
2969   return(0);
2970 }
2971
2972 int user_update(LDAP *ldap_handle, char *dn_path, char *user_name,
2973                 char *Uid, char *MitId, char *MoiraId, int State,
2974                 char *WinHomeDir, char *WinProfileDir)
2975 {
2976   LDAPMod   *mods[20];
2977   LK_ENTRY  *group_base;
2978   int  group_count;
2979   char distinguished_name[512];
2980   char *mitMoiraId_v[] = {NULL, NULL};
2981   char *uid_v[] = {NULL, NULL};
2982   char *mitid_v[] = {NULL, NULL};
2983   char *homedir_v[] = {NULL, NULL};
2984   char *winProfile_v[] = {NULL, NULL};
2985   char *drives_v[] = {NULL, NULL};
2986   char *userAccountControl_v[] = {NULL, NULL};
2987   char userAccountControlStr[80];
2988   int  n;
2989   int  rc;
2990   int  i;
2991   int  OldUseSFU30;
2992   u_int userAccountControl = UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD | UF_PASSWD_CANT_CHANGE;
2993   char filter[128];
2994   char *attr_array[3];
2995   char temp[256];
2996
2997   if (!check_string(user_name))
2998     {
2999       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", user_name);
3000       return(AD_INVALID_NAME);
3001     }
3002
3003   group_count = 0;
3004   group_base = NULL;
3005
3006   if (strlen(MoiraId) != 0)
3007     {
3008       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
3009       attr_array[0] = "cn";
3010       attr_array[1] = NULL;
3011       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3012                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3013         {
3014           com_err(whoami, 0, "Unable to process user %s : %s",
3015                   user_name, ldap_err2string(rc));
3016           return(rc);
3017         }
3018     }
3019   if (group_count != 1)
3020     {
3021       linklist_free(group_base);
3022       group_base = NULL;
3023       group_count = 0;
3024       sprintf(filter, "(sAMAccountName=%s)", user_name);
3025       attr_array[0] = "cn";
3026       attr_array[1] = NULL;
3027       sprintf(temp, "%s,%s", user_ou, dn_path);
3028       if ((rc = linklist_build(ldap_handle, temp, filter, attr_array, 
3029                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3030         {
3031           com_err(whoami, 0, "Unable to process user %s : %s",
3032                   user_name, ldap_err2string(rc));
3033           return(rc);
3034         }
3035     }
3036
3037   if (group_count != 1)
3038     {
3039       com_err(whoami, 0, "Unable to find user %s in AD",
3040               user_name);
3041       linklist_free(group_base);
3042       return(AD_NO_USER_FOUND);
3043     }
3044   strcpy(distinguished_name, group_base->dn);
3045
3046   linklist_free(group_base);
3047   group_count = 0;
3048
3049   if ((strlen(MitId) != 0) && (MitId[0] == '9'))
3050     rc = attribute_update(ldap_handle, distinguished_name, MitId, "employeeID", user_name);
3051   else
3052     rc = attribute_update(ldap_handle, distinguished_name, "none", "employeeID", user_name);
3053   rc = attribute_update(ldap_handle, distinguished_name, Uid, "uid", user_name);
3054   rc = attribute_update(ldap_handle, distinguished_name, MoiraId, "mitMoiraId", user_name);
3055
3056   n = 0;
3057   if (!UseSFU30)
3058     {
3059       ADD_ATTR("uidNumber", uid_v, LDAP_MOD_REPLACE);
3060     }
3061   else
3062     {
3063       ADD_ATTR("msSFU30UidNumber", uid_v, LDAP_MOD_REPLACE);
3064     }
3065
3066
3067   if ((State != US_NO_PASSWD) && (State != US_REGISTERED))
3068     userAccountControl |= UF_ACCOUNTDISABLE;
3069   sprintf(userAccountControlStr, "%ld", userAccountControl);
3070   userAccountControl_v[0] = userAccountControlStr;
3071   ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_REPLACE);
3072
3073   n = SetHomeDirectory(ldap_handle, user_name, distinguished_name, WinHomeDir, 
3074                        WinProfileDir, homedir_v, winProfile_v,
3075                        drives_v, mods, LDAP_MOD_REPLACE, n);
3076
3077   mods[n] = NULL;
3078   if ((rc = ldap_modify_s(ldap_handle, distinguished_name, mods)) != LDAP_SUCCESS)
3079     {
3080         OldUseSFU30 = UseSFU30;
3081         SwitchSFU(mods, &UseSFU30, n);
3082         if (OldUseSFU30 != UseSFU30)
3083             rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
3084         if (rc)
3085         {
3086             com_err(whoami, 0, "Unable to modify user data for %s : %s",
3087                 user_name, ldap_err2string(rc));
3088         }
3089     }
3090   for (i = 0; i < n; i++)
3091     free(mods[i]);
3092   return(rc);
3093 }
3094
3095 int user_rename(LDAP *ldap_handle, char *dn_path, char *before_user_name, 
3096                 char *user_name)
3097 {
3098   LDAPMod *mods[20];
3099   char new_dn[256];
3100   char old_dn[256];
3101   char upn[256];
3102   char temp[128];
3103   char *userPrincipalName_v[] = {NULL, NULL};
3104   char *altSecurityIdentities_v[] = {NULL, NULL};
3105   char *name_v[] = {NULL, NULL};
3106   char *samAccountName_v[] = {NULL, NULL};
3107   int  n;
3108   int  rc;
3109   int  i;
3110
3111   if (!check_string(before_user_name))
3112     {
3113       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", before_user_name);
3114       return(AD_INVALID_NAME);
3115     }
3116   if (!check_string(user_name))
3117     {
3118       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", user_name);
3119       return(AD_INVALID_NAME);
3120     }
3121
3122   strcpy(user_name, user_name);
3123   sprintf(old_dn, "cn=%s,%s,%s", before_user_name, user_ou, dn_path);
3124   sprintf(new_dn, "cn=%s", user_name);
3125   if ((rc = ldap_rename_s(ldap_handle, old_dn, new_dn, NULL, TRUE, 
3126                            NULL, NULL)) != LDAP_SUCCESS)
3127     {
3128       com_err(whoami, 0, "Unable to rename user from %s to %s : %s",
3129               before_user_name, user_name, ldap_err2string(rc));
3130       return(rc);
3131     }
3132
3133   name_v[0] = user_name;
3134   sprintf(upn, "%s@%s", user_name, ldap_domain);
3135   userPrincipalName_v[0] = upn;
3136   sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
3137   altSecurityIdentities_v[0] = temp;
3138   samAccountName_v[0] = user_name;
3139
3140   n = 0;
3141   ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_REPLACE);
3142   ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_REPLACE);
3143   ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
3144   ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_REPLACE);
3145   mods[n] = NULL;
3146   sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, dn_path);
3147   if ((rc = ldap_modify_s(ldap_handle, new_dn, mods)) != LDAP_SUCCESS)
3148     {
3149       com_err(whoami, 0, "Unable to modify user data for %s after renaming : %s",
3150               user_name, ldap_err2string(rc));
3151     }
3152   for (i = 0; i < n; i++)
3153     free(mods[i]);
3154   return(rc);
3155 }
3156
3157 int filesys_process(LDAP *ldap_handle, char *dn_path, char *fs_name, 
3158                     char *fs_type, char *fs_pack, int operation)
3159 {
3160   char  distinguished_name[256];
3161   char  winPath[256];
3162   char  winProfile[256];
3163   char  filter[128];
3164   char  *attr_array[3];
3165   char  *homedir_v[] = {NULL, NULL};
3166   char  *winProfile_v[] = {NULL, NULL};
3167   char  *drives_v[] = {NULL, NULL};
3168   int   group_count;
3169   int   n;
3170   int   rc;
3171   int   i;
3172   LDAPMod   *mods[20];
3173   LK_ENTRY  *group_base;
3174
3175   if (!check_string(fs_name))
3176     {
3177       com_err(whoami, 0, "Unable to process invalid filesys name %s", fs_name);
3178       return(AD_INVALID_NAME);
3179     }
3180
3181   if (strcmp(fs_type, "AFS"))
3182     {
3183       com_err(whoami, 0, "Unable to process invalid filesys type %s", fs_type);
3184       return(AD_INVALID_FILESYS);
3185     }
3186
3187   group_count = 0;
3188   group_base = NULL;
3189   sprintf(filter, "(sAMAccountName=%s)", fs_name);
3190   attr_array[0] = "cn";
3191   attr_array[1] = NULL;
3192   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3193                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3194     {
3195       com_err(whoami, 0, "Unable to process filesys %s : %s",
3196               fs_name, ldap_err2string(rc));
3197       return(rc);
3198     }
3199
3200   if (group_count != 1)
3201     {
3202       linklist_free(group_base);
3203       com_err(whoami, 0, "Unable to find user %s in AD",
3204               fs_name);
3205       return(LDAP_NO_SUCH_OBJECT);
3206     }
3207   strcpy(distinguished_name, group_base->dn);
3208   linklist_free(group_base);
3209   group_count = 0;
3210
3211   n = 0;
3212   if (operation == LDAP_MOD_ADD)
3213     {
3214       memset(winPath, 0, sizeof(winPath));
3215       AfsToWinAfs(fs_pack, winPath);
3216       homedir_v[0] = winPath;
3217       drives_v[0] = "H:";
3218       memset(winProfile, 0, sizeof(winProfile));
3219       strcpy(winProfile, winPath);
3220       strcat(winProfile, "\\.winprofile");
3221       winProfile_v[0] = winProfile;
3222     }
3223   else
3224     {
3225       homedir_v[0] = NULL;
3226       drives_v[0] = NULL;
3227       winProfile_v[0] = NULL;
3228     }
3229   ADD_ATTR("profilePath", winProfile_v, operation);
3230   ADD_ATTR("homeDrive", drives_v, operation);
3231   ADD_ATTR("homeDirectory", homedir_v, operation);
3232   mods[n] = NULL;
3233
3234   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
3235   if (rc != LDAP_SUCCESS)
3236     {
3237       com_err(whoami, 0, "Unable to modify user data for filesys %s : %s",
3238               fs_name, ldap_err2string(rc));
3239     }
3240   for (i = 0; i < n; i++)
3241     free(mods[i]);
3242
3243   return(rc);
3244 }
3245
3246 int user_create(int ac, char **av, void *ptr)
3247 {
3248   LK_ENTRY  *group_base;
3249   LDAPMod *mods[20];
3250   char new_dn[256];
3251   char user_name[256];
3252   char sam_name[256];
3253   char upn[256];
3254   char *cn_v[] = {NULL, NULL};
3255   char *objectClass_v[] = {"top", "person", 
3256                            "organizationalPerson", 
3257                            "user", NULL};
3258
3259   char *samAccountName_v[] = {NULL, NULL};
3260   char *altSecurityIdentities_v[] = {NULL, NULL};
3261   char *mitMoiraId_v[] = {NULL, NULL};
3262   char *name_v[] = {NULL, NULL};
3263   char *desc_v[] = {NULL, NULL};
3264   char *userPrincipalName_v[] = {NULL, NULL};
3265   char *userAccountControl_v[] = {NULL, NULL};
3266   char *uid_v[] = {NULL, NULL};
3267   char *mitid_v[] = {NULL, NULL};
3268   char *homedir_v[] = {NULL, NULL};
3269   char *winProfile_v[] = {NULL, NULL};
3270   char *drives_v[] = {NULL, NULL};
3271   char userAccountControlStr[80];
3272   char temp[128];
3273   u_int userAccountControl = UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD | UF_PASSWD_CANT_CHANGE;
3274   int  n;
3275   int  rc;
3276   int  i;
3277   int  group_count;
3278   int  OldUseSFU30;
3279   char filter[128];
3280   char *attr_array[3];
3281   char **call_args;
3282   char WinHomeDir[1024];
3283   char WinProfileDir[1024];
3284
3285   call_args = ptr;
3286
3287   if (!check_string(av[U_NAME]))
3288     {
3289       callback_rc = AD_INVALID_NAME;
3290       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", av[U_NAME]);
3291       return(AD_INVALID_NAME);
3292     }
3293
3294   memset(WinHomeDir, '\0', sizeof(WinHomeDir));
3295   memset(WinProfileDir, '\0', sizeof(WinProfileDir));
3296   strcpy(WinHomeDir, av[U_WINHOMEDIR]);
3297   strcpy(WinProfileDir, av[U_WINPROFILEDIR]);
3298   strcpy(user_name, av[U_NAME]);
3299   sprintf(upn, "%s@%s", user_name, ldap_domain);
3300   sprintf(sam_name, "%s", av[U_NAME]);
3301   samAccountName_v[0] = sam_name;
3302   if ((atoi(av[U_STATE]) != US_NO_PASSWD) && (atoi(av[U_STATE]) != US_REGISTERED))
3303     userAccountControl |= UF_ACCOUNTDISABLE;
3304   sprintf(userAccountControlStr, "%ld", userAccountControl);
3305   userAccountControl_v[0] = userAccountControlStr;
3306   userPrincipalName_v[0] = upn;
3307
3308   cn_v[0] = user_name;
3309   name_v[0] = user_name;
3310   desc_v[0] = "Auto account created by Moira";
3311   sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
3312   altSecurityIdentities_v[0] = temp;    
3313   sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, call_args[1]);
3314
3315   n = 0;
3316   ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
3317   ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
3318   ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
3319   ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_ADD);
3320   ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_ADD);
3321   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
3322   ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
3323   ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
3324   if (strlen(call_args[2]) != 0)    
3325     {
3326       mitMoiraId_v[0] = call_args[2];
3327       ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_ADD);
3328     }
3329   ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_ADD);
3330   if (strlen(av[U_UID]) != 0)
3331     {
3332       uid_v[0] = av[U_UID];
3333       ADD_ATTR("uid", uid_v, LDAP_MOD_ADD);
3334       if (!UseSFU30)
3335         {
3336           ADD_ATTR("uidNumber", uid_v, LDAP_MOD_ADD);
3337         }
3338       else
3339         {
3340           ADD_ATTR("msSFU30UidNumber", uid_v, LDAP_MOD_ADD);
3341         }
3342     }
3343   if ((strlen(av[U_MITID]) != 0) && (av[U_MITID][0] == '9'))
3344       mitid_v[0] = av[U_MITID];
3345   else
3346       mitid_v[0] = "none";
3347   ADD_ATTR("employeeID", mitid_v, LDAP_MOD_ADD);
3348
3349   n = SetHomeDirectory((LDAP *)call_args[0], user_name, new_dn, WinHomeDir, 
3350                        WinProfileDir, homedir_v, winProfile_v,
3351                        drives_v, mods, LDAP_MOD_ADD, n);
3352
3353   mods[n] = NULL;
3354
3355   rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
3356   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
3357   {
3358       OldUseSFU30 = UseSFU30;
3359       SwitchSFU(mods, &UseSFU30, n);
3360       if (OldUseSFU30 != UseSFU30)
3361           rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
3362   }
3363
3364   for (i = 0; i < n; i++)
3365     free(mods[i]);
3366   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
3367     {
3368       com_err(whoami, 0, "Unable to create user %s : %s",
3369               user_name, ldap_err2string(rc));
3370       callback_rc = rc;
3371       return(rc);
3372     }
3373   if (rc == LDAP_SUCCESS)
3374     {
3375       if ((rc = set_password(sam_name, "", ldap_domain)) != 0)
3376         {
3377           com_err(whoami, 0, "Unable to set password for user %s : %ld",
3378                   user_name, rc);
3379         }
3380     }
3381   sprintf(filter, "(sAMAccountName=%s)", av[U_NAME]);
3382   if (strlen(call_args[2]) != 0)
3383     sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", call_args[2]);
3384   attr_array[0] = "objectSid";
3385   attr_array[1] = NULL;
3386   group_count = 0;
3387   group_base = NULL;
3388   if ((rc = linklist_build((LDAP *)call_args[0], call_args[1], filter, attr_array, 
3389                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
3390     {
3391       if (group_count != 1)
3392         {
3393           if (strlen(call_args[2]) != 0)
3394             {
3395               linklist_free(group_base);
3396               group_count = 0;
3397               group_base = NULL;
3398               sprintf(filter, "(sAMAccountName=%s)", av[U_NAME]);
3399               rc = linklist_build((LDAP *)call_args[0], call_args[1], filter, 
3400                                   attr_array, &group_base, &group_count, LDAP_SCOPE_SUBTREE);
3401             }
3402         }
3403       if (group_count == 1)
3404         {
3405           (*sid_ptr) = group_base;
3406           (*sid_ptr)->member = strdup(av[U_NAME]);
3407           (*sid_ptr)->type = (char *)GROUPS;
3408           sid_ptr = &(*sid_ptr)->next;
3409         }
3410       else
3411         {
3412           if (group_base != NULL)
3413             linklist_free(group_base);
3414         }
3415     }
3416   else
3417     {
3418       if (group_base != NULL)
3419         linklist_free(group_base);
3420     }
3421   return(0);
3422 }
3423
3424 int user_change_status(LDAP *ldap_handle, char *dn_path, 
3425                        char *user_name, char *MoiraId,
3426                        int operation)
3427 {
3428   char      filter[128];
3429   char      *attr_array[3];
3430   char      temp[256];
3431   char      distinguished_name[1024];
3432   char      **modvalues;
3433   char      *mitMoiraId_v[] = {NULL, NULL};
3434   LDAPMod   *mods[20];
3435   LK_ENTRY  *group_base;
3436   int       group_count;
3437   int       rc;
3438   int       i;
3439   int       n;
3440   ULONG     ulongValue;
3441
3442   if (!check_string(user_name))
3443     {
3444       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", user_name);
3445       return(AD_INVALID_NAME);
3446     }
3447
3448   group_count = 0;
3449   group_base = NULL;
3450
3451   if (strlen(MoiraId) != 0)
3452     {
3453       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
3454       attr_array[0] = "UserAccountControl";
3455       attr_array[1] = NULL;
3456       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3457                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3458         {
3459           com_err(whoami, 0, "Unable to process user %s : %s",
3460                   user_name, ldap_err2string(rc));
3461           return(rc);
3462         }
3463     }
3464   if (group_count != 1)
3465     {
3466       linklist_free(group_base);
3467       group_count = 0;
3468       group_base = NULL;
3469       sprintf(filter, "(sAMAccountName=%s)", user_name);
3470       attr_array[0] = "UserAccountControl";
3471       attr_array[1] = NULL;
3472       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3473                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3474         {
3475           com_err(whoami, 0, "Unable to process user %s : %s",
3476                   user_name, ldap_err2string(rc));
3477           return(rc);
3478         }
3479     }
3480
3481   if (group_count != 1)
3482     {
3483       linklist_free(group_base);
3484       com_err(whoami, 0, "Unable to find user %s in AD",
3485               user_name);
3486       return(LDAP_NO_SUCH_OBJECT);
3487     }
3488
3489   strcpy(distinguished_name, group_base->dn);
3490   ulongValue = atoi((*group_base).value);
3491   if (operation == MEMBER_DEACTIVATE)
3492     ulongValue |= UF_ACCOUNTDISABLE;
3493   else    
3494     ulongValue &= ~UF_ACCOUNTDISABLE;
3495   sprintf(temp, "%ld", ulongValue);
3496   if ((rc = construct_newvalues(group_base, group_count, (*group_base).value, 
3497                                 temp, &modvalues, REPLACE)) == 1)
3498     goto cleanup;
3499   linklist_free(group_base);
3500   group_base = NULL;
3501   group_count = 0;
3502   n = 0;
3503   ADD_ATTR("UserAccountControl", modvalues, LDAP_MOD_REPLACE);
3504   if (strlen(MoiraId) != 0)
3505     {
3506     mitMoiraId_v[0] = MoiraId;
3507     ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
3508     }
3509   mods[n] = NULL;
3510   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
3511   for (i = 0; i < n; i++)
3512     free(mods[i]);
3513   free_values(modvalues);
3514   if (rc != LDAP_SUCCESS)
3515     {
3516       com_err(whoami, 0, "Unable to change status of user %s : %s",
3517               user_name, ldap_err2string(rc));
3518     }
3519 cleanup:
3520   return(rc);
3521 }
3522
3523 int user_delete(LDAP *ldap_handle, char *dn_path, 
3524                 char *u_name, char *MoiraId)
3525 {
3526   char      filter[128];
3527   char      *attr_array[3];
3528   char      distinguished_name[1024];
3529   char      user_name[512];
3530   LK_ENTRY  *group_base;
3531   int       group_count;
3532   int       rc;
3533
3534   if (!check_string(u_name))
3535     return(AD_INVALID_NAME);
3536
3537   strcpy(user_name, u_name);
3538   group_count = 0;
3539   group_base = NULL;
3540
3541   if (strlen(MoiraId) != 0)
3542     {
3543       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
3544       attr_array[0] = "name";
3545       attr_array[1] = NULL;
3546       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3547                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3548         {
3549           com_err(whoami, 0, "Unable to process user %s : %s",
3550                   user_name, ldap_err2string(rc));
3551           goto cleanup;
3552         }
3553     }
3554   if (group_count != 1)
3555     {
3556       linklist_free(group_base);
3557       group_count = 0;
3558       group_base = NULL;
3559       sprintf(filter, "(sAMAccountName=%s)", user_name);
3560       attr_array[0] = "name";
3561       attr_array[1] = NULL;
3562       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3563                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3564         {
3565           com_err(whoami, 0, "Unable to process user %s : %s",
3566                   user_name, ldap_err2string(rc));
3567           goto cleanup;
3568         }
3569     }
3570
3571   if (group_count != 1)
3572     {
3573       com_err(whoami, 0, "Unable to find user %s in AD",
3574               user_name);
3575       goto cleanup;
3576     }
3577
3578   strcpy(distinguished_name, group_base->dn);
3579   if (rc = ldap_delete_s(ldap_handle, distinguished_name))
3580     {
3581       com_err(whoami, 0, "Unable to process user %s : %s",
3582               user_name, ldap_err2string(rc));
3583     }
3584
3585 cleanup:
3586   linklist_free(group_base);
3587   return(0);
3588 }
3589
3590 void linklist_free(LK_ENTRY *linklist_base)
3591 {
3592   LK_ENTRY *linklist_previous;
3593
3594   while (linklist_base != NULL)
3595     {
3596       if (linklist_base->dn != NULL)
3597         free(linklist_base->dn);
3598       if (linklist_base->attribute != NULL)
3599         free(linklist_base->attribute);
3600       if (linklist_base->value != NULL)
3601         free(linklist_base->value);
3602       if (linklist_base->member != NULL)
3603         free(linklist_base->member);
3604       if (linklist_base->type != NULL)
3605         free(linklist_base->type);
3606       if (linklist_base->list != NULL)
3607         free(linklist_base->list);
3608       linklist_previous = linklist_base;
3609       linklist_base = linklist_previous->next;
3610       free(linklist_previous);
3611     }
3612 }
3613
3614 void free_values(char **modvalues)
3615 {
3616   int i;
3617
3618   i = 0;
3619   if (modvalues != NULL)
3620     {
3621     while (modvalues[i] != NULL)
3622       {
3623         free(modvalues[i]);
3624         modvalues[i] = NULL;
3625         ++i;
3626       }
3627     free(modvalues);
3628   }
3629 }
3630
3631 int sid_update(LDAP *ldap_handle, char *dn_path)
3632 {
3633   LK_ENTRY      *ptr;
3634   int           rc;
3635   unsigned char temp[126];
3636   char          *av[3];
3637
3638   ptr = sid_base;
3639
3640   while (ptr != NULL)
3641     {
3642       memset(temp, 0, sizeof(temp));
3643       convert_b_to_a(temp, ptr->value, ptr->length);
3644       if (!ptr->member)
3645         continue;
3646       av[0] = ptr->member;
3647       av[1] = temp;
3648       if (ptr->type == (char *)GROUPS)
3649         {
3650           ptr->type = NULL;
3651           rc = mr_query("add_list_sid_by_name", 2, av, NULL, NULL);
3652         }
3653       else if (ptr->type == (char *)USERS)
3654         {
3655           ptr->type = NULL;
3656           rc = mr_query("add_user_sid_by_login", 2, av, NULL, NULL);
3657         }
3658       ptr = ptr->next;
3659     }
3660   return(0);
3661 }
3662
3663 void convert_b_to_a(char *string, UCHAR *binary, int length)
3664 {
3665   int   i;
3666   int   j;
3667   UCHAR tmp;
3668
3669   j = 0;
3670   for (i = 0; i < length; i++)
3671     {
3672       tmp = binary[i];
3673       string[j] = tmp;
3674       string[j] >>= 4;
3675       string[j] &= 0x0f;
3676       string[j] += 0x30;
3677       if (string[j] > '9')
3678         string[j] += 0x27;
3679       ++j;
3680       string[j] = tmp & 0x0f;
3681       string[j] += 0x30;
3682       if (string[j] > '9')
3683         string[j] += 0x27;
3684       j++;
3685     }
3686   string[j] = 0;
3687 }
3688
3689 static int illegalchars[] = {
3690   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
3691   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
3692   1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, /* SPACE - / */
3693   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 0 - ? */
3694   0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
3695   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* P - _ */
3696   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
3697   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
3698   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3699   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3700   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3701   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3702   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3703   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3704   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3705   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3706 };
3707
3708 int check_string(char *s)
3709 {
3710   char  character;
3711
3712   for (; *s; s++)
3713     {
3714       character = *s;
3715       if (isupper(character))
3716         character = tolower(character);
3717       if (illegalchars[(unsigned) character])
3718         return 0;
3719     }
3720   return 1;
3721 }
3722
3723 int check_container_name(char *s)
3724 {
3725   char  character;
3726
3727   for (; *s; s++)
3728     {
3729       character = *s;
3730       if (isupper(character))
3731         character = tolower(character);
3732
3733           if (character == ' ')
3734                   continue;
3735       if (illegalchars[(unsigned) character])
3736         return 0;
3737     }
3738   return 1;
3739 }
3740
3741 int mr_connect_cl(char *server, char *client, int version, int auth)
3742 {
3743   int   status;
3744   char  *motd;
3745   char  temp[128];
3746
3747   status = mr_connect(server);
3748   if (status)
3749     {
3750       com_err(whoami, status, "while connecting to Moira");
3751       return status;
3752     }
3753
3754   status = mr_motd(&motd);
3755   if (status)
3756     {
3757       mr_disconnect();
3758       com_err(whoami, status, "while checking server status");
3759       return status;
3760     }
3761   if (motd)
3762     {
3763       sprintf(temp, "The Moira server is currently unavailable: %s", motd);
3764       com_err(whoami, status, temp);
3765       mr_disconnect();
3766       return status;
3767     }
3768
3769   status = mr_version(version);
3770   if (status)
3771     {
3772       if (status == MR_UNKNOWN_PROC)
3773         {
3774           if (version > 2)
3775             status = MR_VERSION_HIGH;
3776           else
3777             status = MR_SUCCESS;
3778         }
3779
3780       if (status == MR_VERSION_HIGH)
3781         {
3782           com_err(whoami, 0, "Warning: This client is running newer code than the server.");
3783                   com_err(whoami, 0, "Some operations may not work.");
3784         }
3785       else if (status && status != MR_VERSION_LOW)
3786         {
3787           com_err(whoami, status, "while setting query version number.");
3788           mr_disconnect();
3789           return status;
3790         }
3791     }
3792
3793   if (auth)
3794     {
3795       status = mr_auth(client);
3796       if (status)
3797         {
3798           com_err(whoami, status, "while authenticating to Moira.");
3799           mr_disconnect();
3800           return status;
3801         }
3802     }
3803
3804   return MR_SUCCESS;
3805 }
3806
3807 void AfsToWinAfs(char* path, char* winPath)
3808 {
3809     char* pathPtr;
3810     char* winPathPtr;
3811     strcpy(winPath, WINAFS);
3812     pathPtr = path + strlen(AFS);
3813     winPathPtr = winPath + strlen(WINAFS);
3814
3815     while (*pathPtr)
3816     {
3817         if (*pathPtr == '/')
3818           *winPathPtr = '\\';
3819         else
3820           *winPathPtr = *pathPtr;
3821
3822         pathPtr++;
3823         winPathPtr++;
3824     }
3825 }
3826
3827 int GetAceInfo(int ac, char **av, void *ptr)
3828 {
3829   char **call_args;
3830   int   security_flag;
3831
3832   call_args = ptr;
3833
3834   strcpy(call_args[0], av[L_ACE_TYPE]);
3835   strcpy(call_args[1], av[L_ACE_NAME]);
3836   security_flag = 0;
3837   get_group_membership(call_args[2], call_args[3], &security_flag, av);
3838   return(LDAP_SUCCESS);
3839
3840 }
3841
3842 int checkADname(LDAP *ldap_handle, char *dn_path, char *Name)
3843 {
3844   char filter[128];
3845   char *attr_array[3];
3846   int  group_count;
3847   int  rc;
3848   LK_ENTRY  *group_base;
3849
3850   group_count = 0;
3851   group_base = NULL;
3852
3853   sprintf(filter, "(sAMAccountName=%s)", Name);
3854   attr_array[0] = "sAMAccountName";
3855   attr_array[1] = NULL;
3856   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3857                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3858     {
3859       com_err(whoami, 0, "Unable to process ACE name %s : %s",
3860               Name, ldap_err2string(rc));
3861       return(1);
3862     }
3863
3864   linklist_free(group_base);
3865   group_base = NULL;
3866   if (group_count == 0)
3867     return(0);
3868   return(1);
3869 }
3870
3871 #define MAX_ACE 7
3872
3873 int ProcessAce(LDAP *ldap_handle, char *dn_path, char *Name, char *Type, int UpdateGroup, int *ProcessGroup)
3874 {
3875   char  *av[2];
3876   char  GroupName[256];
3877   char  *call_args[7];
3878   int   rc;
3879   char  *AceInfo[4];
3880   char  AceType[32];
3881   char  AceName[128];
3882   char  AceMembership[2];
3883   char  AceOu[256];
3884   char  temp[128];
3885
3886   strcpy(GroupName, Name);
3887
3888   if (strcasecmp(Type, "LIST"))
3889     return(1);
3890   while (1)
3891     {
3892       av[0] = GroupName;
3893       AceInfo[0] = AceType;
3894       AceInfo[1] = AceName;
3895       AceInfo[2] = AceMembership;
3896       AceInfo[3] = AceOu;
3897       memset(AceType, '\0', sizeof(AceType));
3898       memset(AceName, '\0', sizeof(AceName));
3899       memset(AceMembership, '\0', sizeof(AceMembership));
3900       memset(AceOu, '\0', sizeof(AceOu));
3901       callback_rc = 0;
3902       if (rc = mr_query("get_list_info", 1, av, GetAceInfo, AceInfo))
3903         {
3904           com_err(whoami, 0, "Unable to get ACE info for list %s : %s", GroupName, error_message(rc));
3905           return(1);
3906         }
3907       if (callback_rc)
3908         {
3909           com_err(whoami, 0, "Unable to get ACE info for list %s", GroupName);
3910           return(1);
3911         }
3912       if ((strcasecmp(AceType, "USER")) && (strcasecmp(AceType, "LIST")))
3913         return(0);
3914       strcpy(temp, AceName);
3915       if (!strcasecmp(AceType, "LIST"))
3916         sprintf(temp, "%s_group", AceName);
3917       if (!UpdateGroup)
3918         {
3919           if (checkADname(ldap_handle, dn_path, temp))
3920             return(0);
3921           (*ProcessGroup) = 1;
3922         }
3923       if (!strcasecmp(AceInfo[0], "LIST"))
3924         {
3925           if (make_new_group(ldap_handle, dn_path, "", AceName, AceOu, AceMembership, 0, UpdateGroup))
3926             return(1);
3927         }
3928       else if (!strcasecmp(AceInfo[0], "USER"))
3929         {
3930           av[0] = AceName;
3931           call_args[0] = (char *)ldap_handle;
3932           call_args[1] = dn_path;
3933           call_args[2] = "";
3934           call_args[3] = NULL;
3935           sid_base = NULL;
3936           sid_ptr = &sid_base;
3937           callback_rc = 0;
3938           if (rc = mr_query("get_user_account_by_login", 1, av, user_create, call_args))
3939             {
3940               com_err(whoami, 0, "Unable to process user ACE %s for group %s.", AceName, Name);
3941               return(1);
3942             }
3943           if (callback_rc)
3944             {
3945               com_err(whoami, 0, "Unable to process user Ace %s for group %s", AceName, Name);
3946               return(1);
3947             }
3948           if (sid_base != NULL)
3949             {
3950               sid_update(ldap_handle, dn_path);
3951               linklist_free(sid_base);
3952               sid_base = NULL;
3953             }
3954           return(0);
3955         }
3956       else
3957         return(1);
3958       if (!strcasecmp(AceType, "LIST"))
3959         {
3960           if (!strcasecmp(GroupName, AceName))
3961             return(0);
3962         }
3963       strcpy(GroupName, AceName);
3964     }
3965   return(1);
3966 }
3967
3968 int make_new_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
3969                    char *group_name, char *group_ou, char *group_membership, 
3970                    int group_security_flag, int updateGroup)
3971 {
3972   char  *av[3];
3973   char  *call_args[7];
3974   int   rc;
3975
3976   av[0] = group_name;
3977   call_args[0] = (char *)ldap_handle;
3978   call_args[1] = dn_path;
3979   call_args[2] = group_name;
3980   call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
3981   call_args[4] = (char *)updateGroup;
3982   call_args[5] = MoiraId;
3983   call_args[6] = NULL;
3984   sid_base = NULL;
3985   sid_ptr = &sid_base;
3986   callback_rc = 0;
3987   if (rc = mr_query("get_list_info", 1, av, group_create, call_args))
3988     {
3989       moira_disconnect();
3990       com_err(whoami, 0, "Unable to create list %s : %s", group_name, error_message(rc));
3991       return(rc);
3992     }
3993   if (callback_rc)
3994     {
3995       moira_disconnect();
3996       com_err(whoami, 0, "Unable to create list %s", group_name);
3997       return(callback_rc);
3998     }
3999
4000   if (sid_base != NULL)
4001     {
4002       sid_update(ldap_handle, dn_path);
4003       linklist_free(sid_base);
4004       sid_base = NULL;
4005     }
4006   return(0);
4007 }
4008
4009 int populate_group(LDAP *ldap_handle, char *dn_path, char *group_name, 
4010                    char *group_ou, char *group_membership, 
4011                    int group_security_flag, char *MoiraId)
4012 {
4013   char      *av[3];
4014   char      *call_args[7];
4015   char      *pUserOu;
4016   LK_ENTRY  *ptr;
4017   int       rc;
4018
4019   com_err(whoami, 0, "Populating group %s", group_name);
4020   av[0] = group_name;
4021   call_args[0] = (char *)ldap_handle;
4022   call_args[1] = dn_path;
4023   call_args[2] = group_name;
4024   call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
4025   call_args[4] = NULL;
4026   member_base = NULL;
4027   if (rc = mr_query("get_end_members_of_list", 1, av,
4028                     member_list_build, call_args))
4029     {
4030       com_err(whoami, 0, "Unable to populate list %s : %s", 
4031               group_name, error_message(rc));
4032       return(3);
4033     }
4034   if (member_base != NULL)
4035     {
4036       ptr = member_base;
4037       while (ptr != NULL)
4038         {
4039           if (!strcasecmp(ptr->type, "LIST"))
4040             {
4041               ptr = ptr->next;
4042               continue;
4043             }
4044           pUserOu = user_ou;
4045           if (!strcasecmp(ptr->type, "STRING"))
4046             {
4047               if (contact_create(ldap_handle, dn_path, ptr->member, contact_ou))
4048                 return(3);
4049               pUserOu = contact_ou;
4050             }
4051           else if (!strcasecmp(ptr->type, "KERBEROS"))
4052             {
4053               if (contact_create(ldap_handle, dn_path, ptr->member, kerberos_ou))
4054                 return(3);
4055               pUserOu = kerberos_ou;
4056             }
4057           rc = member_add(ldap_handle, dn_path, group_name,
4058                           group_ou, group_membership, ptr->member, 
4059                           pUserOu, MoiraId);
4060           ptr = ptr->next;
4061         }
4062       linklist_free(member_base);
4063       member_base = NULL;
4064     }
4065   return(0);
4066 }
4067
4068 int process_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
4069                   char *group_name, char *group_ou, char *group_membership, 
4070                   int group_security_flag, int type)
4071 {
4072   char      before_desc[512];
4073   char      before_name[256];
4074   char      before_group_ou[256];
4075   char      before_group_membership[2];
4076   char      distinguishedName[256];
4077   char      ad_distinguishedName[256];
4078   char      filter[128];
4079   char      *attr_array[3];
4080   int       before_security_flag;
4081   int       group_count;
4082   int       rc;
4083   LK_ENTRY  *group_base;
4084   LK_ENTRY  *ptr;
4085   char      ou_both[512];
4086   char      ou_security[512];
4087   char      ou_distribution[512];
4088   char      ou_neither[512];
4089
4090   memset(ad_distinguishedName, '\0', sizeof(ad_distinguishedName));
4091   sprintf(distinguishedName, "CN=%s,%s,%s", group_name, group_ou, dn_path);
4092
4093
4094   memset(filter, '\0', sizeof(filter));
4095   group_base = NULL;
4096   group_count = 0;
4097   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
4098                         "*", MoiraId, 
4099                         "distinguishedName", &group_base, 
4100                         &group_count, filter))
4101     return(rc);
4102
4103   if (type == CHECK_GROUPS)
4104     {
4105       if (group_count == 1)
4106         {
4107           if (!strcasecmp(group_base->value, distinguishedName))
4108             {
4109               linklist_free(group_base);
4110               return(0);
4111             }
4112         }
4113       linklist_free(group_base);
4114       if (group_count == 0)
4115         return(AD_NO_GROUPS_FOUND);
4116       if (group_count == 1)
4117         return(AD_WRONG_GROUP_DN_FOUND);
4118       return(AD_MULTIPLE_GROUPS_FOUND);
4119     }
4120   if (group_count == 0)
4121     {
4122       return(AD_NO_GROUPS_FOUND);
4123     }
4124   if (group_count > 1)
4125     {
4126       ptr = group_base;
4127       while (ptr != NULL)
4128         {
4129           if (!strcasecmp(distinguishedName, ptr->value))
4130             break;
4131           ptr = ptr->next;
4132         }
4133       if (ptr == NULL)
4134         {
4135           com_err(whoami, 0, "%d groups with moira id = %s", group_count, MoiraId);
4136           ptr = group_base;
4137           while (ptr != NULL)
4138             {
4139               com_err(whoami, 0, "%s with moira id = %s", ptr->value, MoiraId);
4140               ptr = ptr->next;
4141             }
4142           linklist_free(group_base);
4143           return(AD_MULTIPLE_GROUPS_FOUND);
4144         }
4145       ptr = group_base;
4146       while (ptr != NULL)
4147         {
4148           if (strcasecmp(distinguishedName, ptr->value))
4149             rc = ldap_delete_s(ldap_handle, ptr->value);
4150           ptr = ptr->next;
4151         }
4152       linklist_free(group_base);
4153       memset(filter, '\0', sizeof(filter));
4154       group_base = NULL;
4155       group_count = 0;
4156       if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
4157                             "*", MoiraId, 
4158                             "distinguishedName", &group_base, 
4159                             &group_count, filter))
4160         return(rc);
4161       if (group_count == 0)
4162         return(AD_NO_GROUPS_FOUND);
4163       if (group_count > 1)
4164         return(AD_MULTIPLE_GROUPS_FOUND);
4165     }
4166
4167   strcpy(ad_distinguishedName, group_base->value);
4168   linklist_free(group_base);
4169   group_base = NULL;
4170   group_count = 0;
4171
4172   attr_array[0] = "sAMAccountName";
4173   attr_array[1] = NULL;
4174   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4175                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
4176     {
4177       com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
4178                MoiraId, ldap_err2string(rc));
4179       return(rc);
4180     }
4181   sprintf(filter, "(sAMAccountName=%s)", group_base->value);
4182
4183   if (!strcasecmp(ad_distinguishedName, distinguishedName))
4184     {
4185       linklist_free(group_base);
4186       group_base = NULL;
4187       group_count = 0;
4188       return(0);
4189     }
4190   linklist_free(group_base);
4191   group_base = NULL;
4192   group_count = 0;
4193   memset(ou_both, '\0', sizeof(ou_both));
4194   memset(ou_security, '\0', sizeof(ou_security));
4195   memset(ou_distribution, '\0', sizeof(ou_distribution));
4196   memset(ou_neither, '\0', sizeof(ou_neither));
4197   memset(before_name, '\0', sizeof(before_name));
4198   memset(before_desc, '\0', sizeof(before_desc));
4199   memset(before_group_membership, '\0', sizeof(before_group_membership));
4200   attr_array[0] = "name";
4201   attr_array[1] = NULL;
4202   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4203                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
4204     {
4205       com_err(whoami, 0, "Unable to get list name with MoiraId = %s: %s",
4206               MoiraId, ldap_err2string(rc));
4207       return(rc);
4208     }
4209   strcpy(before_name, group_base->value);
4210   linklist_free(group_base);
4211   group_base = NULL;
4212   group_count = 0;
4213   attr_array[0] = "description";
4214   attr_array[1] = NULL;
4215   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4216                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
4217     {
4218       com_err(whoami, 0, 
4219               "Unable to get list description with MoiraId = %s: %s",
4220               MoiraId, ldap_err2string(rc));
4221       return(rc);
4222     }
4223   if (group_count != 0)
4224     {
4225       strcpy(before_desc, group_base->value);
4226       linklist_free(group_base);
4227       group_base = NULL;
4228       group_count = 0;
4229     }
4230   change_to_lower_case(ad_distinguishedName);  
4231   strcpy(ou_both, group_ou_both);
4232   change_to_lower_case(ou_both);
4233   strcpy(ou_security, group_ou_security);
4234   change_to_lower_case(ou_security);
4235   strcpy(ou_distribution, group_ou_distribution);
4236   change_to_lower_case(ou_distribution);
4237   strcpy(ou_neither, group_ou_neither);
4238   change_to_lower_case(ou_neither);
4239   if (strstr(ad_distinguishedName, ou_both))
4240     {
4241       strcpy(before_group_ou, group_ou_both);
4242       before_group_membership[0] = 'B';
4243       before_security_flag = 1;
4244     }
4245   else if (strstr(ad_distinguishedName, ou_security))
4246     {
4247       strcpy(before_group_ou, group_ou_security);
4248       before_group_membership[0] = 'S';
4249       before_security_flag = 1;
4250     }
4251   else if (strstr(ad_distinguishedName, ou_distribution))
4252     {
4253       strcpy(before_group_ou, group_ou_distribution);
4254       before_group_membership[0] = 'D';
4255       before_security_flag = 0;
4256     }
4257   else if (strstr(ad_distinguishedName, ou_neither))
4258     {
4259       strcpy(before_group_ou, group_ou_neither);
4260       before_group_membership[0] = 'N';
4261       before_security_flag = 0;
4262     }
4263   else
4264     return(AD_NO_OU_FOUND);
4265   rc = group_rename(ldap_handle, dn_path, before_name, before_group_membership, 
4266                     before_group_ou, before_security_flag, before_desc,
4267                     group_name, group_membership, group_ou, group_security_flag,
4268                     before_desc, MoiraId, filter);
4269   return(rc);
4270 }
4271
4272 void change_to_lower_case(char *ptr)
4273 {
4274   int i;
4275
4276   for (i = 0; i < (int)strlen(ptr); i++)
4277     {
4278       ptr[i] = tolower(ptr[i]);
4279     }
4280 }
4281
4282 int ad_get_group(LDAP *ldap_handle, char *dn_path, 
4283                  char *group_name, char *group_membership, 
4284                  char *MoiraId, char *attribute,
4285                  LK_ENTRY **linklist_base, int *linklist_count,
4286                  char *rFilter)
4287 {
4288   LK_ENTRY  *pPtr;
4289   char  filter[128];
4290   char  *attr_array[3];
4291   int   rc;
4292
4293   (*linklist_base) = NULL;
4294   (*linklist_count) = 0;
4295   if (strlen(rFilter) != 0)
4296     {
4297       strcpy(filter, rFilter);
4298       attr_array[0] = attribute;
4299       attr_array[1] = NULL;
4300       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4301                                linklist_base, linklist_count, LDAP_SCOPE_SUBTREE)) != 0)
4302         {
4303           com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
4304                   MoiraId, ldap_err2string(rc));
4305          return(rc);
4306        }
4307     if ((*linklist_count) == 1)
4308       {
4309         strcpy(rFilter, filter);
4310         return(0);
4311       }
4312     }
4313
4314   linklist_free((*linklist_base));
4315   (*linklist_base) = NULL;
4316   (*linklist_count) = 0;
4317   if (strlen(MoiraId) != 0)
4318     {
4319       sprintf(filter, "(&(objectClass=group)(mitMoiraId=%s))", MoiraId);
4320       attr_array[0] = attribute;
4321       attr_array[1] = NULL;
4322       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4323                                linklist_base, linklist_count, LDAP_SCOPE_SUBTREE)) != 0)
4324         {
4325           com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
4326                   MoiraId, ldap_err2string(rc));
4327          return(rc);
4328        }
4329     }
4330   if ((*linklist_count) > 1)
4331     {
4332       com_err(whoami, 0, "multiple groups with mitMoiraId = %s", MoiraId);
4333       pPtr = (*linklist_base);
4334       while (pPtr)
4335         {
4336           com_err(whoami, 0, "groups %s has mitMoiraId = %s", pPtr->value, MoiraId);
4337           pPtr = pPtr->next;
4338         }
4339       linklist_free((*linklist_base));
4340       (*linklist_base) = NULL;
4341       (*linklist_count) = 0;
4342     }
4343   if ((*linklist_count) == 1)
4344     {
4345       if (!memcmp(&(*linklist_base)->value[3], group_name, strlen(group_name)))
4346         {
4347           strcpy(rFilter, filter);
4348           return(0);
4349         }
4350     }
4351
4352   linklist_free((*linklist_base));
4353   (*linklist_base) = NULL;
4354   (*linklist_count) = 0;
4355   sprintf(filter, "(sAMAccountName=%s_group)", group_name);
4356   attr_array[0] = attribute;
4357   attr_array[1] = NULL;
4358   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4359                            linklist_base, linklist_count, LDAP_SCOPE_SUBTREE)) != 0)
4360     {
4361       com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
4362               MoiraId, ldap_err2string(rc));
4363       return(rc);
4364     }
4365   if ((*linklist_count) == 1)
4366     {
4367       strcpy(rFilter, filter);
4368       return(0);
4369     }
4370
4371   return(0);
4372 }
4373
4374 int check_user(LDAP *ldap_handle, char *dn_path, char *UserName, char *MoiraId)
4375 {
4376   char filter[128];
4377   char *attr_array[3];
4378   char SamAccountName[64];
4379   int  group_count;
4380   int  rc;
4381   LK_ENTRY  *group_base;
4382   LK_ENTRY  *gPtr;
4383
4384   group_count = 0;
4385   group_base = NULL;
4386
4387   if (strlen(MoiraId) != 0)
4388     {
4389       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
4390       attr_array[0] = "sAMAccountName";
4391       attr_array[1] = NULL;
4392       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4393                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
4394         {
4395           com_err(whoami, 0, "Unable to process user %s : %s",
4396                   UserName, ldap_err2string(rc));
4397           return(rc);
4398         }
4399       if (group_count > 1)
4400         {
4401           com_err(whoami, 0, "multiple users exist with MoiraId = %s",
4402                   MoiraId);
4403           gPtr = group_base;
4404           while (gPtr)
4405             {
4406               com_err(whoami, 0, "user %s exist with MoiraId = %s",
4407                       gPtr->value, MoiraId);
4408               gPtr = gPtr->next;
4409             }
4410         }
4411     }
4412   if (group_count != 1)
4413     {
4414       linklist_free(group_base);
4415       group_count = 0;
4416       group_base = NULL;
4417       sprintf(filter, "(sAMAccountName=%s)", UserName);
4418       attr_array[0] = "sAMAccountName";
4419       attr_array[1] = NULL;
4420       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4421                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
4422         {
4423           com_err(whoami, 0, "Unable to process user %s : %s",
4424                   UserName, ldap_err2string(rc));
4425           return(rc);
4426         }
4427     }
4428
4429   if (group_count != 1)
4430     {
4431       linklist_free(group_base);
4432       return(AD_NO_USER_FOUND);
4433     }
4434   strcpy(SamAccountName, group_base->value);
4435   linklist_free(group_base);
4436   group_count = 0;
4437   rc = 0;
4438   if (strcmp(SamAccountName, UserName))
4439     {
4440       rc = user_rename(ldap_handle, dn_path, SamAccountName, 
4441                        UserName);
4442     }
4443   return(0);
4444 }
4445
4446 void container_get_dn(char *src, char *dest)
4447 {
4448   char *sPtr;
4449   char *array[20];
4450   char name[256];
4451   int  n;
4452
4453   memset(array, '\0', 20 * sizeof(array[0]));
4454
4455   if (strlen(src) == 0)
4456     return;
4457   strcpy(name, src);
4458   sPtr = name;
4459   n = 0;
4460   array[n] = name;
4461   ++n;
4462   while (*sPtr)
4463     {
4464       if ((*sPtr) == '/')
4465         {
4466           (*sPtr) = '\0';
4467           ++sPtr;
4468           array[n] = sPtr;
4469           ++n;
4470         }
4471       else
4472         ++sPtr;
4473     }
4474   strcpy(dest, "OU=");
4475   while (n != 0)
4476     {
4477       strcat(dest, array[n-1]);
4478       --n;
4479       if (n > 0)
4480         {
4481           strcat(dest, ",OU=");
4482         }
4483     }
4484   return;
4485 }
4486
4487 void container_get_name(char *src, char *dest)
4488 {
4489   char *sPtr;
4490   char *dPtr;
4491
4492   if (strlen(src) == 0)
4493     return;
4494   sPtr = src;
4495   dPtr = src;
4496   while (*sPtr)
4497     {
4498       if ((*sPtr) == '/')
4499         {
4500           dPtr = sPtr;
4501           ++dPtr;
4502         }
4503       ++sPtr;
4504     }
4505   strcpy(dest, dPtr);
4506   return;
4507 }
4508
4509 void container_check(LDAP *ldap_handle, char *dn_path, char *name)
4510 {
4511   char cName[256];
4512   char *av[7];
4513   int  i;
4514   int  rc;
4515
4516   strcpy(cName, name);
4517   for (i = 0; i < (int)strlen(cName); i++)
4518     {
4519       if (cName[i] == '/')
4520         {
4521           cName[i] = '\0';
4522           av[CONTAINER_NAME] = cName;
4523           av[CONTAINER_DESC] = "";
4524           av[CONTAINER_LOCATION] = "";
4525           av[CONTAINER_CONTACT] = "";
4526           av[CONTAINER_TYPE] = "";
4527           av[CONTAINER_ID] = "";
4528           av[CONTAINER_ROWID] = "";
4529           rc = container_create(ldap_handle, dn_path, 7, av);
4530           if (rc == LDAP_SUCCESS)
4531             {
4532               com_err(whoami, 0, "container %s created without a mitMoiraId", cName);
4533             }
4534           cName[i] = '/';
4535         }
4536     }
4537
4538 }
4539
4540 int container_rename(LDAP *ldap_handle, char *dn_path, int beforec, char **before, 
4541                      int afterc, char **after)
4542 {
4543   char      dName[256];
4544   char      cName[256];
4545   char      new_cn[128];
4546   char      new_dn_path[256];
4547   char      temp[256];
4548   char      distinguishedName[256];
4549   char      *pPtr;
4550   int       rc;
4551   int       i;
4552
4553   memset(cName, '\0', sizeof(cName));
4554   container_get_name(after[CONTAINER_NAME], cName);
4555   if (!check_container_name(cName))
4556     {
4557       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", cName);
4558       return(AD_INVALID_NAME);
4559     }
4560
4561   memset(distinguishedName, '\0', sizeof(distinguishedName));
4562   if (rc = container_get_distinguishedName(ldap_handle, dn_path, distinguishedName, beforec, before))
4563     return(rc);
4564   if (strlen(distinguishedName) == 0)
4565     {
4566       rc = container_create(ldap_handle, dn_path, afterc, after);
4567       return(rc);
4568     }
4569
4570   strcpy(temp, after[CONTAINER_NAME]);
4571   pPtr = temp;
4572   for (i = 0; i < (int)strlen(temp); i++)
4573     {
4574       if (temp[i] == '/')
4575         {
4576           pPtr = &temp[i];
4577         }
4578     }
4579   (*pPtr) = '\0';
4580
4581   container_get_dn(temp, dName);
4582   if (strlen(temp) != 0)
4583     sprintf(new_dn_path, "%s,%s", dName, dn_path);
4584   else
4585     sprintf(new_dn_path, "%s", dn_path);
4586   sprintf(new_cn, "OU=%s", cName);
4587
4588   container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
4589
4590   if ((rc = ldap_rename_s(ldap_handle, distinguishedName, new_cn, new_dn_path,
4591                           TRUE, NULL, NULL)) != LDAP_SUCCESS)
4592     {
4593       com_err(whoami, 0, "Unable to rename container from %s to %s : %s",
4594               before[CONTAINER_NAME], after[CONTAINER_NAME], ldap_err2string(rc));
4595       return(rc);
4596     }
4597
4598   memset(dName, '\0', sizeof(dName));
4599   container_get_dn(after[CONTAINER_NAME], dName);
4600   rc = container_adupdate(ldap_handle, dn_path, dName, "", afterc, after);
4601   return(rc);
4602 }
4603
4604 int container_delete(LDAP *ldap_handle, char *dn_path, int count, char **av)
4605 {
4606   char      distinguishedName[256];
4607   int       rc;
4608
4609   memset(distinguishedName, '\0', sizeof(distinguishedName));
4610   if (rc = container_get_distinguishedName(ldap_handle, dn_path, distinguishedName, count, av))
4611     return(rc);
4612   if (strlen(distinguishedName) == 0)
4613     return(0);
4614   if ((rc = ldap_delete_s(ldap_handle, distinguishedName)) != LDAP_SUCCESS)
4615     {
4616       if (rc == LDAP_NOT_ALLOWED_ON_NONLEAF)
4617         container_move_objects(ldap_handle, dn_path, distinguishedName);
4618       else
4619         com_err(whoami, 0, "Unable to delete container %s from AD : %s",
4620                 av[CONTAINER_NAME], ldap_err2string(rc));
4621     }
4622   return(rc);
4623 }
4624
4625 int container_create(LDAP *ldap_handle, char *dn_path, int count, char **av)
4626 {
4627   char      *attr_array[3];
4628   LK_ENTRY  *group_base;
4629   int       group_count;
4630   LDAPMod   *mods[20];
4631   char      *objectClass_v[] = {"top", 
4632                            "organizationalUnit", 
4633                            NULL};
4634
4635   char *ou_v[] = {NULL, NULL};
4636   char *name_v[] = {NULL, NULL};
4637   char *moiraId_v[] = {NULL, NULL};
4638   char *desc_v[] = {NULL, NULL};
4639   char *managedBy_v[] = {NULL, NULL};
4640   char dName[256];
4641   char cName[256];
4642   char managedByDN[256];
4643   char filter[256];
4644   char temp[256];
4645   int  n;
4646   int  i;
4647   int  rc;
4648
4649   memset(filter, '\0', sizeof(filter));
4650   memset(dName, '\0', sizeof(dName));
4651   memset(cName, '\0', sizeof(cName));
4652   memset(managedByDN, '\0', sizeof(managedByDN));
4653   container_get_dn(av[CONTAINER_NAME], dName);
4654   container_get_name(av[CONTAINER_NAME], cName);
4655
4656   if ((strlen(cName) == 0) || (strlen(dName) == 0))
4657     {
4658       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", cName);
4659       return(AD_INVALID_NAME);
4660     }
4661
4662   if (!check_container_name(cName))
4663     {
4664       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", cName);
4665       return(AD_INVALID_NAME);
4666     }
4667
4668   n = 0;
4669   ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
4670   name_v[0] = cName;
4671   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
4672   ou_v[0] = cName;
4673   ADD_ATTR("ou", ou_v, LDAP_MOD_ADD);
4674   if (strlen(av[CONTAINER_ROWID]) != 0)
4675     {
4676       moiraId_v[0] = av[CONTAINER_ROWID];
4677       ADD_ATTR("mitMoiraId", moiraId_v, LDAP_MOD_ADD);
4678     }
4679   if (strlen(av[CONTAINER_DESC]) != 0)
4680     {
4681       desc_v[0] = av[CONTAINER_DESC];
4682       ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
4683     }
4684   if ((strlen(av[CONTAINER_TYPE]) != 0) && (strlen(av[CONTAINER_ID]) != 0))
4685     {
4686           if (!strcasecmp(av[CONTAINER_TYPE], "KERBEROS"))
4687           {
4688                   if (!contact_create(ldap_handle, dn_path, av[CONTAINER_ID], kerberos_ou))
4689                   {
4690                         sprintf(managedByDN, "CN=%s,%s,%s", av[CONTAINER_ID], kerberos_ou,dn_path);
4691                         managedBy_v[0] = managedByDN;
4692                         ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_ADD);
4693                   }
4694           }
4695           else
4696           {
4697                 if (!strcasecmp(av[CONTAINER_TYPE], "USER"))
4698         {
4699           sprintf(filter, "(&(cn=%s)(&(objectCategory=person)(objectClass=user)))", av[CONTAINER_ID]);
4700         }
4701                 if (!strcasecmp(av[CONTAINER_TYPE], "LIST"))
4702         {
4703           sprintf(filter, "(&(objectClass=group)(cn=%s))", av[CONTAINER_ID]);
4704         }
4705                 if (strlen(filter) != 0)
4706         {
4707           attr_array[0] = "distinguishedName";
4708           attr_array[1] = NULL;
4709           group_count = 0;
4710           group_base = NULL;
4711           if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4712                                    &group_base, &group_count, LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
4713             {
4714               if (group_count == 1)
4715                 {
4716                   strcpy(managedByDN, group_base->value);
4717                   managedBy_v[0] = managedByDN;
4718                   ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_ADD);
4719                 }
4720               linklist_free(group_base);
4721               group_base = NULL;
4722               group_count = 0;
4723             }
4724         }
4725     }
4726   }
4727   mods[n] = NULL;
4728
4729   sprintf(temp, "%s,%s", dName, dn_path);
4730   rc = ldap_add_ext_s(ldap_handle, temp, mods, NULL, NULL);
4731   for (i = 0; i < n; i++)
4732     free(mods[i]);
4733   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
4734     {
4735       com_err(whoami, 0, "Unable to create container %s : %s",
4736               cName, ldap_err2string(rc));
4737       return(rc);
4738     }
4739   if (rc == LDAP_ALREADY_EXISTS)
4740     {
4741       if (strlen(av[CONTAINER_ROWID]) != 0)
4742         rc = container_adupdate(ldap_handle, dn_path, dName, "", count, av);
4743     }
4744   return(rc);
4745 }
4746
4747 int container_update(LDAP *ldap_handle, char *dn_path, int beforec, char **before, 
4748                      int afterc, char **after)
4749 {
4750   char distinguishedName[256];
4751   int  rc;
4752
4753   memset(distinguishedName, '\0', sizeof(distinguishedName));
4754   if (rc = container_get_distinguishedName(ldap_handle, dn_path, distinguishedName, afterc, after))
4755     return(rc);
4756   if (strlen(distinguishedName) == 0)
4757     {
4758       rc = container_create(ldap_handle, dn_path, afterc, after);
4759       return(rc);
4760     }
4761
4762   container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
4763   rc = container_adupdate(ldap_handle, dn_path, "", distinguishedName, afterc, after);
4764
4765   return(rc);
4766 }
4767
4768 int container_get_distinguishedName(LDAP *ldap_handle, char *dn_path, char *distinguishedName, int count, char **av)
4769 {
4770   char      *attr_array[3];
4771   LK_ENTRY  *group_base;
4772   int       group_count;
4773   char      dName[256];
4774   char      cName[256];
4775   char      filter[512];
4776   int       rc;
4777
4778   memset(filter, '\0', sizeof(filter));
4779   memset(dName, '\0', sizeof(dName));
4780   memset(cName, '\0', sizeof(cName));
4781   container_get_dn(av[CONTAINER_NAME], dName);
4782   container_get_name(av[CONTAINER_NAME], cName);
4783
4784   if (strlen(dName) == 0)
4785     {
4786       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", av[CONTAINER_NAME]);
4787       return(AD_INVALID_NAME);
4788     }
4789
4790   if (!check_container_name(cName))
4791     {
4792       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", cName);
4793       return(AD_INVALID_NAME);
4794     }
4795
4796   sprintf(filter, "(&(objectClass=organizationalUnit)(mitMoiraId=%s))", av[CONTAINER_ROWID]);
4797   attr_array[0] = "distinguishedName";
4798   attr_array[1] = NULL;
4799   group_count = 0;
4800   group_base = NULL;
4801   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4802                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
4803     {
4804       if (group_count == 1)
4805         {
4806           strcpy(distinguishedName, group_base->value);
4807         }
4808       linklist_free(group_base);
4809       group_base = NULL;
4810       group_count = 0;
4811     }
4812   if (strlen(distinguishedName) == 0)
4813     {
4814       sprintf(filter, "(&(objectClass=organizationalUnit)(distinguishedName=%s,%s))", dName, dn_path);
4815       attr_array[0] = "distinguishedName";
4816       attr_array[1] = NULL;
4817       group_count = 0;
4818       group_base = NULL;
4819       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4820                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
4821         {
4822           if (group_count == 1)
4823             {
4824               strcpy(distinguishedName, group_base->value);
4825             }
4826           linklist_free(group_base);
4827           group_base = NULL;
4828           group_count = 0;
4829         }
4830     }
4831   return(0);
4832 }
4833
4834 int container_adupdate(LDAP *ldap_handle, char *dn_path, char *dName, 
4835                        char *distinguishedName, int count, char **av)
4836 {
4837   char      *attr_array[5];
4838   LK_ENTRY  *group_base;
4839   LK_ENTRY  *pPtr;
4840   LDAPMod   *mods[20];
4841   int       group_count;
4842   char      filter[512];
4843   char      *moiraId_v[] = {NULL, NULL};
4844   char      *desc_v[] = {NULL, NULL};
4845   char      *managedBy_v[] = {NULL, NULL};
4846   char      managedByDN[256];
4847   char      moiraId[64];
4848   char      desc[256];
4849   char      ad_path[512];
4850   int       rc;
4851   int       i;
4852   int       n;
4853
4854
4855   strcpy(ad_path, distinguishedName);
4856   if (strlen(dName) != 0)
4857     sprintf(ad_path, "%s,%s", dName, dn_path);
4858
4859   sprintf(filter, "(&(objectClass=organizationalUnit)(distinguishedName=%s))", ad_path);
4860   if (strlen(av[CONTAINER_ID]) != 0)
4861     sprintf(filter, "(&(objectClass=organizationalUnit)(mitMoiraId=%s))", av[CONTAINER_ROWID]);
4862   attr_array[0] = "mitMoiraId";
4863   attr_array[1] = "description";
4864   attr_array[2] = "managedBy";
4865   attr_array[3] = NULL;
4866   group_count = 0;
4867   group_base = NULL;
4868   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4869                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != LDAP_SUCCESS)
4870     {
4871       com_err(whoami, 0, "Unable to retreive container info for %s : %s",
4872               av[CONTAINER_NAME], ldap_err2string(rc));
4873       return(rc);
4874     }
4875   memset(managedByDN, '\0', sizeof(managedByDN));
4876   memset(moiraId, '\0', sizeof(moiraId));
4877   memset(desc, '\0', sizeof(desc));
4878   pPtr = group_base;
4879   while (pPtr)
4880     {
4881       if (!strcasecmp(pPtr->attribute, "description"))
4882         strcpy(desc, pPtr->value);
4883       else if (!strcasecmp(pPtr->attribute, "managedBy"))
4884         strcpy(managedByDN, pPtr->value);
4885       else if (!strcasecmp(pPtr->attribute, "mitMoiraId"))
4886         strcpy(moiraId, pPtr->value);
4887       pPtr = pPtr->next;
4888     }
4889   linklist_free(group_base);
4890   group_base = NULL;
4891   group_count = 0;
4892
4893   n = 0;
4894   if (strlen(av[CONTAINER_ROWID]) != 0)
4895     {
4896       moiraId_v[0] = av[CONTAINER_ROWID];
4897       ADD_ATTR("mitMoiraId", moiraId_v, LDAP_MOD_REPLACE);
4898     }
4899   if (strlen(av[CONTAINER_DESC]) != 0)
4900     {
4901       attribute_update(ldap_handle, ad_path, av[CONTAINER_DESC], "description", dName);
4902     }
4903   else
4904     {
4905       if (strlen(desc) != 0)
4906         {
4907           attribute_update(ldap_handle, ad_path, "", "description", dName);
4908         }
4909     }
4910   if ((strlen(av[CONTAINER_TYPE]) != 0) && (strlen(av[CONTAINER_ID]) != 0))
4911     {
4912           if (!strcasecmp(av[CONTAINER_TYPE], "KERBEROS"))
4913           {
4914                   if (!contact_create(ldap_handle, dn_path, av[CONTAINER_ID], kerberos_ou))
4915                   {
4916                         sprintf(managedByDN, "CN=%s,%s,%s", av[CONTAINER_ID], kerberos_ou, dn_path);
4917                         managedBy_v[0] = managedByDN;
4918             ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_REPLACE);
4919                   }
4920                   else
4921                   {
4922                         if (strlen(managedByDN) != 0)
4923                         {
4924                 attribute_update(ldap_handle, ad_path, "", "managedBy", dName);
4925                         }
4926                   }
4927           }
4928           else
4929           {
4930                 memset(filter, '\0', sizeof(filter));
4931                 if (!strcasecmp(av[CONTAINER_TYPE], "USER"))
4932         {
4933           sprintf(filter, "(&(cn=%s)(&(objectCategory=person)(objectClass=user)))", av[CONTAINER_ID]);
4934         }
4935                 if (!strcasecmp(av[CONTAINER_TYPE], "LIST"))
4936         {
4937           sprintf(filter, "(&(objectClass=group)(cn=%s))", av[CONTAINER_ID]);
4938         }
4939                 if (strlen(filter) != 0)
4940         {
4941           attr_array[0] = "distinguishedName";
4942           attr_array[1] = NULL;
4943           group_count = 0;
4944           group_base = NULL;
4945           if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4946                                    &group_base, &group_count, LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
4947             {
4948               if (group_count == 1)
4949                 {
4950                   strcpy(managedByDN, group_base->value);
4951                   managedBy_v[0] = managedByDN;
4952                   ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_REPLACE);
4953                 }
4954               else
4955                 {
4956                   if (strlen(managedByDN) != 0)
4957                     {
4958                         attribute_update(ldap_handle, ad_path, "", "managedBy", dName);
4959                     }
4960                 }
4961               linklist_free(group_base);
4962               group_base = NULL;
4963               group_count = 0;
4964             }
4965         }
4966                 else
4967         {
4968           if (strlen(managedByDN) != 0)
4969             {
4970                 attribute_update(ldap_handle, ad_path, "", "managedBy", dName);
4971             }
4972         }
4973           }
4974     }
4975   mods[n] = NULL;
4976   if (n == 0)
4977     return(LDAP_SUCCESS);
4978
4979   rc = ldap_modify_s(ldap_handle, ad_path, mods);
4980   for (i = 0; i < n; i++)
4981     free(mods[i]);
4982   if (rc != LDAP_SUCCESS)
4983     {
4984         com_err(whoami, 0, "Unable to modify container info for %s : %s",
4985                 av[CONTAINER_NAME], ldap_err2string(rc));
4986         return(rc);
4987     }
4988   return(rc);
4989 }
4990
4991 int container_move_objects(LDAP *ldap_handle, char *dn_path, char *dName)
4992 {
4993   char      *attr_array[3];
4994   LK_ENTRY  *group_base;
4995   LK_ENTRY  *pPtr;
4996   int       group_count;
4997   char      filter[512];
4998   char      new_cn[128];
4999   char      temp[256];
5000   int       rc;
5001   int       NumberOfEntries = 10;
5002   int       i;
5003   int       count;
5004
5005   rc = ldap_set_option(ldap_handle, LDAP_OPT_SIZELIMIT, &NumberOfEntries);
5006
5007   for (i = 0; i < 3; i++)
5008     {
5009       memset(filter, '\0', sizeof(filter));
5010       if (i == 0)
5011         {
5012           strcpy(filter, "(!(|(objectClass=computer)(objectClass=organizationalUnit)))");
5013           attr_array[0] = "cn";
5014           attr_array[1] = NULL;
5015         }
5016       else if (i == 1)
5017         {
5018           strcpy(filter, "(objectClass=computer)");
5019           attr_array[0] = "cn";
5020           attr_array[1] = NULL;
5021         }
5022       else
5023         {
5024           strcpy(filter, "(objectClass=organizationalUnit)");
5025           attr_array[0] = "ou";
5026           attr_array[1] = NULL;
5027         }
5028
5029       while (1)
5030         {
5031           if ((rc = linklist_build(ldap_handle, dName, filter, attr_array, 
5032                                    &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != LDAP_SUCCESS)
5033             {
5034               break;
5035             }
5036           if (group_count == 0)
5037             break;
5038           pPtr = group_base;
5039           while(pPtr)
5040             {
5041               if (!strcasecmp(pPtr->attribute, "cn"))
5042                 {
5043                   sprintf(new_cn, "cn=%s", pPtr->value);
5044                   if (i == 0)
5045                     sprintf(temp, "%s,%s", orphans_other_ou, dn_path);
5046                   if (i == 1)
5047                     sprintf(temp, "%s,%s", orphans_machines_ou, dn_path);
5048                   count = 1;
5049                   while (1)
5050                     {
5051                       rc = ldap_rename_s(ldap_handle, pPtr->dn, new_cn, temp,
5052                                          TRUE, NULL, NULL);
5053                       if (rc == LDAP_ALREADY_EXISTS)
5054                         {
5055                           sprintf(new_cn, "cn=%s_%d", pPtr->value, count);
5056                           ++count;
5057                         }
5058                       else
5059                         break;
5060                     }
5061                 }
5062               else if (!strcasecmp(pPtr->attribute, "ou"))
5063                 {
5064                   rc = ldap_delete_s(ldap_handle, pPtr->dn);
5065                 }
5066               pPtr = pPtr->next;
5067             }
5068           linklist_free(group_base);
5069           group_base = NULL;
5070           group_count = 0;
5071         }
5072     }
5073   return(0);
5074 }
5075
5076 int get_machine_ou(LDAP *ldap_handle, char *dn_path, char *member, char *machine_ou, char *NewMachineName)
5077 {
5078   LK_ENTRY  *group_base;
5079   int  group_count;
5080   int  i;
5081   char filter[128];
5082   char *attr_array[3];
5083   char cn[256];
5084   char dn[256];
5085   char temp[256];
5086   char *pPtr;
5087   int   rc;
5088
5089   strcpy(NewMachineName, member);
5090   rc = moira_connect();
5091   rc = GetMachineName(NewMachineName);
5092   moira_disconnect();
5093   if (strlen(NewMachineName) == 0)
5094     {
5095       com_err(whoami, 0, "Unable to find alais for machine %s in Moira", member);
5096       return(1);
5097     }
5098
5099   pPtr = NULL;
5100   pPtr = strchr(NewMachineName, '.');
5101   if (pPtr != NULL)
5102     (*pPtr) = '\0';
5103
5104   group_base = NULL;
5105   group_count = 0;
5106   sprintf(filter, "(sAMAccountName=%s$)", NewMachineName);
5107   attr_array[0] = "cn";
5108   attr_array[1] = NULL;
5109   sprintf(temp, "%s", dn_path);
5110   if ((rc = linklist_build(ldap_handle, temp, filter, attr_array, 
5111                         &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
5112     {
5113       com_err(whoami, 0, "Unable to process machine %s : %s",
5114               member, ldap_err2string(rc));
5115       return(1);
5116     }
5117   if (group_count != 1)
5118     {
5119       com_err(whoami, 0, "Unable to process machine %s : machine not found in AD",
5120               NewMachineName);
5121       return(1);
5122     }
5123   strcpy(dn, group_base->dn);
5124   strcpy(cn, group_base->value);
5125   for (i = 0; i < (int)strlen(dn); i++)
5126     dn[i] = tolower(dn[i]);
5127   for (i = 0; i < (int)strlen(cn); i++)
5128     cn[i] = tolower(cn[i]);
5129   linklist_free(group_base);
5130   pPtr = NULL;
5131   pPtr = strstr(dn, cn);
5132   if (pPtr == NULL)
5133     {
5134       com_err(whoami, 0, "Unable to process machine %s",
5135               member);
5136       return(1);
5137     }
5138   pPtr += strlen(cn) + 1;
5139   strcpy(machine_ou, pPtr);
5140   pPtr = NULL;
5141   pPtr = strstr(machine_ou, "dc=");
5142   if (pPtr == NULL)
5143     {
5144       com_err(whoami, 0, "Unable to process machine %s",
5145               member);
5146       return(1);
5147     }
5148   --pPtr;
5149   (*pPtr) = '\0';
5150   return(0);
5151 }
5152
5153 int machine_move_to_ou(LDAP *ldap_handle, char * dn_path, char *MoiraMachineName, char *DestinationOu)
5154 {
5155
5156     char        NewCn[128];
5157     char        OldDn[512];
5158     char        MachineName[128];
5159     char        filter[128];
5160     char        *attr_array[3];
5161     char        NewOu[256];
5162     char        *cPtr = NULL;
5163     int         group_count;
5164     long        rc;
5165     LK_ENTRY    *group_base;
5166
5167     group_count = 0;
5168     group_base = NULL;
5169
5170     strcpy(MachineName, MoiraMachineName);
5171     rc = GetMachineName(MachineName);
5172     if (strlen(MachineName) == 0)
5173     {
5174         com_err(whoami, 0, "Unable to find alais for machine %s in Moira", MoiraMachineName);
5175         return(1);
5176     }
5177
5178     cPtr = strchr(MachineName, '.');
5179     if (cPtr != NULL)
5180         (*cPtr) = '\0';
5181     sprintf(filter, "(sAMAccountName=%s$)", MachineName);
5182     attr_array[0] = "sAMAccountName";
5183     attr_array[1] = NULL;
5184     if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, &group_base, 
5185                              &group_count, LDAP_SCOPE_SUBTREE)) != 0)
5186     {
5187         com_err(whoami, 0, "Unable to process machine %s : %s",
5188                 MoiraMachineName, ldap_err2string(rc));
5189         return(1);
5190     }
5191
5192     if (group_count == 1)
5193         strcpy(OldDn, group_base->dn);
5194     linklist_free(group_base);
5195     group_base = NULL;
5196     if (group_count != 1)
5197     {
5198         com_err(whoami, 0, "Unable to find machine %s in AD: %s", MoiraMachineName);
5199         return(1);
5200     }
5201     sprintf(NewOu, "%s,%s", DestinationOu, dn_path);
5202     cPtr = strchr(OldDn, ',');
5203     if (cPtr != NULL)
5204     {
5205         ++cPtr;
5206         if (!strcasecmp(cPtr, NewOu))
5207             return(0);
5208     }
5209     sprintf(NewCn, "CN=%s", MachineName);
5210     rc = ldap_rename_s(ldap_handle, OldDn, NewCn, NewOu, TRUE, NULL, NULL);
5211     return(rc);
5212 }
5213
5214 int machine_check(LDAP *ldap_handle, char *dn_path, char *machine_name)
5215 {
5216     char    Name[128];
5217     char    *pPtr;
5218     int     rc;
5219
5220     memset(Name, '\0', sizeof(Name));
5221     strcpy(Name, machine_name);
5222     pPtr = NULL;
5223     pPtr = strchr(Name, '.');
5224     if (pPtr != NULL)
5225         (*pPtr) = '\0';
5226     strcat(Name, "$");
5227     return(!(rc = checkADname(ldap_handle, dn_path, Name)));
5228 }
5229
5230 int machine_get_moira_container(LDAP *ldap_handle, char *dn_path, char *machine_name, char *container_name)
5231 {
5232     int     rc;
5233     char    *av[2];
5234     char    *call_args[2];
5235
5236     av[0] = machine_name;
5237     call_args[0] = (char *)container_name;
5238     rc = mr_query("get_machine_to_container_map", 1, av, machine_GetMoiraContainer,
5239                    call_args);
5240     return(rc);
5241 }
5242
5243 int machine_GetMoiraContainer(int ac, char **av, void *ptr)
5244 {
5245     char **call_args;
5246     
5247     call_args = ptr;
5248     strcpy(call_args[0], av[1]);
5249     return(0);
5250 }
5251
5252 int Moira_container_group_create(char **after)
5253 {
5254   long rc;
5255   char GroupName[64];
5256   char *argv[20];
5257   
5258   memset(GroupName, '\0', sizeof(GroupName));
5259   rc = Moira_groupname_create(GroupName, after[CONTAINER_NAME], 
5260                               after[CONTAINER_ROWID]);
5261   if (rc)
5262     return rc;
5263   
5264   argv[L_NAME] = GroupName;
5265   argv[L_ACTIVE] = "1";
5266   argv[L_PUBLIC] = "0";
5267   argv[L_HIDDEN] = "0";
5268   argv[L_MAILLIST] = "0";
5269   argv[L_GROUP] = "1";
5270   argv[L_GID] = UNIQUE_GID;
5271   argv[L_NFSGROUP] = "0";
5272   argv[L_MAILMAN] = "0";
5273   argv[L_MAILMAN_SERVER] = "[NONE]";
5274   argv[L_DESC] = "auto created container group";
5275   argv[L_ACE_TYPE] = "USER";
5276   argv[L_MEMACE_TYPE] = "USER";
5277   argv[L_ACE_NAME] = "sms";
5278   argv[L_MEMACE_NAME] = "sms";
5279
5280   if (rc = mr_query("add_list", 15, argv, NULL, NULL))
5281     {
5282       com_err(whoami, 0, "Unable to create container group %s for container %s: %s",
5283               GroupName, after[CONTAINER_NAME], error_message(rc));
5284     }
5285
5286   Moira_setContainerGroup(after[CONTAINER_NAME], GroupName);
5287   Moira_addGroupToParent(after[CONTAINER_NAME], GroupName);
5288   
5289   return(rc);
5290 }
5291
5292 int Moira_container_group_update(char **before, char **after)
5293 {
5294   long rc;
5295   char BeforeGroupName[64];
5296   char AfterGroupName[64];
5297   char *argv[20];
5298   
5299   if (!strcasecmp(after[CONTAINER_NAME], before[CONTAINER_NAME]))
5300     return(0);
5301
5302   memset(BeforeGroupName, '\0', sizeof(BeforeGroupName));
5303   Moira_getGroupName(after[CONTAINER_NAME], BeforeGroupName, 0);
5304   if (strlen(BeforeGroupName) == 0)
5305     return(0);
5306
5307   memset(AfterGroupName, '\0', sizeof(AfterGroupName));
5308   rc = Moira_groupname_create(AfterGroupName, after[CONTAINER_NAME], 
5309                               after[CONTAINER_ROWID]);
5310   if (rc)
5311     return rc;
5312
5313   if (strcasecmp(BeforeGroupName, AfterGroupName))
5314     {
5315       argv[L_NAME] = BeforeGroupName;
5316       argv[L_NAME + 1] = AfterGroupName;
5317       argv[L_ACTIVE + 1] = "1";
5318       argv[L_PUBLIC + 1] = "0";
5319       argv[L_HIDDEN + 1] = "1";
5320       argv[L_MAILLIST + 1] = "0";
5321       argv[L_GROUP + 1] = "1";
5322       argv[L_GID + 1] = UNIQUE_GID;
5323       argv[L_NFSGROUP + 1] = "0";
5324       argv[L_MAILMAN + 1] = "0";
5325       argv[L_MAILMAN_SERVER + 1] = "[NONE]";
5326       argv[L_DESC + 1] = "auto created container group";
5327       argv[L_ACE_TYPE + 1] = "USER";
5328       argv[L_MEMACE_TYPE + 1] = "USER";
5329       argv[L_ACE_NAME + 1] = "sms";
5330       argv[L_MEMACE_NAME + 1] = "sms";
5331       
5332       if (rc = mr_query("update_list", 16, argv, NULL, NULL))
5333         {
5334           com_err(whoami, 0, "Unable to rename container group from %s to %s: %s",
5335                   BeforeGroupName, AfterGroupName, error_message(rc));
5336         }
5337     }
5338   
5339   return(rc);
5340 }
5341
5342 int Moira_container_group_delete(char **before)
5343 {
5344   long rc = 0;
5345   char *argv[13];
5346   char GroupName[64];
5347   char ParentGroupName[64];
5348   
5349   memset(ParentGroupName, '\0', sizeof(ParentGroupName));
5350   Moira_getGroupName(before[CONTAINER_NAME], ParentGroupName, 1);
5351
5352   memset(GroupName, '\0', sizeof(GroupName));
5353   if (strcmp(before[CONTAINER_GROUP_NAME], "[none]"))
5354     strcpy(GroupName, before[CONTAINER_GROUP_NAME]);
5355   
5356   if ((strlen(ParentGroupName) != 0) && (strlen(GroupName) != 0))
5357     {
5358       argv[0] = ParentGroupName;
5359       argv[1] = "LIST";
5360       argv[2] = GroupName;
5361       if (rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL))
5362         {
5363           com_err(whoami, 0, "Unable to delete container group %s from list: %s",
5364                   GroupName, ParentGroupName, error_message(rc));
5365         }
5366     }
5367   
5368   if (strlen(GroupName) != 0)
5369     {
5370       argv[0] = GroupName;
5371       if (rc = mr_query("delete_list", 1, argv, NULL, NULL))
5372         {
5373           com_err(whoami, 0, "Unable to delete container group %s : %s",
5374                   GroupName, error_message(rc));
5375         }
5376      }
5377   
5378   return(rc);
5379 }
5380
5381 int Moira_groupname_create(char *GroupName, char *ContainerName,
5382                            char *ContainerRowID)
5383 {
5384   char *ptr;
5385   char *ptr1;
5386   char temp[64];
5387   char newGroupName[64];
5388   char tempGroupName[64];
5389   char *argv[1];
5390   int  i;
5391   long rc;
5392
5393   strcpy(temp, ContainerName);
5394   
5395   ptr1 = strrchr(temp, '/');
5396   if (ptr1 != NULL)
5397     ptr = ++ptr1;
5398   else
5399     ptr = temp;
5400
5401   if (strlen(ptr) > 25)
5402     ptr[25] ='\0';
5403
5404   sprintf(newGroupName, "cnt-%s", ptr);
5405
5406   /* change everything to lower case */
5407   ptr = newGroupName;
5408   while (*ptr)
5409     {
5410       if (isupper(*ptr))
5411         *ptr = tolower(*ptr);
5412       if (*ptr == ' ')
5413         *ptr = '-';
5414       ptr++;
5415     }
5416
5417   strcpy(tempGroupName, newGroupName);
5418   i = (int)'0';
5419   /* append 0-9 then a-z if a duplicate is found */
5420   while(1)
5421     {
5422       argv[0] = newGroupName;
5423       if (rc = mr_query("get_list_info", 1, argv, NULL, NULL))
5424         {
5425           if (rc == MR_NO_MATCH)
5426             break;
5427           com_err(whoami, 0, "Moira error while creating group name for container %s : %s",
5428                   ContainerName, error_message(rc));
5429           return rc;
5430         }
5431       sprintf(newGroupName, "%s-%c", tempGroupName, i);
5432       if (i == (int)'z')
5433         {
5434           com_err(whoami, 0, "Unable to find a unique group name for container %s: too many duplicate container names",
5435                   ContainerName);
5436           return 1;
5437         }
5438       if (i == '9')
5439         i = 'a';
5440       else
5441         i++;
5442     }
5443
5444   strcpy(GroupName, newGroupName);
5445   return(0);
5446 }
5447
5448 int Moira_setContainerGroup(char *origContainerName, char *GroupName)
5449 {
5450   long rc;
5451   char *argv[3];
5452   
5453   argv[0] = origContainerName;
5454   argv[1] = GroupName;
5455
5456   if ((rc = mr_query("set_container_list", 2, argv, NULL, NULL)))
5457     {
5458          com_err(whoami, 0, "Unable to set container group %s in container %s: %s",
5459                  GroupName, origContainerName, error_message(rc));
5460     }
5461
5462   return(0);
5463 }
5464
5465  int Moira_addGroupToParent(char *origContainerName, char *GroupName)
5466  {
5467    char ContainerName[64];
5468    char ParentGroupName[64];
5469    char *argv[3];
5470    long rc;
5471
5472    strcpy(ContainerName, origContainerName);
5473
5474    Moira_getGroupName(ContainerName, ParentGroupName, 1);
5475    /* top-level container */
5476    if (strlen(ParentGroupName) == 0)
5477      return(0);
5478    
5479    argv[0] = ParentGroupName;
5480    argv[1] = "LIST";
5481    argv[2] = GroupName;
5482    if ((rc = mr_query("add_member_to_list", 3, argv, NULL, NULL)))
5483      {
5484        com_err(whoami, 0, "Unable to add container group %s to parent group %s: %s",
5485                GroupName, ParentGroupName, error_message(rc));
5486      }
5487    return(0);
5488  }
5489
5490 int Moira_getContainerGroup(int ac, char **av, void *ptr)
5491 {
5492   char **call_args;
5493   
5494   call_args = ptr;
5495   strcpy(call_args[0], av[1]);
5496   return(0);
5497 }
5498
5499 int Moira_getGroupName(char *origContainerName, char *GroupName,
5500                        int ParentFlag)
5501 {
5502   char ContainerName[64];
5503   char *argv[3];
5504   char *call_args[3];
5505   char *ptr;
5506   long rc;
5507
5508   strcpy(ContainerName, origContainerName);
5509
5510   if (ParentFlag)
5511     {
5512       ptr = strrchr(ContainerName, '/');
5513       if (ptr != NULL)
5514         (*ptr) = '\0';
5515       else
5516         return(0);
5517     }
5518
5519   argv[0] = ContainerName;
5520   argv[1] = NULL;
5521   call_args[0] = GroupName;
5522   call_args[1] = NULL;
5523
5524   if (!(rc = mr_query("get_container_list", 1, argv, Moira_getContainerGroup,
5525                       call_args)))
5526     {
5527       if (strlen(GroupName) != 0)
5528         return(0);
5529     }
5530
5531   if (rc)
5532     com_err(whoami, 0, "Unable to get container group from container %s: %s",
5533             ContainerName, error_message(rc));
5534   else
5535     com_err(whoami, 0, "Unable to get container group from container %s",
5536             ContainerName);
5537      return(0);
5538 }
5539
5540 int Moira_process_machine_container_group(char *MachineName, char* GroupName, 
5541                                           int DeleteMachine)
5542 {
5543   char *argv[3];
5544   long rc;
5545
5546   if (strcmp(GroupName, "[none]") == 0)
5547     return 0;
5548
5549   argv[0] = GroupName;
5550   argv[1] = "MACHINE";
5551   argv[2] = MachineName;
5552   if (!DeleteMachine)
5553     rc = mr_query("add_member_to_list", 3, argv, NULL, NULL);
5554   else
5555     rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL);
5556   if (rc)
5557     {
5558       com_err(whoami, 0, "Unable to add machine %s to container group%s: %s",
5559               MachineName, GroupName, error_message(rc));
5560     }
5561   return(0);
5562 }
5563
5564 int GetMachineName(char *MachineName)
5565 {
5566         char    *args[2];
5567     char    NewMachineName[1024];
5568     char    *szDot;
5569     int     rc = 0;
5570     int     i;
5571     DWORD   dwLen = 0;
5572     char    *call_args[2];
5573
5574     // If the address happens to be in the top-level MIT domain, great!
5575     strcpy(NewMachineName, MachineName);
5576     for (i = 0; i < (int)strlen(NewMachineName); i++)
5577         NewMachineName[i] = toupper(NewMachineName[i]);
5578     szDot = strchr(NewMachineName,'.');
5579     if ((szDot) && (!strcasecmp(szDot+1, DOMAIN_SUFFIX)))
5580     {
5581         return(0);
5582     }
5583         
5584     // If not, see if it has a Moira alias in the top-level MIT domain.
5585     memset(NewMachineName, '\0', sizeof(NewMachineName));
5586         args[0] = "*";
5587     args[1] = MachineName;
5588     call_args[0] = NewMachineName;
5589     call_args[1] = NULL;
5590     if (rc = mr_query("get_hostalias", 2, args, ProcessMachineName, call_args))
5591     {
5592         com_err(whoami, 0, "Unable to resolve machine name %s : %s",
5593                 MachineName, error_message(rc));
5594         strcpy(MachineName, "");
5595         return(0);
5596     }
5597
5598     if (strlen(NewMachineName) != 0)
5599         strcpy(MachineName, NewMachineName);
5600     else
5601         strcpy(MachineName, "");
5602     return(0);
5603
5604 }
5605
5606 int ProcessMachineName(int ac, char **av, void *ptr)
5607 {
5608     char    **call_args;
5609     char    MachineName[1024];
5610     char    *szDot;
5611     int     i;
5612
5613     call_args = ptr;
5614     if (strlen(call_args[0]) == 0)
5615     {
5616         strcpy(MachineName, av[0]);
5617         for (i = 0; i < (int)strlen(MachineName); i++)
5618             MachineName[i] = toupper(MachineName[i]);
5619         szDot = strchr(MachineName,'.');
5620         if ((szDot) && (!strcasecmp(szDot+1,DOMAIN_SUFFIX)))
5621         {
5622             strcpy(call_args[0], MachineName);
5623         }
5624     }
5625     return(0);
5626 }
5627
5628 void SwitchSFU(LDAPMod **mods, int *UseSFU30, int n)
5629 {
5630     int i;
5631
5632     if (*UseSFU30)
5633     {
5634         for (i = 0; i < n; i++)
5635         {
5636             if (!strcmp(mods[i]->mod_type, "msSFU30UidNumber"))
5637                 mods[i]->mod_type = "uidNumber";
5638         }
5639         (*UseSFU30) = 0;
5640     }
5641     else
5642     {
5643         for (i = 0; i < n; i++)
5644         {
5645             if (!strcmp(mods[i]->mod_type, "uidNumber"))
5646                 mods[i]->mod_type = "msSFU30UidNumber";
5647         }
5648         (*UseSFU30) = 1;
5649     }
5650 }
5651
5652 int SetHomeDirectory(LDAP *ldap_handle, char *user_name, char *DistinguishedName,
5653                      char *WinHomeDir, char *WinProfileDir,
5654                      char **homedir_v, char **winProfile_v,
5655                      char **drives_v, LDAPMod **mods, 
5656                      int OpType, int n)
5657 {
5658     char **hp;
5659     char cWeight[3];
5660     char cPath[1024];
5661     char path[1024];
5662     char winPath[1024];
5663     char winProfile[1024];
5664     char homeDrive[8];
5665     int  last_weight;
5666     int  i;
5667     int  rc;
5668     LDAPMod *DelMods[20];
5669
5670     memset(homeDrive, '\0', sizeof(homeDrive));
5671     memset(path, '\0', sizeof(path));
5672     memset(winPath, '\0', sizeof(winPath));
5673     memset(winProfile, '\0', sizeof(winProfile));
5674     hp = NULL;
5675     if ((!strcasecmp(WinHomeDir, "[afs]")) || (!strcasecmp(WinProfileDir, "[afs]")))
5676     {
5677         if ((hp = hes_resolve(user_name, "filsys")) != NULL)
5678         {
5679             memset(cWeight, 0, sizeof(cWeight));
5680             memset(cPath, 0, sizeof(cPath));
5681             last_weight = 1000;
5682             i = 0;
5683             while (hp[i] != NULL)
5684             {
5685                 if (sscanf(hp[i], "%*s %s", cPath))
5686                 {
5687                     if (strnicmp(cPath, AFS, strlen(AFS)) == 0)
5688                     {
5689                         if (sscanf(hp[i], "%*s %*s %*s %*s %s", cWeight))
5690                         {
5691                             if (atoi(cWeight) < last_weight)
5692                             {
5693                                 strcpy(path, cPath);
5694                                 last_weight = (int)atoi(cWeight);
5695                             }
5696                         }
5697                         else 
5698                             strcpy(path, cPath);
5699                     }
5700                 }
5701               ++i;
5702             }
5703             if (strlen(path))
5704             {
5705                 if (!strnicmp(path, AFS, strlen(AFS)))
5706                 {
5707                     AfsToWinAfs(path, winPath);
5708                     strcpy(winProfile, winPath);
5709                     strcat(winProfile, "\\.winprofile");
5710                 }
5711             }
5712         }
5713     }
5714
5715     if (hp != NULL)
5716     {
5717         i = 0;
5718         while (hp[i])
5719         {
5720             free(hp[i]);
5721             i++;
5722         }
5723     }
5724
5725     if (!strcasecmp(WinHomeDir, "[local]"))
5726         memset(winPath, '\0', sizeof(winPath));
5727     else if (!strcasecmp(WinHomeDir, "[afs]"))
5728     {
5729         strcpy(homeDrive, "H:");
5730     }
5731     else
5732     {
5733         strcpy(winPath, WinHomeDir);
5734         if (!strncmp(WinHomeDir, "\\\\", 2))
5735         {
5736             strcpy(homeDrive, "H:");
5737         }        
5738     }
5739
5740     // nothing needs to be done if WinProfileDir is [afs].
5741     if (!strcasecmp(WinProfileDir, "[local]"))
5742         memset(winProfile, '\0', sizeof(winProfile));
5743     else if (strcasecmp(WinProfileDir, "[afs]"))
5744     {
5745         strcpy(winProfile, WinProfileDir);
5746     }
5747
5748     if (strlen(winProfile) != 0)
5749     {
5750         if (winProfile[strlen(winProfile) - 1] == '\\')
5751             winProfile[strlen(winProfile) - 1] = '\0';
5752     }
5753     if (strlen(winPath) != 0)
5754     {
5755         if (winPath[strlen(winPath) - 1] == '\\')
5756             winPath[strlen(winPath) - 1] = '\0';
5757     }
5758
5759     if ((winProfile[1] == ':') && (strlen(winProfile) == 2))
5760         strcat(winProfile, "\\");
5761     if ((winPath[1] == ':') && (strlen(winPath) == 2))
5762         strcat(winPath, "\\");
5763
5764     if (strlen(winPath) == 0)
5765     {
5766         if (OpType == LDAP_MOD_REPLACE)
5767         {
5768             i = 0;
5769             DEL_ATTR("homeDirectory", LDAP_MOD_DELETE);
5770             DelMods[i] = NULL;
5771             //unset homeDirectory attribute for user.
5772             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
5773             free(DelMods[0]);
5774         }
5775     }
5776     else
5777     {
5778         homedir_v[0] = strdup(winPath);
5779         ADD_ATTR("homeDirectory", homedir_v, OpType);
5780     }
5781
5782     if (strlen(winProfile) == 0)
5783     {
5784         if (OpType == LDAP_MOD_REPLACE)
5785         {
5786             i = 0;
5787             DEL_ATTR("profilePath", LDAP_MOD_DELETE);
5788             DelMods[i] = NULL;
5789             //unset profilePate attribute for user.
5790             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
5791             free(DelMods[0]);
5792         }
5793     }
5794     else
5795     {
5796         winProfile_v[0] = strdup(winProfile);
5797         ADD_ATTR("profilePath", winProfile_v, OpType);
5798     }
5799
5800     if (strlen(homeDrive) == 0)
5801     {
5802         if (OpType == LDAP_MOD_REPLACE)
5803         {
5804             i = 0;
5805             DEL_ATTR("homeDrive", LDAP_MOD_DELETE);
5806             DelMods[i] = NULL;
5807             //unset homeDrive attribute for user
5808             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
5809             free(DelMods[0]);
5810         }
5811     }
5812     else
5813     {
5814         drives_v[0] = strdup(homeDrive);
5815         ADD_ATTR("homeDrive", drives_v, OpType);
5816     }
5817
5818     return(n);
5819 }
5820
5821 int GetServerList(char *ldap_domain, char **ServerList)
5822 {
5823   unsigned long   rc;
5824   int             group_count;
5825   int             UseSFU30;
5826   int             Count;
5827   int             i;
5828   int             IgnoreServerListError;
5829   int             ServerListFound;
5830   char            default_server[256];
5831   char            dn_path[256];
5832   char            *attr_array[3];
5833   char            *sPtr;
5834   char            base[128];
5835   char            filter[128];
5836   LK_ENTRY        *group_base;
5837   LK_ENTRY        *gPtr;
5838   LDAP            *ldap_handle;
5839   FILE            *fptr;
5840
5841   memset(default_server, '\0', sizeof(default_server));
5842   memset(dn_path, '\0', sizeof(dn_path));
5843   for (i = 0; i < MAX_SERVER_NAMES; i++)
5844     {
5845       if (ServerList[i] != NULL)
5846         {
5847           free(ServerList[i]);
5848           ServerList[i] = NULL;
5849         }
5850     }
5851   IgnoreServerListError = 1;
5852   if (rc = ad_connect(&ldap_handle, ldap_domain, dn_path, "", "", default_server, 0, 
5853                       ServerList, &IgnoreServerListError))
5854       return(1);
5855   memset(ServerList, '\0', sizeof(ServerList[0]) * MAX_SERVER_NAMES);
5856   group_count = 0;
5857   group_base = NULL;
5858   Count = 0;
5859   ServerListFound = 0;
5860
5861   strcpy(filter, "(&(objectClass=rIDManager)(fSMORoleOwner=*))");
5862   attr_array[0] = "fSMORoleOwner";
5863   attr_array[1] = NULL;
5864   if (!(rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
5865                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
5866     {
5867       if (group_count != 0)
5868         {
5869           sPtr = strstr(group_base->value, ",CN=");
5870           if (sPtr != NULL)
5871             {
5872               sPtr += strlen(",CN=");
5873               if (ServerList[0] == NULL)
5874                   ServerList[0] = calloc(1, 256);
5875               strcpy(ServerList[0], sPtr);
5876               sPtr = strstr(ServerList[0], ",");
5877               if (sPtr != NULL)
5878                   (*sPtr) = '\0';
5879               ++Count;
5880               ServerListFound = 1;
5881             }
5882         }
5883     }
5884   linklist_free(group_base);
5885
5886   group_count = 0;
5887   group_base = NULL;
5888   attr_array[0] = "cn";
5889   attr_array[1] = NULL;
5890   strcpy(filter, "(cn=*)");
5891   sprintf(base, "cn=Servers,cn=Default-First-Site-Name,cn=Sites,cn=Configuration,%s", dn_path);
5892
5893   if (!(rc = linklist_build(ldap_handle, base, filter, attr_array, 
5894                            &group_base, &group_count, LDAP_SCOPE_ONELEVEL)) != 0)
5895     {
5896       if (group_count != 0)
5897         {
5898           gPtr = group_base;
5899           while (gPtr != NULL)
5900             {
5901               if (ServerListFound != 0)
5902                 {
5903                   if (!strcasecmp(ServerList[0], gPtr->value))
5904                     {
5905                       gPtr = gPtr->next;
5906                       continue;
5907                     }
5908                 }
5909               if (Count < MAX_SERVER_NAMES)
5910                 {
5911                   if (ServerList[Count] == NULL)
5912                       ServerList[Count] = calloc(1, 256);
5913                   strcpy(ServerList[Count], gPtr->value);
5914                   gPtr = gPtr->next;
5915                   ++Count;
5916                 }
5917             }
5918         }
5919     }
5920   linklist_free(group_base);
5921
5922   UseSFU30 = 0;
5923   group_count = 0;
5924   group_base = NULL;
5925
5926   strcpy(filter, "(cn=msSFU-30-Uid-Number)");
5927   sprintf(base, "cn=schema,cn=configuration,%s", dn_path);
5928
5929   if (!(rc = linklist_build(ldap_handle, base, filter, NULL, 
5930                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
5931     {
5932       if (group_count != 0)
5933         {
5934           UseSFU30 = 1;
5935         }
5936     }
5937   linklist_free(group_base);
5938   group_count = 0;
5939   group_base = NULL;
5940
5941   if ((fptr = fopen(WINADCFG, "w+")) != NULL)
5942     {
5943       fprintf(fptr, "%s%s\n", DOMAIN, ldap_domain);
5944       if (UseSFU30)
5945           fprintf(fptr, "%s%s\n", MSSFU, SFUTYPE);
5946       for (i = 0; i < MAX_SERVER_NAMES; i++)
5947         {
5948           if (ServerList[i] != NULL)
5949             {
5950               fprintf(fptr, "%s%s\n", SERVER, ServerList[i]);
5951             }
5952         }
5953       fclose(fptr);
5954     }
5955   ldap_unbind_s(ldap_handle);
5956
5957   return(0);
5958 }
5959
5960 int attribute_update(LDAP *ldap_handle, char *distinguished_name, 
5961                       char *attribute_value, char *attribute, char *user_name)
5962 {
5963   char      *mod_v[] = {NULL, NULL};
5964   LDAPMod   *DelMods[20];
5965   LDAPMod   *mods[20];
5966   int       n;
5967   int       i;
5968   int       rc;
5969
5970   if (strlen(attribute_value) == 0)
5971     {
5972       i = 0;
5973       DEL_ATTR(attribute, LDAP_MOD_DELETE);
5974       DelMods[i] = NULL;
5975       rc = ldap_modify_s(ldap_handle, distinguished_name, DelMods);
5976       free(DelMods[0]);
5977     }
5978     else
5979     {
5980       n = 0;
5981       mod_v[0] = attribute_value;
5982       ADD_ATTR(attribute, mod_v, LDAP_MOD_REPLACE);
5983       mods[n] = NULL;
5984       if ((rc = ldap_modify_s(ldap_handle, distinguished_name, mods)) != LDAP_SUCCESS)
5985         {
5986           free(mods[0]);
5987           n = 0;
5988           mod_v[0] = attribute_value;
5989           ADD_ATTR(attribute, mod_v, LDAP_MOD_ADD);
5990           mods[n] = NULL;
5991           if ((rc = ldap_modify_s(ldap_handle, distinguished_name, mods)) != LDAP_SUCCESS)
5992             {
5993               com_err(whoami, 0, "Unable to change the %s attribute for %s in the AD : %s",
5994                       attribute, user_name, ldap_err2string(rc));
5995             }
5996         }
5997       free(mods[0]);
5998     }
5999   return(rc);
6000 }
This page took 0.548833 seconds and 5 git commands to generate.