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