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