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