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