]> andersk Git - moira.git/blob - incremental/winad/winad.c
*** empty log message ***
[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   uid_v[0] = Uid;
3015   if (!UseSFU30)
3016     {
3017       ADD_ATTR("uidNumber", uid_v, LDAP_MOD_REPLACE);
3018     }
3019   else
3020     {
3021       ADD_ATTR("msSFU30UidNumber", uid_v, LDAP_MOD_REPLACE);
3022     }
3023
3024
3025   if ((State != US_NO_PASSWD) && (State != US_REGISTERED))
3026     userAccountControl |= UF_ACCOUNTDISABLE;
3027   sprintf(userAccountControlStr, "%ld", userAccountControl);
3028   userAccountControl_v[0] = userAccountControlStr;
3029   ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_REPLACE);
3030
3031   n = SetHomeDirectory(ldap_handle, user_name, distinguished_name, WinHomeDir, 
3032                        WinProfileDir, homedir_v, winProfile_v,
3033                        drives_v, mods, LDAP_MOD_REPLACE, n);
3034
3035   mods[n] = NULL;
3036   if ((rc = ldap_modify_s(ldap_handle, distinguished_name, mods)) != LDAP_SUCCESS)
3037     {
3038         OldUseSFU30 = UseSFU30;
3039         SwitchSFU(mods, &UseSFU30, n);
3040         if (OldUseSFU30 != UseSFU30)
3041             rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
3042         if (rc)
3043         {
3044             com_err(whoami, 0, "Unable to modify user data for %s : %s",
3045                 user_name, ldap_err2string(rc));
3046         }
3047     }
3048   for (i = 0; i < n; i++)
3049     free(mods[i]);
3050   return(rc);
3051 }
3052
3053 int user_rename(LDAP *ldap_handle, char *dn_path, char *before_user_name, 
3054                 char *user_name)
3055 {
3056   LDAPMod *mods[20];
3057   char new_dn[256];
3058   char old_dn[256];
3059   char upn[256];
3060   char temp[128];
3061   char *userPrincipalName_v[] = {NULL, NULL};
3062   char *altSecurityIdentities_v[] = {NULL, NULL};
3063   char *name_v[] = {NULL, NULL};
3064   char *samAccountName_v[] = {NULL, NULL};
3065   int  n;
3066   int  rc;
3067   int  i;
3068
3069   if (!check_string(before_user_name))
3070     {
3071       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", before_user_name);
3072       return(AD_INVALID_NAME);
3073     }
3074   if (!check_string(user_name))
3075     {
3076       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", user_name);
3077       return(AD_INVALID_NAME);
3078     }
3079
3080   strcpy(user_name, user_name);
3081   sprintf(old_dn, "cn=%s,%s,%s", before_user_name, user_ou, dn_path);
3082   sprintf(new_dn, "cn=%s", user_name);
3083   if ((rc = ldap_rename_s(ldap_handle, old_dn, new_dn, NULL, TRUE, 
3084                            NULL, NULL)) != LDAP_SUCCESS)
3085     {
3086       com_err(whoami, 0, "Unable to rename user from %s to %s : %s",
3087               before_user_name, user_name, ldap_err2string(rc));
3088       return(rc);
3089     }
3090
3091   name_v[0] = user_name;
3092   sprintf(upn, "%s@%s", user_name, ldap_domain);
3093   userPrincipalName_v[0] = upn;
3094   sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
3095   altSecurityIdentities_v[0] = temp;
3096   samAccountName_v[0] = user_name;
3097
3098   n = 0;
3099   ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_REPLACE);
3100   ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_REPLACE);
3101   ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
3102   ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_REPLACE);
3103   mods[n] = NULL;
3104   sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, dn_path);
3105   if ((rc = ldap_modify_s(ldap_handle, new_dn, mods)) != LDAP_SUCCESS)
3106     {
3107       com_err(whoami, 0, "Unable to modify user data for %s after renaming : %s",
3108               user_name, ldap_err2string(rc));
3109     }
3110   for (i = 0; i < n; i++)
3111     free(mods[i]);
3112   return(rc);
3113 }
3114
3115 int filesys_process(LDAP *ldap_handle, char *dn_path, char *fs_name, 
3116                     char *fs_type, char *fs_pack, int operation)
3117 {
3118   char  distinguished_name[256];
3119   char  winPath[256];
3120   char  winProfile[256];
3121   char  filter[128];
3122   char  *attr_array[3];
3123   int   group_count;
3124   int   rc;
3125   LK_ENTRY  *group_base;
3126
3127   if (!check_string(fs_name))
3128     {
3129       com_err(whoami, 0, "Unable to process invalid filesys name %s", fs_name);
3130       return(AD_INVALID_NAME);
3131     }
3132
3133   if (strcmp(fs_type, "AFS"))
3134     {
3135       com_err(whoami, 0, "Unable to process invalid filesys type %s", fs_type);
3136       return(AD_INVALID_FILESYS);
3137     }
3138
3139   group_count = 0;
3140   group_base = NULL;
3141   sprintf(filter, "(sAMAccountName=%s)", fs_name);
3142   attr_array[0] = "cn";
3143   attr_array[1] = NULL;
3144   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3145                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3146     {
3147       com_err(whoami, 0, "Unable to process filesys %s : %s",
3148               fs_name, ldap_err2string(rc));
3149       return(rc);
3150     }
3151
3152   if (group_count != 1)
3153     {
3154       linklist_free(group_base);
3155       com_err(whoami, 0, "Unable to find user %s in AD",
3156               fs_name);
3157       return(LDAP_NO_SUCH_OBJECT);
3158     }
3159   strcpy(distinguished_name, group_base->dn);
3160   linklist_free(group_base);
3161   group_count = 0;
3162
3163   if (operation == LDAP_MOD_ADD)
3164     {
3165       memset(winPath, 0, sizeof(winPath));
3166       AfsToWinAfs(fs_pack, winPath);
3167       memset(winProfile, 0, sizeof(winProfile));
3168       strcpy(winProfile, winPath);
3169       strcat(winProfile, "\\.winprofile");
3170
3171       rc = attribute_update(ldap_handle, distinguished_name, winProfile, "profilePath", fs_name);
3172       rc = attribute_update(ldap_handle, distinguished_name, "H:", "homeDrive", fs_name);
3173       rc = attribute_update(ldap_handle, distinguished_name, winPath, "homeDirectory", fs_name);
3174
3175     }
3176   else
3177     {
3178       rc = attribute_update(ldap_handle, distinguished_name, "", "profilePath", fs_name);
3179       rc = attribute_update(ldap_handle, distinguished_name, "", "homeDrive", fs_name);
3180       rc = attribute_update(ldap_handle, distinguished_name, "", "homeDirectory", fs_name);
3181     }
3182
3183   return(0);
3184 }
3185
3186 int user_create(int ac, char **av, void *ptr)
3187 {
3188   LK_ENTRY  *group_base;
3189   LDAPMod *mods[20];
3190   char new_dn[256];
3191   char user_name[256];
3192   char sam_name[256];
3193   char upn[256];
3194   char *cn_v[] = {NULL, NULL};
3195   char *objectClass_v[] = {"top", "person", 
3196                            "organizationalPerson", 
3197                            "user", NULL};
3198
3199   char *samAccountName_v[] = {NULL, NULL};
3200   char *altSecurityIdentities_v[] = {NULL, NULL};
3201   char *mitMoiraId_v[] = {NULL, NULL};
3202   char *name_v[] = {NULL, NULL};
3203   char *desc_v[] = {NULL, NULL};
3204   char *userPrincipalName_v[] = {NULL, NULL};
3205   char *userAccountControl_v[] = {NULL, NULL};
3206   char *uid_v[] = {NULL, NULL};
3207   char *mitid_v[] = {NULL, NULL};
3208   char *homedir_v[] = {NULL, NULL};
3209   char *winProfile_v[] = {NULL, NULL};
3210   char *drives_v[] = {NULL, NULL};
3211   char userAccountControlStr[80];
3212   char temp[128];
3213   u_int userAccountControl = UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD | UF_PASSWD_CANT_CHANGE;
3214   int  n;
3215   int  rc;
3216   int  i;
3217   int  group_count;
3218   int  OldUseSFU30;
3219   char filter[128];
3220   char *attr_array[3];
3221   char **call_args;
3222   char WinHomeDir[1024];
3223   char WinProfileDir[1024];
3224
3225   call_args = ptr;
3226
3227   if (!check_string(av[U_NAME]))
3228     {
3229       callback_rc = AD_INVALID_NAME;
3230       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", av[U_NAME]);
3231       return(AD_INVALID_NAME);
3232     }
3233
3234   memset(WinHomeDir, '\0', sizeof(WinHomeDir));
3235   memset(WinProfileDir, '\0', sizeof(WinProfileDir));
3236   strcpy(WinHomeDir, av[U_WINHOMEDIR]);
3237   strcpy(WinProfileDir, av[U_WINPROFILEDIR]);
3238   strcpy(user_name, av[U_NAME]);
3239   sprintf(upn, "%s@%s", user_name, ldap_domain);
3240   sprintf(sam_name, "%s", av[U_NAME]);
3241   samAccountName_v[0] = sam_name;
3242   if ((atoi(av[U_STATE]) != US_NO_PASSWD) && (atoi(av[U_STATE]) != US_REGISTERED))
3243     userAccountControl |= UF_ACCOUNTDISABLE;
3244   sprintf(userAccountControlStr, "%ld", userAccountControl);
3245   userAccountControl_v[0] = userAccountControlStr;
3246   userPrincipalName_v[0] = upn;
3247
3248   cn_v[0] = user_name;
3249   name_v[0] = user_name;
3250   desc_v[0] = "Auto account created by Moira";
3251   sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
3252   altSecurityIdentities_v[0] = temp;    
3253   sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, call_args[1]);
3254
3255   n = 0;
3256   ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
3257   ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
3258   ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
3259   ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_ADD);
3260   ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_ADD);
3261   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
3262   ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
3263   ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
3264   if (strlen(call_args[2]) != 0)    
3265     {
3266       mitMoiraId_v[0] = call_args[2];
3267       ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_ADD);
3268     }
3269   ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_ADD);
3270   if (strlen(av[U_UID]) != 0)
3271     {
3272       uid_v[0] = av[U_UID];
3273       ADD_ATTR("uid", uid_v, LDAP_MOD_ADD);
3274       if (!UseSFU30)
3275         {
3276           ADD_ATTR("uidNumber", uid_v, LDAP_MOD_ADD);
3277         }
3278       else
3279         {
3280           ADD_ATTR("msSFU30UidNumber", uid_v, LDAP_MOD_ADD);
3281         }
3282     }
3283   if ((strlen(av[U_MITID]) != 0) && (av[U_MITID][0] == '9'))
3284       mitid_v[0] = av[U_MITID];
3285   else
3286       mitid_v[0] = "none";
3287   ADD_ATTR("employeeID", mitid_v, LDAP_MOD_ADD);
3288
3289   n = SetHomeDirectory((LDAP *)call_args[0], user_name, new_dn, WinHomeDir, 
3290                        WinProfileDir, homedir_v, winProfile_v,
3291                        drives_v, mods, LDAP_MOD_ADD, n);
3292
3293   mods[n] = NULL;
3294
3295   rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
3296   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
3297   {
3298       OldUseSFU30 = UseSFU30;
3299       SwitchSFU(mods, &UseSFU30, n);
3300       if (OldUseSFU30 != UseSFU30)
3301           rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
3302   }
3303
3304   for (i = 0; i < n; i++)
3305     free(mods[i]);
3306   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
3307     {
3308       com_err(whoami, 0, "Unable to create user %s : %s",
3309               user_name, ldap_err2string(rc));
3310       callback_rc = rc;
3311       return(rc);
3312     }
3313   if (rc == LDAP_SUCCESS)
3314     {
3315       if ((rc = set_password(sam_name, "", ldap_domain)) != 0)
3316         {
3317           ad_kdc_disconnect();
3318           tickets_get_k5();
3319           if (!ad_server_connect(default_server, ldap_domain))
3320             {
3321               com_err(whoami, 0, "Unable to set password for user %s : %s",
3322                       user_name, "cannot get changepw ticket from windows domain");
3323             }
3324           else
3325             {
3326               if ((rc = set_password(sam_name, "", ldap_domain)) != 0)
3327                 {
3328                   com_err(whoami, 0, "Unable to set password for user %s : %ld",
3329                           user_name, rc);
3330                 }
3331             }
3332         }
3333     }
3334   sprintf(filter, "(sAMAccountName=%s)", av[U_NAME]);
3335   if (strlen(call_args[2]) != 0)
3336     sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", call_args[2]);
3337   attr_array[0] = "objectSid";
3338   attr_array[1] = NULL;
3339   group_count = 0;
3340   group_base = NULL;
3341   if ((rc = linklist_build((LDAP *)call_args[0], call_args[1], filter, attr_array, 
3342                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
3343     {
3344       if (group_count != 1)
3345         {
3346           if (strlen(call_args[2]) != 0)
3347             {
3348               linklist_free(group_base);
3349               group_count = 0;
3350               group_base = NULL;
3351               sprintf(filter, "(sAMAccountName=%s)", av[U_NAME]);
3352               rc = linklist_build((LDAP *)call_args[0], call_args[1], filter, 
3353                                   attr_array, &group_base, &group_count, LDAP_SCOPE_SUBTREE);
3354             }
3355         }
3356       if (group_count == 1)
3357         {
3358           (*sid_ptr) = group_base;
3359           (*sid_ptr)->member = strdup(av[U_NAME]);
3360           (*sid_ptr)->type = (char *)GROUPS;
3361           sid_ptr = &(*sid_ptr)->next;
3362         }
3363       else
3364         {
3365           if (group_base != NULL)
3366             linklist_free(group_base);
3367         }
3368     }
3369   else
3370     {
3371       if (group_base != NULL)
3372         linklist_free(group_base);
3373     }
3374   return(0);
3375 }
3376
3377 int user_change_status(LDAP *ldap_handle, char *dn_path, 
3378                        char *user_name, char *MoiraId,
3379                        int operation)
3380 {
3381   char      filter[128];
3382   char      *attr_array[3];
3383   char      temp[256];
3384   char      distinguished_name[1024];
3385   char      **modvalues;
3386   char      *mitMoiraId_v[] = {NULL, NULL};
3387   LDAPMod   *mods[20];
3388   LK_ENTRY  *group_base;
3389   int       group_count;
3390   int       rc;
3391   int       i;
3392   int       n;
3393   ULONG     ulongValue;
3394
3395   if (!check_string(user_name))
3396     {
3397       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", user_name);
3398       return(AD_INVALID_NAME);
3399     }
3400
3401   group_count = 0;
3402   group_base = NULL;
3403
3404   if (strlen(MoiraId) != 0)
3405     {
3406       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
3407       attr_array[0] = "UserAccountControl";
3408       attr_array[1] = NULL;
3409       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3410                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3411         {
3412           com_err(whoami, 0, "Unable to process user %s : %s",
3413                   user_name, ldap_err2string(rc));
3414           return(rc);
3415         }
3416     }
3417   if (group_count != 1)
3418     {
3419       linklist_free(group_base);
3420       group_count = 0;
3421       group_base = NULL;
3422       sprintf(filter, "(sAMAccountName=%s)", user_name);
3423       attr_array[0] = "UserAccountControl";
3424       attr_array[1] = NULL;
3425       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3426                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3427         {
3428           com_err(whoami, 0, "Unable to process user %s : %s",
3429                   user_name, ldap_err2string(rc));
3430           return(rc);
3431         }
3432     }
3433
3434   if (group_count != 1)
3435     {
3436       linklist_free(group_base);
3437       com_err(whoami, 0, "Unable to find user %s in AD",
3438               user_name);
3439       return(LDAP_NO_SUCH_OBJECT);
3440     }
3441
3442   strcpy(distinguished_name, group_base->dn);
3443   ulongValue = atoi((*group_base).value);
3444   if (operation == MEMBER_DEACTIVATE)
3445     ulongValue |= UF_ACCOUNTDISABLE;
3446   else    
3447     ulongValue &= ~UF_ACCOUNTDISABLE;
3448   sprintf(temp, "%ld", ulongValue);
3449   if ((rc = construct_newvalues(group_base, group_count, (*group_base).value, 
3450                                 temp, &modvalues, REPLACE)) == 1)
3451     goto cleanup;
3452   linklist_free(group_base);
3453   group_base = NULL;
3454   group_count = 0;
3455   n = 0;
3456   ADD_ATTR("UserAccountControl", modvalues, LDAP_MOD_REPLACE);
3457   if (strlen(MoiraId) != 0)
3458     {
3459     mitMoiraId_v[0] = MoiraId;
3460     ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
3461     }
3462   mods[n] = NULL;
3463   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
3464   for (i = 0; i < n; i++)
3465     free(mods[i]);
3466   free_values(modvalues);
3467   if (rc != LDAP_SUCCESS)
3468     {
3469       com_err(whoami, 0, "Unable to change status of user %s : %s",
3470               user_name, ldap_err2string(rc));
3471     }
3472 cleanup:
3473   return(rc);
3474 }
3475
3476 int user_delete(LDAP *ldap_handle, char *dn_path, 
3477                 char *u_name, char *MoiraId)
3478 {
3479   char      filter[128];
3480   char      *attr_array[3];
3481   char      distinguished_name[1024];
3482   char      user_name[512];
3483   LK_ENTRY  *group_base;
3484   int       group_count;
3485   int       rc;
3486
3487   if (!check_string(u_name))
3488     return(AD_INVALID_NAME);
3489
3490   strcpy(user_name, u_name);
3491   group_count = 0;
3492   group_base = NULL;
3493
3494   if (strlen(MoiraId) != 0)
3495     {
3496       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
3497       attr_array[0] = "name";
3498       attr_array[1] = NULL;
3499       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3500                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3501         {
3502           com_err(whoami, 0, "Unable to process user %s : %s",
3503                   user_name, ldap_err2string(rc));
3504           goto cleanup;
3505         }
3506     }
3507   if (group_count != 1)
3508     {
3509       linklist_free(group_base);
3510       group_count = 0;
3511       group_base = NULL;
3512       sprintf(filter, "(sAMAccountName=%s)", user_name);
3513       attr_array[0] = "name";
3514       attr_array[1] = NULL;
3515       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3516                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3517         {
3518           com_err(whoami, 0, "Unable to process user %s : %s",
3519                   user_name, ldap_err2string(rc));
3520           goto cleanup;
3521         }
3522     }
3523
3524   if (group_count != 1)
3525     {
3526       com_err(whoami, 0, "Unable to find user %s in AD",
3527               user_name);
3528       goto cleanup;
3529     }
3530
3531   strcpy(distinguished_name, group_base->dn);
3532   if (rc = ldap_delete_s(ldap_handle, distinguished_name))
3533     {
3534       com_err(whoami, 0, "Unable to process user %s : %s",
3535               user_name, ldap_err2string(rc));
3536     }
3537
3538 cleanup:
3539   linklist_free(group_base);
3540   return(0);
3541 }
3542
3543 void linklist_free(LK_ENTRY *linklist_base)
3544 {
3545   LK_ENTRY *linklist_previous;
3546
3547   while (linklist_base != NULL)
3548     {
3549       if (linklist_base->dn != NULL)
3550         free(linklist_base->dn);
3551       if (linklist_base->attribute != NULL)
3552         free(linklist_base->attribute);
3553       if (linklist_base->value != NULL)
3554         free(linklist_base->value);
3555       if (linklist_base->member != NULL)
3556         free(linklist_base->member);
3557       if (linklist_base->type != NULL)
3558         free(linklist_base->type);
3559       if (linklist_base->list != NULL)
3560         free(linklist_base->list);
3561       linklist_previous = linklist_base;
3562       linklist_base = linklist_previous->next;
3563       free(linklist_previous);
3564     }
3565 }
3566
3567 void free_values(char **modvalues)
3568 {
3569   int i;
3570
3571   i = 0;
3572   if (modvalues != NULL)
3573     {
3574     while (modvalues[i] != NULL)
3575       {
3576         free(modvalues[i]);
3577         modvalues[i] = NULL;
3578         ++i;
3579       }
3580     free(modvalues);
3581   }
3582 }
3583
3584 int sid_update(LDAP *ldap_handle, char *dn_path)
3585 {
3586   LK_ENTRY      *ptr;
3587   int           rc;
3588   unsigned char temp[126];
3589   char          *av[3];
3590
3591   ptr = sid_base;
3592
3593   while (ptr != NULL)
3594     {
3595       memset(temp, 0, sizeof(temp));
3596       convert_b_to_a(temp, ptr->value, ptr->length);
3597       if (!ptr->member)
3598         continue;
3599       av[0] = ptr->member;
3600       av[1] = temp;
3601       if (ptr->type == (char *)GROUPS)
3602         {
3603           ptr->type = NULL;
3604           rc = mr_query("add_list_sid_by_name", 2, av, NULL, NULL);
3605         }
3606       else if (ptr->type == (char *)USERS)
3607         {
3608           ptr->type = NULL;
3609           rc = mr_query("add_user_sid_by_login", 2, av, NULL, NULL);
3610         }
3611       ptr = ptr->next;
3612     }
3613   return(0);
3614 }
3615
3616 void convert_b_to_a(char *string, UCHAR *binary, int length)
3617 {
3618   int   i;
3619   int   j;
3620   UCHAR tmp;
3621
3622   j = 0;
3623   for (i = 0; i < length; i++)
3624     {
3625       tmp = binary[i];
3626       string[j] = tmp;
3627       string[j] >>= 4;
3628       string[j] &= 0x0f;
3629       string[j] += 0x30;
3630       if (string[j] > '9')
3631         string[j] += 0x27;
3632       ++j;
3633       string[j] = tmp & 0x0f;
3634       string[j] += 0x30;
3635       if (string[j] > '9')
3636         string[j] += 0x27;
3637       j++;
3638     }
3639   string[j] = 0;
3640 }
3641
3642 static int illegalchars[] = {
3643   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
3644   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
3645   1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, /* SPACE - / */
3646   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 0 - ? */
3647   0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
3648   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* P - _ */
3649   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
3650   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
3651   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3652   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3653   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3654   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3655   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3656   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3657   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3658   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
3659 };
3660
3661 int check_string(char *s)
3662 {
3663   char  character;
3664
3665   for (; *s; s++)
3666     {
3667       character = *s;
3668       if (isupper(character))
3669         character = tolower(character);
3670       if (illegalchars[(unsigned) character])
3671         return 0;
3672     }
3673   return 1;
3674 }
3675
3676 int check_container_name(char *s)
3677 {
3678   char  character;
3679
3680   for (; *s; s++)
3681     {
3682       character = *s;
3683       if (isupper(character))
3684         character = tolower(character);
3685
3686           if (character == ' ')
3687                   continue;
3688       if (illegalchars[(unsigned) character])
3689         return 0;
3690     }
3691   return 1;
3692 }
3693
3694 int mr_connect_cl(char *server, char *client, int version, int auth)
3695 {
3696   int   status;
3697   char  *motd;
3698   char  temp[128];
3699
3700   status = mr_connect(server);
3701   if (status)
3702     {
3703       com_err(whoami, status, "while connecting to Moira");
3704       return status;
3705     }
3706
3707   status = mr_motd(&motd);
3708   if (status)
3709     {
3710       mr_disconnect();
3711       com_err(whoami, status, "while checking server status");
3712       return status;
3713     }
3714   if (motd)
3715     {
3716       sprintf(temp, "The Moira server is currently unavailable: %s", motd);
3717       com_err(whoami, status, temp);
3718       mr_disconnect();
3719       return status;
3720     }
3721
3722   status = mr_version(version);
3723   if (status)
3724     {
3725       if (status == MR_UNKNOWN_PROC)
3726         {
3727           if (version > 2)
3728             status = MR_VERSION_HIGH;
3729           else
3730             status = MR_SUCCESS;
3731         }
3732
3733       if (status == MR_VERSION_HIGH)
3734         {
3735           com_err(whoami, 0, "Warning: This client is running newer code than the server.");
3736                   com_err(whoami, 0, "Some operations may not work.");
3737         }
3738       else if (status && status != MR_VERSION_LOW)
3739         {
3740           com_err(whoami, status, "while setting query version number.");
3741           mr_disconnect();
3742           return status;
3743         }
3744     }
3745
3746   if (auth)
3747     {
3748       status = mr_auth(client);
3749       if (status)
3750         {
3751           com_err(whoami, status, "while authenticating to Moira.");
3752           mr_disconnect();
3753           return status;
3754         }
3755     }
3756
3757   return MR_SUCCESS;
3758 }
3759
3760 void AfsToWinAfs(char* path, char* winPath)
3761 {
3762     char* pathPtr;
3763     char* winPathPtr;
3764     strcpy(winPath, WINAFS);
3765     pathPtr = path + strlen(AFS);
3766     winPathPtr = winPath + strlen(WINAFS);
3767
3768     while (*pathPtr)
3769     {
3770         if (*pathPtr == '/')
3771           *winPathPtr = '\\';
3772         else
3773           *winPathPtr = *pathPtr;
3774
3775         pathPtr++;
3776         winPathPtr++;
3777     }
3778 }
3779
3780 int GetAceInfo(int ac, char **av, void *ptr)
3781 {
3782   char **call_args;
3783   int   security_flag;
3784
3785   call_args = ptr;
3786
3787   strcpy(call_args[0], av[L_ACE_TYPE]);
3788   strcpy(call_args[1], av[L_ACE_NAME]);
3789   security_flag = 0;
3790   get_group_membership(call_args[2], call_args[3], &security_flag, av);
3791   return(LDAP_SUCCESS);
3792
3793 }
3794
3795 int checkADname(LDAP *ldap_handle, char *dn_path, char *Name)
3796 {
3797   char filter[128];
3798   char *attr_array[3];
3799   int  group_count;
3800   int  rc;
3801   LK_ENTRY  *group_base;
3802
3803   group_count = 0;
3804   group_base = NULL;
3805
3806   sprintf(filter, "(sAMAccountName=%s)", Name);
3807   attr_array[0] = "sAMAccountName";
3808   attr_array[1] = NULL;
3809   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
3810                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
3811     {
3812       com_err(whoami, 0, "Unable to process ACE name %s : %s",
3813               Name, ldap_err2string(rc));
3814       return(1);
3815     }
3816
3817   linklist_free(group_base);
3818   group_base = NULL;
3819   if (group_count == 0)
3820     return(0);
3821   return(1);
3822 }
3823
3824 #define MAX_ACE 7
3825
3826 int ProcessAce(LDAP *ldap_handle, char *dn_path, char *Name, char *Type, int UpdateGroup, int *ProcessGroup)
3827 {
3828   char  *av[2];
3829   char  GroupName[256];
3830   char  *call_args[7];
3831   int   rc;
3832   char  *AceInfo[4];
3833   char  AceType[32];
3834   char  AceName[128];
3835   char  AceMembership[2];
3836   char  AceOu[256];
3837   char  temp[128];
3838
3839   strcpy(GroupName, Name);
3840
3841   if (strcasecmp(Type, "LIST"))
3842     return(1);
3843   while (1)
3844     {
3845       av[0] = GroupName;
3846       AceInfo[0] = AceType;
3847       AceInfo[1] = AceName;
3848       AceInfo[2] = AceMembership;
3849       AceInfo[3] = AceOu;
3850       memset(AceType, '\0', sizeof(AceType));
3851       memset(AceName, '\0', sizeof(AceName));
3852       memset(AceMembership, '\0', sizeof(AceMembership));
3853       memset(AceOu, '\0', sizeof(AceOu));
3854       callback_rc = 0;
3855       if (rc = mr_query("get_list_info", 1, av, GetAceInfo, AceInfo))
3856         {
3857           com_err(whoami, 0, "Unable to get ACE info for list %s : %s", GroupName, error_message(rc));
3858           return(1);
3859         }
3860       if (callback_rc)
3861         {
3862           com_err(whoami, 0, "Unable to get ACE info for list %s", GroupName);
3863           return(1);
3864         }
3865       if ((strcasecmp(AceType, "USER")) && (strcasecmp(AceType, "LIST")))
3866         return(0);
3867       strcpy(temp, AceName);
3868       if (!strcasecmp(AceType, "LIST"))
3869         sprintf(temp, "%s_group", AceName);
3870       if (!UpdateGroup)
3871         {
3872           if (checkADname(ldap_handle, dn_path, temp))
3873             return(0);
3874           (*ProcessGroup) = 1;
3875         }
3876       if (!strcasecmp(AceInfo[0], "LIST"))
3877         {
3878           if (make_new_group(ldap_handle, dn_path, "", AceName, AceOu, AceMembership, 0, UpdateGroup))
3879             return(1);
3880         }
3881       else if (!strcasecmp(AceInfo[0], "USER"))
3882         {
3883           av[0] = AceName;
3884           call_args[0] = (char *)ldap_handle;
3885           call_args[1] = dn_path;
3886           call_args[2] = "";
3887           call_args[3] = NULL;
3888           sid_base = NULL;
3889           sid_ptr = &sid_base;
3890           callback_rc = 0;
3891           if (rc = mr_query("get_user_account_by_login", 1, av, user_create, call_args))
3892             {
3893               com_err(whoami, 0, "Unable to process user ACE %s for group %s.", AceName, Name);
3894               return(1);
3895             }
3896           if (callback_rc)
3897             {
3898               com_err(whoami, 0, "Unable to process user Ace %s for group %s", AceName, Name);
3899               return(1);
3900             }
3901           if (sid_base != NULL)
3902             {
3903               sid_update(ldap_handle, dn_path);
3904               linklist_free(sid_base);
3905               sid_base = NULL;
3906             }
3907           return(0);
3908         }
3909       else
3910         return(1);
3911       if (!strcasecmp(AceType, "LIST"))
3912         {
3913           if (!strcasecmp(GroupName, AceName))
3914             return(0);
3915         }
3916       strcpy(GroupName, AceName);
3917     }
3918   return(1);
3919 }
3920
3921 int make_new_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
3922                    char *group_name, char *group_ou, char *group_membership, 
3923                    int group_security_flag, int updateGroup)
3924 {
3925   char  *av[3];
3926   char  *call_args[7];
3927   int   rc;
3928
3929   av[0] = group_name;
3930   call_args[0] = (char *)ldap_handle;
3931   call_args[1] = dn_path;
3932   call_args[2] = group_name;
3933   call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
3934   call_args[4] = (char *)updateGroup;
3935   call_args[5] = MoiraId;
3936   call_args[6] = NULL;
3937   sid_base = NULL;
3938   sid_ptr = &sid_base;
3939   callback_rc = 0;
3940   if (rc = mr_query("get_list_info", 1, av, group_create, call_args))
3941     {
3942       moira_disconnect();
3943       com_err(whoami, 0, "Unable to create list %s : %s", group_name, error_message(rc));
3944       return(rc);
3945     }
3946   if (callback_rc)
3947     {
3948       moira_disconnect();
3949       com_err(whoami, 0, "Unable to create list %s", group_name);
3950       return(callback_rc);
3951     }
3952
3953   if (sid_base != NULL)
3954     {
3955       sid_update(ldap_handle, dn_path);
3956       linklist_free(sid_base);
3957       sid_base = NULL;
3958     }
3959   return(0);
3960 }
3961
3962 int populate_group(LDAP *ldap_handle, char *dn_path, char *group_name, 
3963                    char *group_ou, char *group_membership, 
3964                    int group_security_flag, char *MoiraId)
3965 {
3966   char      *av[3];
3967   char      *call_args[7];
3968   char      *pUserOu;
3969   LK_ENTRY  *ptr;
3970   int       rc;
3971
3972   com_err(whoami, 0, "Populating group %s", group_name);
3973   av[0] = group_name;
3974   call_args[0] = (char *)ldap_handle;
3975   call_args[1] = dn_path;
3976   call_args[2] = group_name;
3977   call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
3978   call_args[4] = NULL;
3979   member_base = NULL;
3980   if (rc = mr_query("get_end_members_of_list", 1, av,
3981                     member_list_build, call_args))
3982     {
3983       com_err(whoami, 0, "Unable to populate list %s : %s", 
3984               group_name, error_message(rc));
3985       return(3);
3986     }
3987   if (member_base != NULL)
3988     {
3989       ptr = member_base;
3990       while (ptr != NULL)
3991         {
3992           if (!strcasecmp(ptr->type, "LIST"))
3993             {
3994               ptr = ptr->next;
3995               continue;
3996             }
3997           pUserOu = user_ou;
3998           if (!strcasecmp(ptr->type, "STRING"))
3999             {
4000               if (contact_create(ldap_handle, dn_path, ptr->member, contact_ou))
4001                 return(3);
4002               pUserOu = contact_ou;
4003             }
4004           else if (!strcasecmp(ptr->type, "KERBEROS"))
4005             {
4006               if (contact_create(ldap_handle, dn_path, ptr->member, kerberos_ou))
4007                 return(3);
4008               pUserOu = kerberos_ou;
4009             }
4010           rc = member_add(ldap_handle, dn_path, group_name,
4011                           group_ou, group_membership, ptr->member, 
4012                           pUserOu, MoiraId);
4013           ptr = ptr->next;
4014         }
4015       linklist_free(member_base);
4016       member_base = NULL;
4017     }
4018   return(0);
4019 }
4020
4021 int process_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
4022                   char *group_name, char *group_ou, char *group_membership, 
4023                   int group_security_flag, int type)
4024 {
4025   char      before_desc[512];
4026   char      before_name[256];
4027   char      before_group_ou[256];
4028   char      before_group_membership[2];
4029   char      distinguishedName[256];
4030   char      ad_distinguishedName[256];
4031   char      filter[128];
4032   char      *attr_array[3];
4033   int       before_security_flag;
4034   int       group_count;
4035   int       rc;
4036   LK_ENTRY  *group_base;
4037   LK_ENTRY  *ptr;
4038   char      ou_both[512];
4039   char      ou_security[512];
4040   char      ou_distribution[512];
4041   char      ou_neither[512];
4042
4043   memset(ad_distinguishedName, '\0', sizeof(ad_distinguishedName));
4044   sprintf(distinguishedName, "CN=%s,%s,%s", group_name, group_ou, dn_path);
4045
4046
4047   memset(filter, '\0', sizeof(filter));
4048   group_base = NULL;
4049   group_count = 0;
4050   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
4051                         "*", MoiraId, 
4052                         "distinguishedName", &group_base, 
4053                         &group_count, filter))
4054     return(rc);
4055
4056   if (type == CHECK_GROUPS)
4057     {
4058       if (group_count == 1)
4059         {
4060           if (!strcasecmp(group_base->value, distinguishedName))
4061             {
4062               linklist_free(group_base);
4063               return(0);
4064             }
4065         }
4066       linklist_free(group_base);
4067       if (group_count == 0)
4068         return(AD_NO_GROUPS_FOUND);
4069       if (group_count == 1)
4070         return(AD_WRONG_GROUP_DN_FOUND);
4071       return(AD_MULTIPLE_GROUPS_FOUND);
4072     }
4073   if (group_count == 0)
4074     {
4075       return(AD_NO_GROUPS_FOUND);
4076     }
4077   if (group_count > 1)
4078     {
4079       ptr = group_base;
4080       while (ptr != NULL)
4081         {
4082           if (!strcasecmp(distinguishedName, ptr->value))
4083             break;
4084           ptr = ptr->next;
4085         }
4086       if (ptr == NULL)
4087         {
4088           com_err(whoami, 0, "%d groups with moira id = %s", group_count, MoiraId);
4089           ptr = group_base;
4090           while (ptr != NULL)
4091             {
4092               com_err(whoami, 0, "%s with moira id = %s", ptr->value, MoiraId);
4093               ptr = ptr->next;
4094             }
4095           linklist_free(group_base);
4096           return(AD_MULTIPLE_GROUPS_FOUND);
4097         }
4098       ptr = group_base;
4099       while (ptr != NULL)
4100         {
4101           if (strcasecmp(distinguishedName, ptr->value))
4102             rc = ldap_delete_s(ldap_handle, ptr->value);
4103           ptr = ptr->next;
4104         }
4105       linklist_free(group_base);
4106       memset(filter, '\0', sizeof(filter));
4107       group_base = NULL;
4108       group_count = 0;
4109       if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
4110                             "*", MoiraId, 
4111                             "distinguishedName", &group_base, 
4112                             &group_count, filter))
4113         return(rc);
4114       if (group_count == 0)
4115         return(AD_NO_GROUPS_FOUND);
4116       if (group_count > 1)
4117         return(AD_MULTIPLE_GROUPS_FOUND);
4118     }
4119
4120   strcpy(ad_distinguishedName, group_base->value);
4121   linklist_free(group_base);
4122   group_base = NULL;
4123   group_count = 0;
4124
4125   attr_array[0] = "sAMAccountName";
4126   attr_array[1] = NULL;
4127   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4128                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
4129     {
4130       com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
4131                MoiraId, ldap_err2string(rc));
4132       return(rc);
4133     }
4134   sprintf(filter, "(sAMAccountName=%s)", group_base->value);
4135
4136   if (!strcasecmp(ad_distinguishedName, distinguishedName))
4137     {
4138       linklist_free(group_base);
4139       group_base = NULL;
4140       group_count = 0;
4141       return(0);
4142     }
4143   linklist_free(group_base);
4144   group_base = NULL;
4145   group_count = 0;
4146   memset(ou_both, '\0', sizeof(ou_both));
4147   memset(ou_security, '\0', sizeof(ou_security));
4148   memset(ou_distribution, '\0', sizeof(ou_distribution));
4149   memset(ou_neither, '\0', sizeof(ou_neither));
4150   memset(before_name, '\0', sizeof(before_name));
4151   memset(before_desc, '\0', sizeof(before_desc));
4152   memset(before_group_membership, '\0', sizeof(before_group_membership));
4153   attr_array[0] = "name";
4154   attr_array[1] = NULL;
4155   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4156                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
4157     {
4158       com_err(whoami, 0, "Unable to get list name with MoiraId = %s: %s",
4159               MoiraId, ldap_err2string(rc));
4160       return(rc);
4161     }
4162   strcpy(before_name, group_base->value);
4163   linklist_free(group_base);
4164   group_base = NULL;
4165   group_count = 0;
4166   attr_array[0] = "description";
4167   attr_array[1] = NULL;
4168   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4169                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
4170     {
4171       com_err(whoami, 0, 
4172               "Unable to get list description with MoiraId = %s: %s",
4173               MoiraId, ldap_err2string(rc));
4174       return(rc);
4175     }
4176   if (group_count != 0)
4177     {
4178       strcpy(before_desc, group_base->value);
4179       linklist_free(group_base);
4180       group_base = NULL;
4181       group_count = 0;
4182     }
4183   change_to_lower_case(ad_distinguishedName);  
4184   strcpy(ou_both, group_ou_both);
4185   change_to_lower_case(ou_both);
4186   strcpy(ou_security, group_ou_security);
4187   change_to_lower_case(ou_security);
4188   strcpy(ou_distribution, group_ou_distribution);
4189   change_to_lower_case(ou_distribution);
4190   strcpy(ou_neither, group_ou_neither);
4191   change_to_lower_case(ou_neither);
4192   if (strstr(ad_distinguishedName, ou_both))
4193     {
4194       strcpy(before_group_ou, group_ou_both);
4195       before_group_membership[0] = 'B';
4196       before_security_flag = 1;
4197     }
4198   else if (strstr(ad_distinguishedName, ou_security))
4199     {
4200       strcpy(before_group_ou, group_ou_security);
4201       before_group_membership[0] = 'S';
4202       before_security_flag = 1;
4203     }
4204   else if (strstr(ad_distinguishedName, ou_distribution))
4205     {
4206       strcpy(before_group_ou, group_ou_distribution);
4207       before_group_membership[0] = 'D';
4208       before_security_flag = 0;
4209     }
4210   else if (strstr(ad_distinguishedName, ou_neither))
4211     {
4212       strcpy(before_group_ou, group_ou_neither);
4213       before_group_membership[0] = 'N';
4214       before_security_flag = 0;
4215     }
4216   else
4217     return(AD_NO_OU_FOUND);
4218   rc = group_rename(ldap_handle, dn_path, before_name, before_group_membership, 
4219                     before_group_ou, before_security_flag, before_desc,
4220                     group_name, group_membership, group_ou, group_security_flag,
4221                     before_desc, MoiraId, filter);
4222   return(rc);
4223 }
4224
4225 void change_to_lower_case(char *ptr)
4226 {
4227   int i;
4228
4229   for (i = 0; i < (int)strlen(ptr); i++)
4230     {
4231       ptr[i] = tolower(ptr[i]);
4232     }
4233 }
4234
4235 int ad_get_group(LDAP *ldap_handle, char *dn_path, 
4236                  char *group_name, char *group_membership, 
4237                  char *MoiraId, char *attribute,
4238                  LK_ENTRY **linklist_base, int *linklist_count,
4239                  char *rFilter)
4240 {
4241   LK_ENTRY  *pPtr;
4242   char  filter[128];
4243   char  *attr_array[3];
4244   int   rc;
4245
4246   (*linklist_base) = NULL;
4247   (*linklist_count) = 0;
4248   if (strlen(rFilter) != 0)
4249     {
4250       strcpy(filter, rFilter);
4251       attr_array[0] = attribute;
4252       attr_array[1] = NULL;
4253       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4254                                linklist_base, linklist_count, LDAP_SCOPE_SUBTREE)) != 0)
4255         {
4256           com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
4257                   MoiraId, ldap_err2string(rc));
4258          return(rc);
4259        }
4260     if ((*linklist_count) == 1)
4261       {
4262         strcpy(rFilter, filter);
4263         return(0);
4264       }
4265     }
4266
4267   linklist_free((*linklist_base));
4268   (*linklist_base) = NULL;
4269   (*linklist_count) = 0;
4270   if (strlen(MoiraId) != 0)
4271     {
4272       sprintf(filter, "(&(objectClass=group)(mitMoiraId=%s))", MoiraId);
4273       attr_array[0] = attribute;
4274       attr_array[1] = NULL;
4275       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4276                                linklist_base, linklist_count, LDAP_SCOPE_SUBTREE)) != 0)
4277         {
4278           com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
4279                   MoiraId, ldap_err2string(rc));
4280          return(rc);
4281        }
4282     }
4283   if ((*linklist_count) > 1)
4284     {
4285       com_err(whoami, 0, "multiple groups with mitMoiraId = %s", MoiraId);
4286       pPtr = (*linklist_base);
4287       while (pPtr)
4288         {
4289           com_err(whoami, 0, "groups %s has mitMoiraId = %s", pPtr->value, MoiraId);
4290           pPtr = pPtr->next;
4291         }
4292       linklist_free((*linklist_base));
4293       (*linklist_base) = NULL;
4294       (*linklist_count) = 0;
4295     }
4296   if ((*linklist_count) == 1)
4297     {
4298       if (!memcmp(&(*linklist_base)->value[3], group_name, strlen(group_name)))
4299         {
4300           strcpy(rFilter, filter);
4301           return(0);
4302         }
4303     }
4304
4305   linklist_free((*linklist_base));
4306   (*linklist_base) = NULL;
4307   (*linklist_count) = 0;
4308   sprintf(filter, "(sAMAccountName=%s_group)", group_name);
4309   attr_array[0] = attribute;
4310   attr_array[1] = NULL;
4311   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4312                            linklist_base, linklist_count, LDAP_SCOPE_SUBTREE)) != 0)
4313     {
4314       com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
4315               MoiraId, ldap_err2string(rc));
4316       return(rc);
4317     }
4318   if ((*linklist_count) == 1)
4319     {
4320       strcpy(rFilter, filter);
4321       return(0);
4322     }
4323
4324   return(0);
4325 }
4326
4327 int check_user(LDAP *ldap_handle, char *dn_path, char *UserName, char *MoiraId)
4328 {
4329   char filter[128];
4330   char *attr_array[3];
4331   char SamAccountName[64];
4332   int  group_count;
4333   int  rc;
4334   LK_ENTRY  *group_base;
4335   LK_ENTRY  *gPtr;
4336
4337   group_count = 0;
4338   group_base = NULL;
4339
4340   if (strlen(MoiraId) != 0)
4341     {
4342       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
4343       attr_array[0] = "sAMAccountName";
4344       attr_array[1] = NULL;
4345       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4346                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
4347         {
4348           com_err(whoami, 0, "Unable to process user %s : %s",
4349                   UserName, ldap_err2string(rc));
4350           return(rc);
4351         }
4352       if (group_count > 1)
4353         {
4354           com_err(whoami, 0, "multiple users exist with MoiraId = %s",
4355                   MoiraId);
4356           gPtr = group_base;
4357           while (gPtr)
4358             {
4359               com_err(whoami, 0, "user %s exist with MoiraId = %s",
4360                       gPtr->value, MoiraId);
4361               gPtr = gPtr->next;
4362             }
4363         }
4364     }
4365   if (group_count != 1)
4366     {
4367       linklist_free(group_base);
4368       group_count = 0;
4369       group_base = NULL;
4370       sprintf(filter, "(sAMAccountName=%s)", UserName);
4371       attr_array[0] = "sAMAccountName";
4372       attr_array[1] = NULL;
4373       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4374                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
4375         {
4376           com_err(whoami, 0, "Unable to process user %s : %s",
4377                   UserName, ldap_err2string(rc));
4378           return(rc);
4379         }
4380     }
4381
4382   if (group_count != 1)
4383     {
4384       linklist_free(group_base);
4385       return(AD_NO_USER_FOUND);
4386     }
4387   strcpy(SamAccountName, group_base->value);
4388   linklist_free(group_base);
4389   group_count = 0;
4390   rc = 0;
4391   if (strcmp(SamAccountName, UserName))
4392     {
4393       rc = user_rename(ldap_handle, dn_path, SamAccountName, 
4394                        UserName);
4395     }
4396   return(0);
4397 }
4398
4399 void container_get_dn(char *src, char *dest)
4400 {
4401   char *sPtr;
4402   char *array[20];
4403   char name[256];
4404   int  n;
4405
4406   memset(array, '\0', 20 * sizeof(array[0]));
4407
4408   if (strlen(src) == 0)
4409     return;
4410   strcpy(name, src);
4411   sPtr = name;
4412   n = 0;
4413   array[n] = name;
4414   ++n;
4415   while (*sPtr)
4416     {
4417       if ((*sPtr) == '/')
4418         {
4419           (*sPtr) = '\0';
4420           ++sPtr;
4421           array[n] = sPtr;
4422           ++n;
4423         }
4424       else
4425         ++sPtr;
4426     }
4427   strcpy(dest, "OU=");
4428   while (n != 0)
4429     {
4430       strcat(dest, array[n-1]);
4431       --n;
4432       if (n > 0)
4433         {
4434           strcat(dest, ",OU=");
4435         }
4436     }
4437   return;
4438 }
4439
4440 void container_get_name(char *src, char *dest)
4441 {
4442   char *sPtr;
4443   char *dPtr;
4444
4445   if (strlen(src) == 0)
4446     return;
4447   sPtr = src;
4448   dPtr = src;
4449   while (*sPtr)
4450     {
4451       if ((*sPtr) == '/')
4452         {
4453           dPtr = sPtr;
4454           ++dPtr;
4455         }
4456       ++sPtr;
4457     }
4458   strcpy(dest, dPtr);
4459   return;
4460 }
4461
4462 void container_check(LDAP *ldap_handle, char *dn_path, char *name)
4463 {
4464   char cName[256];
4465   char *av[7];
4466   int  i;
4467   int  rc;
4468
4469   strcpy(cName, name);
4470   for (i = 0; i < (int)strlen(cName); i++)
4471     {
4472       if (cName[i] == '/')
4473         {
4474           cName[i] = '\0';
4475           av[CONTAINER_NAME] = cName;
4476           av[CONTAINER_DESC] = "";
4477           av[CONTAINER_LOCATION] = "";
4478           av[CONTAINER_CONTACT] = "";
4479           av[CONTAINER_TYPE] = "";
4480           av[CONTAINER_ID] = "";
4481           av[CONTAINER_ROWID] = "";
4482           rc = container_create(ldap_handle, dn_path, 7, av);
4483           if (rc == LDAP_SUCCESS)
4484             {
4485               com_err(whoami, 0, "container %s created without a mitMoiraId", cName);
4486             }
4487           cName[i] = '/';
4488         }
4489     }
4490
4491 }
4492
4493 int container_rename(LDAP *ldap_handle, char *dn_path, int beforec, char **before, 
4494                      int afterc, char **after)
4495 {
4496   char      dName[256];
4497   char      cName[256];
4498   char      new_cn[128];
4499   char      new_dn_path[256];
4500   char      temp[256];
4501   char      distinguishedName[256];
4502   char      *pPtr;
4503   int       rc;
4504   int       i;
4505
4506   memset(cName, '\0', sizeof(cName));
4507   container_get_name(after[CONTAINER_NAME], cName);
4508   if (!check_container_name(cName))
4509     {
4510       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", cName);
4511       return(AD_INVALID_NAME);
4512     }
4513
4514   memset(distinguishedName, '\0', sizeof(distinguishedName));
4515   if (rc = container_get_distinguishedName(ldap_handle, dn_path, distinguishedName, beforec, before))
4516     return(rc);
4517   if (strlen(distinguishedName) == 0)
4518     {
4519       rc = container_create(ldap_handle, dn_path, afterc, after);
4520       return(rc);
4521     }
4522
4523   strcpy(temp, after[CONTAINER_NAME]);
4524   pPtr = temp;
4525   for (i = 0; i < (int)strlen(temp); i++)
4526     {
4527       if (temp[i] == '/')
4528         {
4529           pPtr = &temp[i];
4530         }
4531     }
4532   (*pPtr) = '\0';
4533
4534   container_get_dn(temp, dName);
4535   if (strlen(temp) != 0)
4536     sprintf(new_dn_path, "%s,%s", dName, dn_path);
4537   else
4538     sprintf(new_dn_path, "%s", dn_path);
4539   sprintf(new_cn, "OU=%s", cName);
4540
4541   container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
4542
4543   if ((rc = ldap_rename_s(ldap_handle, distinguishedName, new_cn, new_dn_path,
4544                           TRUE, NULL, NULL)) != LDAP_SUCCESS)
4545     {
4546       com_err(whoami, 0, "Unable to rename container from %s to %s : %s",
4547               before[CONTAINER_NAME], after[CONTAINER_NAME], ldap_err2string(rc));
4548       return(rc);
4549     }
4550
4551   memset(dName, '\0', sizeof(dName));
4552   container_get_dn(after[CONTAINER_NAME], dName);
4553   rc = container_adupdate(ldap_handle, dn_path, dName, "", afterc, after);
4554   return(rc);
4555 }
4556
4557 int container_delete(LDAP *ldap_handle, char *dn_path, int count, char **av)
4558 {
4559   char      distinguishedName[256];
4560   int       rc;
4561
4562   memset(distinguishedName, '\0', sizeof(distinguishedName));
4563   if (rc = container_get_distinguishedName(ldap_handle, dn_path, distinguishedName, count, av))
4564     return(rc);
4565   if (strlen(distinguishedName) == 0)
4566     return(0);
4567   if ((rc = ldap_delete_s(ldap_handle, distinguishedName)) != LDAP_SUCCESS)
4568     {
4569       if (rc == LDAP_NOT_ALLOWED_ON_NONLEAF)
4570         container_move_objects(ldap_handle, dn_path, distinguishedName);
4571       else
4572         com_err(whoami, 0, "Unable to delete container %s from AD : %s",
4573                 av[CONTAINER_NAME], ldap_err2string(rc));
4574     }
4575   return(rc);
4576 }
4577
4578 int container_create(LDAP *ldap_handle, char *dn_path, int count, char **av)
4579 {
4580   char      *attr_array[3];
4581   LK_ENTRY  *group_base;
4582   int       group_count;
4583   LDAPMod   *mods[20];
4584   char      *objectClass_v[] = {"top", 
4585                            "organizationalUnit", 
4586                            NULL};
4587
4588   char *ou_v[] = {NULL, NULL};
4589   char *name_v[] = {NULL, NULL};
4590   char *moiraId_v[] = {NULL, NULL};
4591   char *desc_v[] = {NULL, NULL};
4592   char *managedBy_v[] = {NULL, NULL};
4593   char dName[256];
4594   char cName[256];
4595   char managedByDN[256];
4596   char filter[256];
4597   char temp[256];
4598   int  n;
4599   int  i;
4600   int  rc;
4601
4602   memset(filter, '\0', sizeof(filter));
4603   memset(dName, '\0', sizeof(dName));
4604   memset(cName, '\0', sizeof(cName));
4605   memset(managedByDN, '\0', sizeof(managedByDN));
4606   container_get_dn(av[CONTAINER_NAME], dName);
4607   container_get_name(av[CONTAINER_NAME], cName);
4608
4609   if ((strlen(cName) == 0) || (strlen(dName) == 0))
4610     {
4611       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", cName);
4612       return(AD_INVALID_NAME);
4613     }
4614
4615   if (!check_container_name(cName))
4616     {
4617       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", cName);
4618       return(AD_INVALID_NAME);
4619     }
4620
4621   n = 0;
4622   ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
4623   name_v[0] = cName;
4624   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
4625   ou_v[0] = cName;
4626   ADD_ATTR("ou", ou_v, LDAP_MOD_ADD);
4627   if (strlen(av[CONTAINER_ROWID]) != 0)
4628     {
4629       moiraId_v[0] = av[CONTAINER_ROWID];
4630       ADD_ATTR("mitMoiraId", moiraId_v, LDAP_MOD_ADD);
4631     }
4632   if (strlen(av[CONTAINER_DESC]) != 0)
4633     {
4634       desc_v[0] = av[CONTAINER_DESC];
4635       ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
4636     }
4637   if ((strlen(av[CONTAINER_TYPE]) != 0) && (strlen(av[CONTAINER_ID]) != 0))
4638     {
4639           if (!strcasecmp(av[CONTAINER_TYPE], "KERBEROS"))
4640           {
4641                   if (!contact_create(ldap_handle, dn_path, av[CONTAINER_ID], kerberos_ou))
4642                   {
4643                         sprintf(managedByDN, "CN=%s,%s,%s", av[CONTAINER_ID], kerberos_ou,dn_path);
4644                         managedBy_v[0] = managedByDN;
4645                         ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_ADD);
4646                   }
4647           }
4648           else
4649           {
4650                 if (!strcasecmp(av[CONTAINER_TYPE], "USER"))
4651         {
4652           sprintf(filter, "(&(cn=%s)(&(objectCategory=person)(objectClass=user)))", av[CONTAINER_ID]);
4653         }
4654                 if (!strcasecmp(av[CONTAINER_TYPE], "LIST"))
4655         {
4656           sprintf(filter, "(&(objectClass=group)(cn=%s))", av[CONTAINER_ID]);
4657         }
4658                 if (strlen(filter) != 0)
4659         {
4660           attr_array[0] = "distinguishedName";
4661           attr_array[1] = NULL;
4662           group_count = 0;
4663           group_base = NULL;
4664           if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4665                                    &group_base, &group_count, LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
4666             {
4667               if (group_count == 1)
4668                 {
4669                   strcpy(managedByDN, group_base->value);
4670                   managedBy_v[0] = managedByDN;
4671                   ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_ADD);
4672                 }
4673               linklist_free(group_base);
4674               group_base = NULL;
4675               group_count = 0;
4676             }
4677         }
4678     }
4679   }
4680   mods[n] = NULL;
4681
4682   sprintf(temp, "%s,%s", dName, dn_path);
4683   rc = ldap_add_ext_s(ldap_handle, temp, mods, NULL, NULL);
4684   for (i = 0; i < n; i++)
4685     free(mods[i]);
4686   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
4687     {
4688       com_err(whoami, 0, "Unable to create container %s : %s",
4689               cName, ldap_err2string(rc));
4690       return(rc);
4691     }
4692   if (rc == LDAP_ALREADY_EXISTS)
4693     {
4694       if (strlen(av[CONTAINER_ROWID]) != 0)
4695         rc = container_adupdate(ldap_handle, dn_path, dName, "", count, av);
4696     }
4697   return(rc);
4698 }
4699
4700 int container_update(LDAP *ldap_handle, char *dn_path, int beforec, char **before, 
4701                      int afterc, char **after)
4702 {
4703   char distinguishedName[256];
4704   int  rc;
4705
4706   memset(distinguishedName, '\0', sizeof(distinguishedName));
4707   if (rc = container_get_distinguishedName(ldap_handle, dn_path, distinguishedName, afterc, after))
4708     return(rc);
4709   if (strlen(distinguishedName) == 0)
4710     {
4711       rc = container_create(ldap_handle, dn_path, afterc, after);
4712       return(rc);
4713     }
4714
4715   container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
4716   rc = container_adupdate(ldap_handle, dn_path, "", distinguishedName, afterc, after);
4717
4718   return(rc);
4719 }
4720
4721 int container_get_distinguishedName(LDAP *ldap_handle, char *dn_path, char *distinguishedName, int count, char **av)
4722 {
4723   char      *attr_array[3];
4724   LK_ENTRY  *group_base;
4725   int       group_count;
4726   char      dName[256];
4727   char      cName[256];
4728   char      filter[512];
4729   int       rc;
4730
4731   memset(filter, '\0', sizeof(filter));
4732   memset(dName, '\0', sizeof(dName));
4733   memset(cName, '\0', sizeof(cName));
4734   container_get_dn(av[CONTAINER_NAME], dName);
4735   container_get_name(av[CONTAINER_NAME], cName);
4736
4737   if (strlen(dName) == 0)
4738     {
4739       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", av[CONTAINER_NAME]);
4740       return(AD_INVALID_NAME);
4741     }
4742
4743   if (!check_container_name(cName))
4744     {
4745       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", cName);
4746       return(AD_INVALID_NAME);
4747     }
4748
4749   sprintf(filter, "(&(objectClass=organizationalUnit)(mitMoiraId=%s))", av[CONTAINER_ROWID]);
4750   attr_array[0] = "distinguishedName";
4751   attr_array[1] = NULL;
4752   group_count = 0;
4753   group_base = NULL;
4754   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4755                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
4756     {
4757       if (group_count == 1)
4758         {
4759           strcpy(distinguishedName, group_base->value);
4760         }
4761       linklist_free(group_base);
4762       group_base = NULL;
4763       group_count = 0;
4764     }
4765   if (strlen(distinguishedName) == 0)
4766     {
4767       sprintf(filter, "(&(objectClass=organizationalUnit)(distinguishedName=%s,%s))", dName, dn_path);
4768       attr_array[0] = "distinguishedName";
4769       attr_array[1] = NULL;
4770       group_count = 0;
4771       group_base = NULL;
4772       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4773                                &group_base, &group_count, LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
4774         {
4775           if (group_count == 1)
4776             {
4777               strcpy(distinguishedName, group_base->value);
4778             }
4779           linklist_free(group_base);
4780           group_base = NULL;
4781           group_count = 0;
4782         }
4783     }
4784   return(0);
4785 }
4786
4787 int container_adupdate(LDAP *ldap_handle, char *dn_path, char *dName, 
4788                        char *distinguishedName, int count, char **av)
4789 {
4790   char      *attr_array[5];
4791   LK_ENTRY  *group_base;
4792   LK_ENTRY  *pPtr;
4793   LDAPMod   *mods[20];
4794   int       group_count;
4795   char      filter[512];
4796   char      *moiraId_v[] = {NULL, NULL};
4797   char      *desc_v[] = {NULL, NULL};
4798   char      *managedBy_v[] = {NULL, NULL};
4799   char      managedByDN[256];
4800   char      moiraId[64];
4801   char      desc[256];
4802   char      ad_path[512];
4803   int       rc;
4804   int       i;
4805   int       n;
4806
4807
4808   strcpy(ad_path, distinguishedName);
4809   if (strlen(dName) != 0)
4810     sprintf(ad_path, "%s,%s", dName, dn_path);
4811
4812   sprintf(filter, "(&(objectClass=organizationalUnit)(distinguishedName=%s))", ad_path);
4813   if (strlen(av[CONTAINER_ID]) != 0)
4814     sprintf(filter, "(&(objectClass=organizationalUnit)(mitMoiraId=%s))", av[CONTAINER_ROWID]);
4815   attr_array[0] = "mitMoiraId";
4816   attr_array[1] = "description";
4817   attr_array[2] = "managedBy";
4818   attr_array[3] = NULL;
4819   group_count = 0;
4820   group_base = NULL;
4821   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4822                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != LDAP_SUCCESS)
4823     {
4824       com_err(whoami, 0, "Unable to retreive container info for %s : %s",
4825               av[CONTAINER_NAME], ldap_err2string(rc));
4826       return(rc);
4827     }
4828   memset(managedByDN, '\0', sizeof(managedByDN));
4829   memset(moiraId, '\0', sizeof(moiraId));
4830   memset(desc, '\0', sizeof(desc));
4831   pPtr = group_base;
4832   while (pPtr)
4833     {
4834       if (!strcasecmp(pPtr->attribute, "description"))
4835         strcpy(desc, pPtr->value);
4836       else if (!strcasecmp(pPtr->attribute, "managedBy"))
4837         strcpy(managedByDN, pPtr->value);
4838       else if (!strcasecmp(pPtr->attribute, "mitMoiraId"))
4839         strcpy(moiraId, pPtr->value);
4840       pPtr = pPtr->next;
4841     }
4842   linklist_free(group_base);
4843   group_base = NULL;
4844   group_count = 0;
4845
4846   n = 0;
4847   if (strlen(av[CONTAINER_ROWID]) != 0)
4848     {
4849       moiraId_v[0] = av[CONTAINER_ROWID];
4850       ADD_ATTR("mitMoiraId", moiraId_v, LDAP_MOD_REPLACE);
4851     }
4852   if (strlen(av[CONTAINER_DESC]) != 0)
4853     {
4854       attribute_update(ldap_handle, ad_path, av[CONTAINER_DESC], "description", dName);
4855     }
4856   else
4857     {
4858       if (strlen(desc) != 0)
4859         {
4860           attribute_update(ldap_handle, ad_path, "", "description", dName);
4861         }
4862     }
4863   if ((strlen(av[CONTAINER_TYPE]) != 0) && (strlen(av[CONTAINER_ID]) != 0))
4864     {
4865           if (!strcasecmp(av[CONTAINER_TYPE], "KERBEROS"))
4866           {
4867                   if (!contact_create(ldap_handle, dn_path, av[CONTAINER_ID], kerberos_ou))
4868                   {
4869                         sprintf(managedByDN, "CN=%s,%s,%s", av[CONTAINER_ID], kerberos_ou, dn_path);
4870                         managedBy_v[0] = managedByDN;
4871             ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_REPLACE);
4872                   }
4873                   else
4874                   {
4875                         if (strlen(managedByDN) != 0)
4876                         {
4877                 attribute_update(ldap_handle, ad_path, "", "managedBy", dName);
4878                         }
4879                   }
4880           }
4881           else
4882           {
4883                 memset(filter, '\0', sizeof(filter));
4884                 if (!strcasecmp(av[CONTAINER_TYPE], "USER"))
4885         {
4886           sprintf(filter, "(&(cn=%s)(&(objectCategory=person)(objectClass=user)))", av[CONTAINER_ID]);
4887         }
4888                 if (!strcasecmp(av[CONTAINER_TYPE], "LIST"))
4889         {
4890           sprintf(filter, "(&(objectClass=group)(cn=%s))", av[CONTAINER_ID]);
4891         }
4892                 if (strlen(filter) != 0)
4893         {
4894           attr_array[0] = "distinguishedName";
4895           attr_array[1] = NULL;
4896           group_count = 0;
4897           group_base = NULL;
4898           if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4899                                    &group_base, &group_count, LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
4900             {
4901               if (group_count == 1)
4902                 {
4903                   strcpy(managedByDN, group_base->value);
4904                   managedBy_v[0] = managedByDN;
4905                   ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_REPLACE);
4906                 }
4907               else
4908                 {
4909                   if (strlen(managedByDN) != 0)
4910                     {
4911                         attribute_update(ldap_handle, ad_path, "", "managedBy", dName);
4912                     }
4913                 }
4914               linklist_free(group_base);
4915               group_base = NULL;
4916               group_count = 0;
4917             }
4918         }
4919                 else
4920         {
4921           if (strlen(managedByDN) != 0)
4922             {
4923                 attribute_update(ldap_handle, ad_path, "", "managedBy", dName);
4924             }
4925         }
4926           }
4927     }
4928   mods[n] = NULL;
4929   if (n == 0)
4930     return(LDAP_SUCCESS);
4931
4932   rc = ldap_modify_s(ldap_handle, ad_path, mods);
4933   for (i = 0; i < n; i++)
4934     free(mods[i]);
4935   if (rc != LDAP_SUCCESS)
4936     {
4937         com_err(whoami, 0, "Unable to modify container info for %s : %s",
4938                 av[CONTAINER_NAME], ldap_err2string(rc));
4939         return(rc);
4940     }
4941   return(rc);
4942 }
4943
4944 int container_move_objects(LDAP *ldap_handle, char *dn_path, char *dName)
4945 {
4946   char      *attr_array[3];
4947   LK_ENTRY  *group_base;
4948   LK_ENTRY  *pPtr;
4949   int       group_count;
4950   char      filter[512];
4951   char      new_cn[128];
4952   char      temp[256];
4953   int       rc;
4954   int       NumberOfEntries = 10;
4955   int       i;
4956   int       count;
4957
4958   rc = ldap_set_option(ldap_handle, LDAP_OPT_SIZELIMIT, &NumberOfEntries);
4959
4960   for (i = 0; i < 3; i++)
4961     {
4962       memset(filter, '\0', sizeof(filter));
4963       if (i == 0)
4964         {
4965           strcpy(filter, "(!(|(objectClass=computer)(objectClass=organizationalUnit)))");
4966           attr_array[0] = "cn";
4967           attr_array[1] = NULL;
4968         }
4969       else if (i == 1)
4970         {
4971           strcpy(filter, "(objectClass=computer)");
4972           attr_array[0] = "cn";
4973           attr_array[1] = NULL;
4974         }
4975       else
4976         {
4977           strcpy(filter, "(objectClass=organizationalUnit)");
4978           attr_array[0] = "ou";
4979           attr_array[1] = NULL;
4980         }
4981
4982       while (1)
4983         {
4984           if ((rc = linklist_build(ldap_handle, dName, filter, attr_array, 
4985                                    &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != LDAP_SUCCESS)
4986             {
4987               break;
4988             }
4989           if (group_count == 0)
4990             break;
4991           pPtr = group_base;
4992           while(pPtr)
4993             {
4994               if (!strcasecmp(pPtr->attribute, "cn"))
4995                 {
4996                   sprintf(new_cn, "cn=%s", pPtr->value);
4997                   if (i == 0)
4998                     sprintf(temp, "%s,%s", orphans_other_ou, dn_path);
4999                   if (i == 1)
5000                     sprintf(temp, "%s,%s", orphans_machines_ou, dn_path);
5001                   count = 1;
5002                   while (1)
5003                     {
5004                       rc = ldap_rename_s(ldap_handle, pPtr->dn, new_cn, temp,
5005                                          TRUE, NULL, NULL);
5006                       if (rc == LDAP_ALREADY_EXISTS)
5007                         {
5008                           sprintf(new_cn, "cn=%s_%d", pPtr->value, count);
5009                           ++count;
5010                         }
5011                       else
5012                         break;
5013                     }
5014                 }
5015               else if (!strcasecmp(pPtr->attribute, "ou"))
5016                 {
5017                   rc = ldap_delete_s(ldap_handle, pPtr->dn);
5018                 }
5019               pPtr = pPtr->next;
5020             }
5021           linklist_free(group_base);
5022           group_base = NULL;
5023           group_count = 0;
5024         }
5025     }
5026   return(0);
5027 }
5028
5029 int get_machine_ou(LDAP *ldap_handle, char *dn_path, char *member, char *machine_ou, char *NewMachineName)
5030 {
5031   LK_ENTRY  *group_base;
5032   int  group_count;
5033   int  i;
5034   char filter[128];
5035   char *attr_array[3];
5036   char cn[256];
5037   char dn[256];
5038   char temp[256];
5039   char *pPtr;
5040   int   rc;
5041
5042   strcpy(NewMachineName, member);
5043   rc = moira_connect();
5044   rc = GetMachineName(NewMachineName);
5045   moira_disconnect();
5046   if (strlen(NewMachineName) == 0)
5047     {
5048       com_err(whoami, 0, "Unable to find alais for machine %s in Moira", member);
5049       return(1);
5050     }
5051
5052   pPtr = NULL;
5053   pPtr = strchr(NewMachineName, '.');
5054   if (pPtr != NULL)
5055     (*pPtr) = '\0';
5056
5057   group_base = NULL;
5058   group_count = 0;
5059   sprintf(filter, "(sAMAccountName=%s$)", NewMachineName);
5060   attr_array[0] = "cn";
5061   attr_array[1] = NULL;
5062   sprintf(temp, "%s", dn_path);
5063   if ((rc = linklist_build(ldap_handle, temp, filter, attr_array, 
5064                         &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
5065     {
5066       com_err(whoami, 0, "Unable to process machine %s : %s",
5067               member, ldap_err2string(rc));
5068       return(1);
5069     }
5070   if (group_count != 1)
5071     {
5072       com_err(whoami, 0, "Unable to process machine %s : machine not found in AD",
5073               NewMachineName);
5074       return(1);
5075     }
5076   strcpy(dn, group_base->dn);
5077   strcpy(cn, group_base->value);
5078   for (i = 0; i < (int)strlen(dn); i++)
5079     dn[i] = tolower(dn[i]);
5080   for (i = 0; i < (int)strlen(cn); i++)
5081     cn[i] = tolower(cn[i]);
5082   linklist_free(group_base);
5083   pPtr = NULL;
5084   pPtr = strstr(dn, cn);
5085   if (pPtr == NULL)
5086     {
5087       com_err(whoami, 0, "Unable to process machine %s",
5088               member);
5089       return(1);
5090     }
5091   pPtr += strlen(cn) + 1;
5092   strcpy(machine_ou, pPtr);
5093   pPtr = NULL;
5094   pPtr = strstr(machine_ou, "dc=");
5095   if (pPtr == NULL)
5096     {
5097       com_err(whoami, 0, "Unable to process machine %s",
5098               member);
5099       return(1);
5100     }
5101   --pPtr;
5102   (*pPtr) = '\0';
5103   return(0);
5104 }
5105
5106 int machine_move_to_ou(LDAP *ldap_handle, char * dn_path, char *MoiraMachineName, char *DestinationOu)
5107 {
5108
5109     char        NewCn[128];
5110     char        OldDn[512];
5111     char        MachineName[128];
5112     char        filter[128];
5113     char        *attr_array[3];
5114     char        NewOu[256];
5115     char        *cPtr = NULL;
5116     int         group_count;
5117     long        rc;
5118     LK_ENTRY    *group_base;
5119
5120     group_count = 0;
5121     group_base = NULL;
5122
5123     strcpy(MachineName, MoiraMachineName);
5124     rc = GetMachineName(MachineName);
5125     if (strlen(MachineName) == 0)
5126     {
5127         com_err(whoami, 0, "Unable to find alais for machine %s in Moira", MoiraMachineName);
5128         return(1);
5129     }
5130
5131     cPtr = strchr(MachineName, '.');
5132     if (cPtr != NULL)
5133         (*cPtr) = '\0';
5134     sprintf(filter, "(sAMAccountName=%s$)", MachineName);
5135     attr_array[0] = "sAMAccountName";
5136     attr_array[1] = NULL;
5137     if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, &group_base, 
5138                              &group_count, LDAP_SCOPE_SUBTREE)) != 0)
5139     {
5140         com_err(whoami, 0, "Unable to process machine %s : %s",
5141                 MoiraMachineName, ldap_err2string(rc));
5142         return(1);
5143     }
5144
5145     if (group_count == 1)
5146         strcpy(OldDn, group_base->dn);
5147     linklist_free(group_base);
5148     group_base = NULL;
5149     if (group_count != 1)
5150     {
5151         com_err(whoami, 0, "Unable to find machine %s in AD: %s", MoiraMachineName);
5152         return(1);
5153     }
5154     sprintf(NewOu, "%s,%s", DestinationOu, dn_path);
5155     cPtr = strchr(OldDn, ',');
5156     if (cPtr != NULL)
5157     {
5158         ++cPtr;
5159         if (!strcasecmp(cPtr, NewOu))
5160             return(0);
5161     }
5162     sprintf(NewCn, "CN=%s", MachineName);
5163     rc = ldap_rename_s(ldap_handle, OldDn, NewCn, NewOu, TRUE, NULL, NULL);
5164     return(rc);
5165 }
5166
5167 int machine_check(LDAP *ldap_handle, char *dn_path, char *machine_name)
5168 {
5169     char    Name[128];
5170     char    *pPtr;
5171     int     rc;
5172
5173     memset(Name, '\0', sizeof(Name));
5174     strcpy(Name, machine_name);
5175     pPtr = NULL;
5176     pPtr = strchr(Name, '.');
5177     if (pPtr != NULL)
5178         (*pPtr) = '\0';
5179     strcat(Name, "$");
5180     return(!(rc = checkADname(ldap_handle, dn_path, Name)));
5181 }
5182
5183 int machine_get_moira_container(LDAP *ldap_handle, char *dn_path, char *machine_name, char *container_name)
5184 {
5185     int     rc;
5186     char    *av[2];
5187     char    *call_args[2];
5188
5189     av[0] = machine_name;
5190     call_args[0] = (char *)container_name;
5191     rc = mr_query("get_machine_to_container_map", 1, av, machine_GetMoiraContainer,
5192                    call_args);
5193     return(rc);
5194 }
5195
5196 int machine_GetMoiraContainer(int ac, char **av, void *ptr)
5197 {
5198     char **call_args;
5199     
5200     call_args = ptr;
5201     strcpy(call_args[0], av[1]);
5202     return(0);
5203 }
5204
5205 int Moira_container_group_create(char **after)
5206 {
5207   long rc;
5208   char GroupName[64];
5209   char *argv[20];
5210   
5211   memset(GroupName, '\0', sizeof(GroupName));
5212   rc = Moira_groupname_create(GroupName, after[CONTAINER_NAME], 
5213                               after[CONTAINER_ROWID]);
5214   if (rc)
5215     return rc;
5216   
5217   argv[L_NAME] = GroupName;
5218   argv[L_ACTIVE] = "1";
5219   argv[L_PUBLIC] = "0";
5220   argv[L_HIDDEN] = "0";
5221   argv[L_MAILLIST] = "0";
5222   argv[L_GROUP] = "1";
5223   argv[L_GID] = UNIQUE_GID;
5224   argv[L_NFSGROUP] = "0";
5225   argv[L_MAILMAN] = "0";
5226   argv[L_MAILMAN_SERVER] = "[NONE]";
5227   argv[L_DESC] = "auto created container group";
5228   argv[L_ACE_TYPE] = "USER";
5229   argv[L_MEMACE_TYPE] = "USER";
5230   argv[L_ACE_NAME] = "sms";
5231   argv[L_MEMACE_NAME] = "sms";
5232
5233   if (rc = mr_query("add_list", 15, argv, NULL, NULL))
5234     {
5235       com_err(whoami, 0, "Unable to create container group %s for container %s: %s",
5236               GroupName, after[CONTAINER_NAME], error_message(rc));
5237     }
5238
5239   Moira_setContainerGroup(after[CONTAINER_NAME], GroupName);
5240   Moira_addGroupToParent(after[CONTAINER_NAME], GroupName);
5241   
5242   return(rc);
5243 }
5244
5245 int Moira_container_group_update(char **before, char **after)
5246 {
5247   long rc;
5248   char BeforeGroupName[64];
5249   char AfterGroupName[64];
5250   char *argv[20];
5251   
5252   if (!strcasecmp(after[CONTAINER_NAME], before[CONTAINER_NAME]))
5253     return(0);
5254
5255   memset(BeforeGroupName, '\0', sizeof(BeforeGroupName));
5256   Moira_getGroupName(after[CONTAINER_NAME], BeforeGroupName, 0);
5257   if (strlen(BeforeGroupName) == 0)
5258     return(0);
5259
5260   memset(AfterGroupName, '\0', sizeof(AfterGroupName));
5261   rc = Moira_groupname_create(AfterGroupName, after[CONTAINER_NAME], 
5262                               after[CONTAINER_ROWID]);
5263   if (rc)
5264     return rc;
5265
5266   if (strcasecmp(BeforeGroupName, AfterGroupName))
5267     {
5268       argv[L_NAME] = BeforeGroupName;
5269       argv[L_NAME + 1] = AfterGroupName;
5270       argv[L_ACTIVE + 1] = "1";
5271       argv[L_PUBLIC + 1] = "0";
5272       argv[L_HIDDEN + 1] = "0";
5273       argv[L_MAILLIST + 1] = "0";
5274       argv[L_GROUP + 1] = "1";
5275       argv[L_GID + 1] = UNIQUE_GID;
5276       argv[L_NFSGROUP + 1] = "0";
5277       argv[L_MAILMAN + 1] = "0";
5278       argv[L_MAILMAN_SERVER + 1] = "[NONE]";
5279       argv[L_DESC + 1] = "auto created container group";
5280       argv[L_ACE_TYPE + 1] = "USER";
5281       argv[L_MEMACE_TYPE + 1] = "USER";
5282       argv[L_ACE_NAME + 1] = "sms";
5283       argv[L_MEMACE_NAME + 1] = "sms";
5284       
5285       if (rc = mr_query("update_list", 16, argv, NULL, NULL))
5286         {
5287           com_err(whoami, 0, "Unable to rename container group from %s to %s: %s",
5288                   BeforeGroupName, AfterGroupName, error_message(rc));
5289         }
5290     }
5291   
5292   return(rc);
5293 }
5294
5295 int Moira_container_group_delete(char **before)
5296 {
5297   long rc = 0;
5298   char *argv[13];
5299   char GroupName[64];
5300   char ParentGroupName[64];
5301   
5302   memset(ParentGroupName, '\0', sizeof(ParentGroupName));
5303   Moira_getGroupName(before[CONTAINER_NAME], ParentGroupName, 1);
5304
5305   memset(GroupName, '\0', sizeof(GroupName));
5306   if (strcmp(before[CONTAINER_GROUP_NAME], "[none]"))
5307     strcpy(GroupName, before[CONTAINER_GROUP_NAME]);
5308   
5309   if ((strlen(ParentGroupName) != 0) && (strlen(GroupName) != 0))
5310     {
5311       argv[0] = ParentGroupName;
5312       argv[1] = "LIST";
5313       argv[2] = GroupName;
5314       if (rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL))
5315         {
5316           com_err(whoami, 0, "Unable to delete container group %s from list: %s",
5317                   GroupName, ParentGroupName, error_message(rc));
5318         }
5319     }
5320   
5321   if (strlen(GroupName) != 0)
5322     {
5323       argv[0] = GroupName;
5324       if (rc = mr_query("delete_list", 1, argv, NULL, NULL))
5325         {
5326           com_err(whoami, 0, "Unable to delete container group %s : %s",
5327                   GroupName, error_message(rc));
5328         }
5329      }
5330   
5331   return(rc);
5332 }
5333
5334 int Moira_groupname_create(char *GroupName, char *ContainerName,
5335                            char *ContainerRowID)
5336 {
5337   char *ptr;
5338   char *ptr1;
5339   char temp[64];
5340   char newGroupName[64];
5341   char tempGroupName[64];
5342   char tempgname[64];
5343   char *argv[1];
5344   int  i;
5345   long rc;
5346
5347   strcpy(temp, ContainerName);
5348   
5349   ptr1 = strrchr(temp, '/');
5350   if (ptr1 != NULL)
5351   {
5352     *ptr1 = '\0';
5353     ptr = ++ptr1;
5354     ptr1 = strrchr(temp, '/');
5355     if (ptr1 != NULL)
5356     {
5357         sprintf(tempgname, "%s-%s", ++ptr1, ptr);
5358     }
5359     else
5360         strcpy(tempgname, ptr);
5361   }
5362   else
5363     strcpy(tempgname, temp);
5364
5365   if (strlen(tempgname) > 25)
5366     tempgname[25] ='\0';
5367
5368   sprintf(newGroupName, "cnt-%s", tempgname);
5369
5370   /* change everything to lower case */
5371   ptr = newGroupName;
5372   while (*ptr)
5373     {
5374       if (isupper(*ptr))
5375         *ptr = tolower(*ptr);
5376       if (*ptr == ' ')
5377         *ptr = '-';
5378       ptr++;
5379     }
5380
5381   strcpy(tempGroupName, newGroupName);
5382   i = (int)'0';
5383   /* append 0-9 then a-z if a duplicate is found */
5384   while(1)
5385     {
5386       argv[0] = newGroupName;
5387       if (rc = mr_query("get_list_info", 1, argv, NULL, NULL))
5388         {
5389           if (rc == MR_NO_MATCH)
5390             break;
5391           com_err(whoami, 0, "Moira error while creating group name for container %s : %s",
5392                   ContainerName, error_message(rc));
5393           return rc;
5394         }
5395       sprintf(newGroupName, "%s-%c", tempGroupName, i);
5396       if (i == (int)'z')
5397         {
5398           com_err(whoami, 0, "Unable to find a unique group name for container %s: too many duplicate container names",
5399                   ContainerName);
5400           return 1;
5401         }
5402       if (i == '9')
5403         i = 'a';
5404       else
5405         i++;
5406     }
5407
5408   strcpy(GroupName, newGroupName);
5409   return(0);
5410 }
5411
5412 int Moira_setContainerGroup(char *origContainerName, char *GroupName)
5413 {
5414   long rc;
5415   char *argv[3];
5416   
5417   argv[0] = origContainerName;
5418   argv[1] = GroupName;
5419
5420   if ((rc = mr_query("set_container_list", 2, argv, NULL, NULL)))
5421     {
5422          com_err(whoami, 0, "Unable to set container group %s in container %s: %s",
5423                  GroupName, origContainerName, error_message(rc));
5424     }
5425
5426   return(0);
5427 }
5428
5429  int Moira_addGroupToParent(char *origContainerName, char *GroupName)
5430  {
5431    char ContainerName[64];
5432    char ParentGroupName[64];
5433    char *argv[3];
5434    long rc;
5435
5436    strcpy(ContainerName, origContainerName);
5437
5438    Moira_getGroupName(ContainerName, ParentGroupName, 1);
5439    /* top-level container */
5440    if (strlen(ParentGroupName) == 0)
5441      return(0);
5442    
5443    argv[0] = ParentGroupName;
5444    argv[1] = "LIST";
5445    argv[2] = GroupName;
5446    if ((rc = mr_query("add_member_to_list", 3, argv, NULL, NULL)))
5447      {
5448        com_err(whoami, 0, "Unable to add container group %s to parent group %s: %s",
5449                GroupName, ParentGroupName, error_message(rc));
5450      }
5451    return(0);
5452  }
5453
5454 int Moira_getContainerGroup(int ac, char **av, void *ptr)
5455 {
5456   char **call_args;
5457   
5458   call_args = ptr;
5459   strcpy(call_args[0], av[1]);
5460   return(0);
5461 }
5462
5463 int Moira_getGroupName(char *origContainerName, char *GroupName,
5464                        int ParentFlag)
5465 {
5466   char ContainerName[64];
5467   char *argv[3];
5468   char *call_args[3];
5469   char *ptr;
5470   long rc;
5471
5472   strcpy(ContainerName, origContainerName);
5473
5474   if (ParentFlag)
5475     {
5476       ptr = strrchr(ContainerName, '/');
5477       if (ptr != NULL)
5478         (*ptr) = '\0';
5479       else
5480         return(0);
5481     }
5482
5483   argv[0] = ContainerName;
5484   argv[1] = NULL;
5485   call_args[0] = GroupName;
5486   call_args[1] = NULL;
5487
5488   if (!(rc = mr_query("get_container_list", 1, argv, Moira_getContainerGroup,
5489                       call_args)))
5490     {
5491       if (strlen(GroupName) != 0)
5492         return(0);
5493     }
5494
5495   if (rc)
5496     com_err(whoami, 0, "Unable to get container group from container %s: %s",
5497             ContainerName, error_message(rc));
5498   else
5499     com_err(whoami, 0, "Unable to get container group from container %s",
5500             ContainerName);
5501      return(0);
5502 }
5503
5504 int Moira_process_machine_container_group(char *MachineName, char* GroupName, 
5505                                           int DeleteMachine)
5506 {
5507   char *argv[3];
5508   long rc;
5509
5510   if (strcmp(GroupName, "[none]") == 0)
5511     return 0;
5512
5513   argv[0] = GroupName;
5514   argv[1] = "MACHINE";
5515   argv[2] = MachineName;
5516   if (!DeleteMachine)
5517     rc = mr_query("add_member_to_list", 3, argv, NULL, NULL);
5518   else
5519     rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL);
5520   if (rc)
5521     {
5522       com_err(whoami, 0, "Unable to add machine %s to container group%s: %s",
5523               MachineName, GroupName, error_message(rc));
5524     }
5525   return(0);
5526 }
5527
5528 int GetMachineName(char *MachineName)
5529 {
5530         char    *args[2];
5531     char    NewMachineName[1024];
5532     char    *szDot;
5533     int     rc = 0;
5534     int     i;
5535     DWORD   dwLen = 0;
5536     char    *call_args[2];
5537
5538     // If the address happens to be in the top-level MIT domain, great!
5539     strcpy(NewMachineName, MachineName);
5540     for (i = 0; i < (int)strlen(NewMachineName); i++)
5541         NewMachineName[i] = toupper(NewMachineName[i]);
5542     szDot = strchr(NewMachineName,'.');
5543     if ((szDot) && (!strcasecmp(szDot+1, DOMAIN_SUFFIX)))
5544     {
5545         return(0);
5546     }
5547         
5548     // If not, see if it has a Moira alias in the top-level MIT domain.
5549     memset(NewMachineName, '\0', sizeof(NewMachineName));
5550         args[0] = "*";
5551     args[1] = MachineName;
5552     call_args[0] = NewMachineName;
5553     call_args[1] = NULL;
5554     if (rc = mr_query("get_hostalias", 2, args, ProcessMachineName, call_args))
5555     {
5556         com_err(whoami, 0, "Unable to resolve machine name %s : %s",
5557                 MachineName, error_message(rc));
5558         strcpy(MachineName, "");
5559         return(0);
5560     }
5561
5562     if (strlen(NewMachineName) != 0)
5563         strcpy(MachineName, NewMachineName);
5564     else
5565         strcpy(MachineName, "");
5566     return(0);
5567
5568 }
5569
5570 int ProcessMachineName(int ac, char **av, void *ptr)
5571 {
5572     char    **call_args;
5573     char    MachineName[1024];
5574     char    *szDot;
5575     int     i;
5576
5577     call_args = ptr;
5578     if (strlen(call_args[0]) == 0)
5579     {
5580         strcpy(MachineName, av[0]);
5581         for (i = 0; i < (int)strlen(MachineName); i++)
5582             MachineName[i] = toupper(MachineName[i]);
5583         szDot = strchr(MachineName,'.');
5584         if ((szDot) && (!strcasecmp(szDot+1,DOMAIN_SUFFIX)))
5585         {
5586             strcpy(call_args[0], MachineName);
5587         }
5588     }
5589     return(0);
5590 }
5591
5592 void SwitchSFU(LDAPMod **mods, int *UseSFU30, int n)
5593 {
5594     int i;
5595
5596     if (*UseSFU30)
5597     {
5598         for (i = 0; i < n; i++)
5599         {
5600             if (!strcmp(mods[i]->mod_type, "msSFU30UidNumber"))
5601                 mods[i]->mod_type = "uidNumber";
5602         }
5603         (*UseSFU30) = 0;
5604     }
5605     else
5606     {
5607         for (i = 0; i < n; i++)
5608         {
5609             if (!strcmp(mods[i]->mod_type, "uidNumber"))
5610                 mods[i]->mod_type = "msSFU30UidNumber";
5611         }
5612         (*UseSFU30) = 1;
5613     }
5614 }
5615
5616 int SetHomeDirectory(LDAP *ldap_handle, char *user_name, char *DistinguishedName,
5617                      char *WinHomeDir, char *WinProfileDir,
5618                      char **homedir_v, char **winProfile_v,
5619                      char **drives_v, LDAPMod **mods, 
5620                      int OpType, int n)
5621 {
5622     char **hp;
5623     char cWeight[3];
5624     char cPath[1024];
5625     char path[1024];
5626     char winPath[1024];
5627     char winProfile[1024];
5628     char homeDrive[8];
5629     int  last_weight;
5630     int  i;
5631     int  rc;
5632     LDAPMod *DelMods[20];
5633
5634     memset(homeDrive, '\0', sizeof(homeDrive));
5635     memset(path, '\0', sizeof(path));
5636     memset(winPath, '\0', sizeof(winPath));
5637     memset(winProfile, '\0', sizeof(winProfile));
5638     hp = NULL;
5639     if ((!strcasecmp(WinHomeDir, "[afs]")) || (!strcasecmp(WinProfileDir, "[afs]")))
5640     {
5641         if ((hp = hes_resolve(user_name, "filsys")) != NULL)
5642         {
5643             memset(cWeight, 0, sizeof(cWeight));
5644             memset(cPath, 0, sizeof(cPath));
5645             last_weight = 1000;
5646             i = 0;
5647             while (hp[i] != NULL)
5648             {
5649                 if (sscanf(hp[i], "%*s %s", cPath))
5650                 {
5651                     if (strnicmp(cPath, AFS, strlen(AFS)) == 0)
5652                     {
5653                         if (sscanf(hp[i], "%*s %*s %*s %*s %s", cWeight))
5654                         {
5655                             if (atoi(cWeight) < last_weight)
5656                             {
5657                                 strcpy(path, cPath);
5658                                 last_weight = (int)atoi(cWeight);
5659                             }
5660                         }
5661                         else 
5662                             strcpy(path, cPath);
5663                     }
5664                 }
5665               ++i;
5666             }
5667             if (strlen(path))
5668             {
5669                 if (!strnicmp(path, AFS, strlen(AFS)))
5670                 {
5671                     AfsToWinAfs(path, winPath);
5672                     strcpy(winProfile, winPath);
5673                     strcat(winProfile, "\\.winprofile");
5674                 }
5675             }
5676         }
5677         else
5678             return(n);
5679     }
5680
5681     if ((!strcasecmp(WinHomeDir, "[dfs]")) || (!strcasecmp(WinProfileDir, "[dfs]")))
5682     {
5683         sprintf(path, "\\\\%s\\dfs\\profiles\\%c\\%s", ldap_domain, user_name[0], user_name);
5684         if (!strcasecmp(WinProfileDir, "[dfs]"))
5685           {
5686             strcpy(winProfile, path);
5687             strcat(winProfile, "\\.winprofile");
5688           }
5689         if (!strcasecmp(WinHomeDir, "[dfs]"))
5690           strcpy(winPath, path);
5691     }
5692
5693     if (hp != NULL)
5694     {
5695         i = 0;
5696         while (hp[i])
5697         {
5698             free(hp[i]);
5699             i++;
5700         }
5701     }
5702
5703     if (!strcasecmp(WinHomeDir, "[local]"))
5704         memset(winPath, '\0', sizeof(winPath));
5705     else if (!strcasecmp(WinHomeDir, "[afs]") || !strcasecmp(WinHomeDir, "[dfs]"))
5706     {
5707         strcpy(homeDrive, "H:");
5708     }
5709     else
5710     {
5711         strcpy(winPath, WinHomeDir);
5712         if (!strncmp(WinHomeDir, "\\\\", 2))
5713         {
5714             strcpy(homeDrive, "H:");
5715         }        
5716     }
5717
5718     // nothing needs to be done if WinProfileDir is [afs].
5719     if (!strcasecmp(WinProfileDir, "[local]"))
5720         memset(winProfile, '\0', sizeof(winProfile));
5721     else if (strcasecmp(WinProfileDir, "[afs]") && strcasecmp(WinProfileDir, "[dfs]"))
5722     {
5723         strcpy(winProfile, WinProfileDir);
5724     }
5725
5726     if (strlen(winProfile) != 0)
5727     {
5728         if (winProfile[strlen(winProfile) - 1] == '\\')
5729             winProfile[strlen(winProfile) - 1] = '\0';
5730     }
5731     if (strlen(winPath) != 0)
5732     {
5733         if (winPath[strlen(winPath) - 1] == '\\')
5734             winPath[strlen(winPath) - 1] = '\0';
5735     }
5736
5737     if ((winProfile[1] == ':') && (strlen(winProfile) == 2))
5738         strcat(winProfile, "\\");
5739     if ((winPath[1] == ':') && (strlen(winPath) == 2))
5740         strcat(winPath, "\\");
5741
5742     if (strlen(winPath) == 0)
5743     {
5744         if (OpType == LDAP_MOD_REPLACE)
5745         {
5746             i = 0;
5747             DEL_ATTR("homeDirectory", LDAP_MOD_DELETE);
5748             DelMods[i] = NULL;
5749             //unset homeDirectory attribute for user.
5750             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
5751             free(DelMods[0]);
5752         }
5753     }
5754     else
5755     {
5756         homedir_v[0] = strdup(winPath);
5757         ADD_ATTR("homeDirectory", homedir_v, OpType);
5758     }
5759
5760     if (strlen(winProfile) == 0)
5761     {
5762         if (OpType == LDAP_MOD_REPLACE)
5763         {
5764             i = 0;
5765             DEL_ATTR("profilePath", LDAP_MOD_DELETE);
5766             DelMods[i] = NULL;
5767             //unset profilePate attribute for user.
5768             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
5769             free(DelMods[0]);
5770         }
5771     }
5772     else
5773     {
5774         winProfile_v[0] = strdup(winProfile);
5775         ADD_ATTR("profilePath", winProfile_v, OpType);
5776     }
5777
5778     if (strlen(homeDrive) == 0)
5779     {
5780         if (OpType == LDAP_MOD_REPLACE)
5781         {
5782             i = 0;
5783             DEL_ATTR("homeDrive", LDAP_MOD_DELETE);
5784             DelMods[i] = NULL;
5785             //unset homeDrive attribute for user
5786             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
5787             free(DelMods[0]);
5788         }
5789     }
5790     else
5791     {
5792         drives_v[0] = strdup(homeDrive);
5793         ADD_ATTR("homeDrive", drives_v, OpType);
5794     }
5795
5796     return(n);
5797 }
5798
5799 int GetServerList(char *ldap_domain, char **ServerList)
5800 {
5801   unsigned long   rc;
5802   int             group_count;
5803   int             UseSFU30;
5804   int             Count;
5805   int             i;
5806   int             k;
5807   int             ServerListFound;
5808   char            default_server[256];
5809   char            dn_path[256];
5810   char            *attr_array[3];
5811   char            *sPtr;
5812   char            base[128];
5813   char            filter[128];
5814   LK_ENTRY        *group_base;
5815   LK_ENTRY        *gPtr;
5816   LDAP            *ldap_handle;
5817   FILE            *fptr;
5818
5819   memset(default_server, '\0', sizeof(default_server));
5820   memset(dn_path, '\0', sizeof(dn_path));
5821   for (i = 0; i < MAX_SERVER_NAMES; i++)
5822     {
5823       if (ServerList[i] != NULL)
5824         {
5825           free(ServerList[i]);
5826           ServerList[i] = NULL;
5827         }
5828     }
5829   if (rc = ad_connect(&ldap_handle, ldap_domain, dn_path, "", "", default_server, 0, 
5830                       ServerList))
5831       return(1);
5832   memset(ServerList, '\0', sizeof(ServerList[0]) * MAX_SERVER_NAMES);
5833   group_count = 0;
5834   group_base = NULL;
5835   Count = 0;
5836   ServerListFound = 0;
5837
5838   strcpy(filter, "(&(objectClass=rIDManager)(fSMORoleOwner=*))");
5839   attr_array[0] = "fSMORoleOwner";
5840   attr_array[1] = NULL;
5841   if (!(rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
5842                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
5843     {
5844       if (group_count != 0)
5845         {
5846           sPtr = strstr(group_base->value, ",CN=");
5847           if (sPtr != NULL)
5848             {
5849               sPtr += strlen(",CN=");
5850               if (ServerList[0] == NULL)
5851                   ServerList[0] = calloc(1, 256);
5852               strcpy(ServerList[0], sPtr);
5853               sPtr = strstr(ServerList[0], ",");
5854               if (sPtr != NULL)
5855                   (*sPtr) = '\0';
5856               ++Count;
5857               ServerListFound = 1;
5858             }
5859         }
5860     }
5861   linklist_free(group_base);
5862
5863   group_count = 0;
5864   group_base = NULL;
5865   attr_array[0] = "cn";
5866   attr_array[1] = NULL;
5867   strcpy(filter, "(cn=*)");
5868   sprintf(base, "cn=Servers,cn=Default-First-Site-Name,cn=Sites,cn=Configuration,%s", dn_path);
5869
5870   if (!(rc = linklist_build(ldap_handle, base, filter, attr_array, 
5871                            &group_base, &group_count, LDAP_SCOPE_ONELEVEL)) != 0)
5872     {
5873       if (group_count != 0)
5874         {
5875           gPtr = group_base;
5876           while (gPtr != NULL)
5877             {
5878               if (ServerListFound != 0)
5879                 {
5880                   if (!strcasecmp(ServerList[0], gPtr->value))
5881                     {
5882                       gPtr = gPtr->next;
5883                       continue;
5884                     }
5885                 }
5886               if (Count < MAX_SERVER_NAMES)
5887                 {
5888                   if (ServerList[Count] == NULL)
5889                       ServerList[Count] = calloc(1, 256);
5890                   strcpy(ServerList[Count], gPtr->value);
5891                   gPtr = gPtr->next;
5892                   ++Count;
5893                 }
5894             }
5895         }
5896     }
5897   linklist_free(group_base);
5898
5899   UseSFU30 = 0;
5900   group_count = 0;
5901   group_base = NULL;
5902
5903   strcpy(filter, "(cn=msSFU-30-Uid-Number)");
5904   sprintf(base, "cn=schema,cn=configuration,%s", dn_path);
5905
5906   if (!(rc = linklist_build(ldap_handle, base, filter, NULL, 
5907                            &group_base, &group_count, LDAP_SCOPE_SUBTREE)) != 0)
5908     {
5909       if (group_count != 0)
5910         {
5911           UseSFU30 = 1;
5912         }
5913     }
5914   linklist_free(group_base);
5915   group_count = 0;
5916   group_base = NULL;
5917
5918   if ((fptr = fopen(WINADCFG, "w+")) != NULL)
5919     {
5920       fprintf(fptr, "%s %s\n", DOMAIN, ldap_domain);
5921       if (strlen(PrincipalName) != 0)
5922           fprintf(fptr, "%s %s\n", PRINCIPALNAME, PrincipalName);
5923       if (UseSFU30)
5924           fprintf(fptr, "%s %s\n", MSSFU, SFUTYPE);
5925       for (i = 0; i < MAX_SERVER_NAMES; i++)
5926         {
5927           if (ServerList[i] != NULL)
5928             {
5929               fprintf(fptr, "%s %s\n", SERVER, ServerList[i]);
5930             }
5931         }
5932       fclose(fptr);
5933     }
5934   ldap_unbind_s(ldap_handle);
5935
5936   for (i = 0; i < MAX_SERVER_NAMES; i++)
5937     {
5938       if (ServerList[i] != NULL)
5939         {
5940           if (ServerList[i][strlen(ServerList[i]) - 1] == '\n')
5941               ServerList[i][strlen(ServerList[i]) - 1] = '\0';
5942           strcat(ServerList[i], ".");
5943           strcat(ServerList[i], ldap_domain);
5944           for (k = 0; k < (int)strlen(ServerList[i]); k++)
5945               ServerList[i][k] = toupper(ServerList[i][k]);
5946         }
5947     }
5948
5949   return(0);
5950 }
5951
5952 int attribute_update(LDAP *ldap_handle, char *distinguished_name, 
5953                       char *attribute_value, char *attribute, char *user_name)
5954 {
5955   char      *mod_v[] = {NULL, NULL};
5956   LDAPMod   *DelMods[20];
5957   LDAPMod   *mods[20];
5958   int       n;
5959   int       i;
5960   int       rc;
5961
5962   if (strlen(attribute_value) == 0)
5963     {
5964       i = 0;
5965       DEL_ATTR(attribute, LDAP_MOD_DELETE);
5966       DelMods[i] = NULL;
5967       rc = ldap_modify_s(ldap_handle, distinguished_name, DelMods);
5968       free(DelMods[0]);
5969     }
5970     else
5971     {
5972       n = 0;
5973       mod_v[0] = attribute_value;
5974       ADD_ATTR(attribute, mod_v, LDAP_MOD_REPLACE);
5975       mods[n] = NULL;
5976       if ((rc = ldap_modify_s(ldap_handle, distinguished_name, mods)) != LDAP_SUCCESS)
5977         {
5978           free(mods[0]);
5979           n = 0;
5980           mod_v[0] = attribute_value;
5981           ADD_ATTR(attribute, mod_v, LDAP_MOD_ADD);
5982           mods[n] = NULL;
5983           if ((rc = ldap_modify_s(ldap_handle, distinguished_name, mods)) != LDAP_SUCCESS)
5984             {
5985               com_err(whoami, 0, "Unable to change the %s attribute for %s in the AD : %s",
5986                       attribute, user_name, ldap_err2string(rc));
5987             }
5988         }
5989       free(mods[0]);
5990     }
5991   return(rc);
5992 }
5993
5994 int tickets_get_k5()
5995 {
5996     char temp[128];
5997     char KinitPath[128];
5998     int  retval;
5999     int  i;
6000     static char EnvVar[128];
6001     static char EnvVar1[128];
6002
6003     strcpy(EnvVar, KRB5CCNAME);
6004     retval = putenv(EnvVar);
6005     strcpy(EnvVar1, KRBTKFILE);
6006     retval = putenv(EnvVar1);
6007
6008     for (i = 0; i < (int)strlen(PrincipalName); i++)
6009         PrincipalName[i] = tolower(PrincipalName[i]);
6010     if (strlen(PrincipalName) == 0)
6011     {
6012         strcpy(PrincipalName, PRODUCTION_PRINCIPAL);
6013         if (strcasecmp(ldap_domain, PRIMARY_DOMAIN))
6014             strcpy(PrincipalName, TEST_PRINCIPAL);
6015     }
6016
6017     memset(KinitPath, '\0',sizeof(KinitPath));
6018 #ifndef _WIN32
6019     strcpy(KinitPath, "/usr/athena/bin/");
6020 #endif
6021     sprintf(temp, "%skinit -k -t %s %s", KinitPath, KEYTABFILE, PrincipalName);
6022     retval = system(temp);
6023     if (retval)
6024         return(-1);
6025     return(0);
6026 }
6027
6028 int get_tickets()
6029 {
6030
6031     if (tickets_get_k5())
6032     {
6033         sleep(1);
6034         if (tickets_get_k5())
6035         {
6036             critical_alert("AD incremental", "%s",
6037                            "winad.incr incremental failed (unable to get kerberos tickets)");
6038             exit(1);
6039         }
6040     }
6041     return(0);
6042 }
6043
6044 int destroy_cache(void)
6045 {
6046   krb5_context          context;
6047   krb5_ccache                   cache;
6048   krb5_error_code       rc;
6049
6050   context = NULL;
6051   cache = NULL;
6052   if (!krb5_init_context(&context))
6053     {
6054       if (!krb5_cc_default(context, &cache))
6055         rc = krb5_cc_destroy(context, cache);
6056     }
6057   if (context != NULL)
6058     krb5_free_context(context);
6059   dest_tkt();
6060
6061   return(rc);
6062 }
6063
6064
6065 void StringTrim(char *StringToTrim)
6066 {
6067     char    *cPtr;
6068     char    temp[256];
6069     int     i;
6070
6071     if (strlen(StringToTrim) == 0)
6072         return;
6073
6074     cPtr = StringToTrim;
6075     while (isspace(*cPtr))
6076     {
6077         ++cPtr;
6078     }
6079     strcpy(temp, cPtr);
6080     if (strlen(temp) == 0)
6081     {
6082         strcpy(StringToTrim, temp);
6083         return;
6084     }
6085     while (1)
6086     {
6087         i = strlen(temp);
6088         if (i == 0)
6089             break;
6090         if (!isspace(temp[i-1]))
6091             break;
6092         temp[i-1] = '\0';
6093     }
6094
6095     strcpy(StringToTrim, temp);
6096     return;
6097 }
6098
6099 void ReadConfigFile()
6100 {
6101     int     Count;
6102     int     i;
6103     int     k;
6104     char    temp[256];
6105     char    temp1[256];
6106     FILE    *fptr;
6107
6108     Count = 0;
6109
6110     if ((fptr = fopen(WINADCFG, "r")) != NULL)
6111     {
6112         while (fgets(temp, sizeof(temp), fptr) != 0)
6113         {
6114             for (i = 0; i < (int)strlen(temp); i++)
6115                 temp[i] = toupper(temp[i]);
6116             if (temp[strlen(temp) - 1] == '\n')
6117                 temp[strlen(temp) - 1] = '\0';
6118             StringTrim(temp);
6119             if (strlen(temp) == 0)
6120                 continue;
6121             if (!strncmp(temp, DOMAIN, strlen(DOMAIN)))
6122             {
6123                 if (strlen(temp) > (strlen(DOMAIN)))
6124                 {
6125                     strcpy(ldap_domain, &temp[strlen(DOMAIN)]);
6126                     StringTrim(ldap_domain);
6127                 }
6128             }
6129             else if (!strncmp(temp, PRINCIPALNAME, strlen(PRINCIPALNAME)))
6130             {
6131                 if (strlen(temp) > (strlen(PRINCIPALNAME)))
6132                 {
6133                     strcpy(PrincipalName, &temp[strlen(PRINCIPALNAME)]);
6134                     StringTrim(PrincipalName);
6135                 }
6136             }
6137             else if (!strncmp(temp, SERVER, strlen(SERVER)))
6138             {
6139                 if (strlen(temp) > (strlen(SERVER)))
6140                 {
6141                     ServerList[Count] = calloc(1, 256);
6142                     strcpy(ServerList[Count], &temp[strlen(SERVER)]);
6143                     StringTrim(ServerList[Count]);
6144                     ++Count;
6145                 }
6146             }
6147             else if (!strncmp(temp, MSSFU, strlen(MSSFU)))
6148             {
6149                 if (strlen(temp) > (strlen(MSSFU)))
6150                 {
6151                     strcpy(temp1, &temp[strlen(MSSFU)]);
6152                     StringTrim(temp1);
6153                     if (!strcmp(temp1, SFUTYPE))
6154                         UseSFU30 = 1;
6155                 }
6156             }
6157             else if (!strcasecmp(temp, "NOCHANGE"))
6158             {
6159                 NoChangeConfigFile = 1;
6160             }
6161             else
6162             {
6163                 if (strlen(ldap_domain) != 0)
6164                 {
6165                     memset(ldap_domain, '\0', sizeof(ldap_domain));
6166                     break;
6167                 }
6168                 if (strlen(temp) != 0)
6169                     strcpy(ldap_domain, temp);
6170             }
6171         }
6172         fclose(fptr);
6173     }
6174
6175     if (strlen(ldap_domain) == 0)
6176     {
6177         critical_alert("incremental", "%s",
6178                        "winad.incr cannot run due to a configuration error in winad.cfg");
6179         exit(1);
6180     }
6181     if (Count == 0)
6182         return;
6183     for (i = 0; i < Count; i++)
6184     {
6185         if (ServerList[i] != 0)
6186         {
6187             strcat(ServerList[i], ".");
6188             strcat(ServerList[i], ldap_domain);
6189             for (k = 0; k < (int)strlen(ServerList[i]); k++)
6190                 ServerList[i][k] = toupper(ServerList[i][k]);
6191         }
6192     }
6193
6194 }
This page took 0.510974 seconds and 5 git commands to generate.