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