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