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