]> andersk Git - moira.git/blob - incremental/ldap/winad.c
Don't mess with sms/smstest.
[moira.git] / incremental / ldap / winad.c
1 /* $Header$
2 /* ldap.incr arguments example
3  *
4  * arguments when moira creates the account - ignored by ldap.incr since the 
5  * account is unusable. users 0 11 #45198 45198 /bin/cmd cmd Last First Middle
6  * 0 950000001 2000 121049
7  *
8  * login, unix_uid, shell, winconsoleshell, last, 
9  * first, middle, status, mitid, type, moiraid
10  *
11  * arguments for creating or updating a user account 
12  * users 11 11 username 45206 /bin/cmd cmd Last First Middle 2 950000001 STAFF
13  * 121058  PathToHomeDir PathToProfileDir username 45206 /bin/cmd cmd Last
14  * First Middle 1 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
15  * users 11 11 #45206 45206 /bin/cmd cmd Last First Middle 0 950000001 STAFF
16  * 121058  PathToHomeDir PathToProfileDir newuser 45206 /bin/cmd cmd Last
17  * First Middle 2 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
18  *
19  * login, unix_uid, shell, winconsoleshell, last, first, middle, status, 
20  * mitid, type, moiraid
21  *
22  * arguments for deactivating/deleting a user account
23  * users 11 11 username 45206 /bin/cmd cmd Last First Middle 1 950000001 STAFF
24  * 121058  PathToHomeDir PathToProfileDir username 45206 /bin/cmd cmd Last
25  * First Middle 3 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
26  * users 11 11 username 45206 /bin/cmd cmd Last First Middle 2 950000001 STAFF
27  * 121058  PathToHomeDir PathToProfileDir username 45206 /bin/cmd cmd Last
28  * First Middle 3 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
29  * 
30  * login, unix_uid, shell, winconsoleshell, last, first, middle, status,
31  * mitid, type, moiraid
32  *
33  * arguments for reactivating a user account
34  * users 11 11 username 45206 /bin/cmd cmd Last First Middle 3 950000001 STAFF
35  * 121058 username 45206 /bin/cmd cmd Last First Middle 1 950000001 STAFF
36  * 121058
37  * users 11 11 username 45206 /bin/cmd cmd Last First Middle 3 950000001 STAFF
38  * 121058 username 45206 /bin/cmd cmd Last First Middle 2 950000001 STAFF 12105
39  *
40  * login, unix_uid, shell, winconsoleshell, last, first, middle, status, 
41  * mitid, type, moiraid
42  *
43  * arguments for changing user name
44  * users 11 11 oldusername 45206 /bin/cmd cmd Last First Middle 1 950000001 
45  * STAFF 121058 PathToHomeDir PathToProfileDir newusername 45206 /bin/cmd cmd 
46  * Last First Middle 1 950000001 STAFF 121058 PathToHomeDir PathToProfileDir
47  *
48  * login, unix_uid, shell, winconsoleshell, last, first, middle, status, 
49  * mitid, type, moiraid
50  *
51  * arguments for expunging a user
52  * users 11 0 username 45198 /bin/cmd cmd Last First Middle 0 950000001 2000
53  * 121049
54  *
55  * login, unix_uid, shell, winconsoleshell, last, first, middle, status, 
56  * mitid, type, moiraid
57  *
58  * arguments for creating a "special" group/list
59  * list 0 11 listname 1 1 0 0 0 -1 NONE 0 description 92616
60  *
61  * listname, active, publicflg, hidden, maillist, grouplist, gid, acl_type, 
62  * acl_id, description, moiraid
63  * 
64  * arguments for creating a "mail" group/list
65  * list 0 11 listname 1 1 0 1 0 -1 NONE 0 description 92616
66  *
67  * listname, active, publicflg, hidden, maillist, grouplist, gid, acl_type, 
68  * acl_id, description, moiraid
69  *
70  * arguments for creating a "group" group/list
71  * list 0 11 listname 1 1 0 0 1 -1 NONE 0 description 92616
72  * 
73  * listname, active, publicflg, hidden, maillist, grouplist, gid, acl_type, 
74  * acl_id, description, moiraid
75  *
76  * arguments for creating a "group/mail" group/list
77  * list 0 11 listname 1 1 0 1 1 -1 NONE 0 description 92616
78  *
79  * listname, active, publicflg, hidden, maillist, grouplist, gid, acl_type, 
80  * acl_id, description, moiraid
81  *
82  * arguments to add a USER member to group/list
83  * imembers 0 12 listname USER userName 1 1 0 0 0 -1 1 92616 121047
84  *
85  * list_name, user_type, name, active, publicflg, hidden, maillist, grouplist,
86  * gid, userStatus, moiraListId, moiraUserId
87  *
88  * arguments to add a STRING or KERBEROS member to group/list
89  * imembers 0 10 listname STRING stringName 1 1 0 0 0 -1 92616
90  * imembers 0 10 listlistnameName KERBEROS kerberosName 1 1 0 0 0 -1 92616
91  *
92  * list_name, user_type, name, active, publicflg, hidden, maillist, grouplist,
93  * gid, moiraListId
94  *
95  * NOTE: group members of type LIST are ignored.
96  *
97  * arguments to remove a USER member to group/list
98  * imembers 12 0 listname USER userName 1 1 0 0 0 -1 1 92616 121047
99  * 
100  * list_name, user_type, name, active, publicflg, hidden, maillist, grouplist,
101  * gid, userStatus, moiraListId, moiraUserId
102  *
103  * arguments to remove a STRING or KERBEROS member to group/list
104  * imembers 10 0 listname STRING stringName 1 1 0 0 0 -1 92616
105  * imembers 10 0 listname KERBEROS kerberosName 1 1 0 0 0 -1 92616
106  *
107  * list_name, user_type, name, active, publicflg, hidden, maillist, grouplist,
108  * gid, moiraListId
109  *
110  * NOTE: group members of type LIST are ignored.
111  *
112  * arguments for renaming a group/list
113  * list 11 11 oldlistname 1 1 0 0 0 -1 NONE 0 description 92616 newlistname 1
114  * 1 0 0 0 -1 description 0 92616
115  * 
116  * name, active, publicflg, hidden, maillist, grouplist, gid, acl_type, 
117  * acl_id, description, moiraListId
118  *
119  * arguments for deleting a group/list
120  * list 11 0 listname 1 1 0 0 0 -1 NONE 0 description 92616
121  *
122  * name, active, publicflg, hidden, maillist, grouplist, gid, acl_type, 
123  * acl_id, description, moiraListId
124  *
125  * arguments for adding a file system
126  * filesys 0 12 username AFS ATHENA.MIT.EDU 
127  * /afs/athena.mit.edu/user/n/e/username /mit/username w descripton username
128  * wheel 1 HOMEDIR 101727
129  *
130  * arguments for deleting a file system
131  * filesys 12 0 username AFS ATHENA.MIT.EDU 
132  * /afs/athena.mit.edu/user/n/e/username /mit/username w descripton username
133  * wheel 1 HOMEDIR 101727
134  *
135  * arguments when moira creates a container (OU).
136  * containers 0 8 machines/test/bottom description location contact USER
137  * 105316 2222 [none]
138  *
139  * arguments when moira deletes a container (OU).
140  * containers 8 0 machines/test/bottom description location contact USER 
141  * 105316 2222 groupname
142  *
143  * arguments when moira modifies a container information (OU).
144  * containers 8 8 machines/test/bottom description location contact USER 
145  * 105316 2222 groupname machines/test/bottom description1 location contact 
146  * USER 105316 2222 groupname
147  *
148  * arguments when moira adds a machine from an OU
149  * table name, beforec, afterc, machine_name, container_name, mach_id, cnt_id
150  * mcntmap 0 5 DAVIDT.MIT.EDU dttest/dttest1 76767 46 groupname
151  *
152  * arguments when moira removes a machine from an OU
153  * table name, beforec, afterc, machine_name, container_name, mach_id, cnt_id
154  * mcntmap 0 5 DAVIDT.MIT.EDU dttest/dttest1 76767 46 groupname
155  *
156 */
157
158 #include <mit-copyright.h>
159
160 #ifdef _WIN32
161 #include <winsock2.h>
162 #include <windows.h>
163 #include <stdlib.h>
164 #include <malloc.h>
165 #include <lmaccess.h>
166 #endif
167
168 #include <hesiod.h>
169 #include <string.h>
170 #include <ldap.h>
171 #include <stdio.h>
172 #include <moira.h>
173 #include <moira_site.h>
174 #include <mrclient.h>
175 #include <krb5.h>
176 #include <gsssasl.h>
177 #include <gssldap.h> 
178 #include "kpasswd.h"
179
180 #ifdef _WIN32
181 #ifndef ECONNABORTED
182 #define ECONNABORTED WSAECONNABORTED
183 #endif
184 #ifndef ECONNREFUSED
185 #define ECONNREFUSED WSAECONNREFUSED
186 #endif
187 #ifndef EHOSTUNREACH
188 #define EHOSTUNREACH WSAEHOSTUNREACH
189 #endif
190 #define krb5_xfree free
191 #define F_OK 0
192 #define sleep(A) Sleep(A * 1000);
193 #endif /* _WIN32 */
194
195 #ifndef _WIN32
196 #include <sys/types.h>
197 #include <netinet/in.h>
198 #include <arpa/nameser.h>
199 #include <resolv.h>
200 #include <sys/utsname.h>
201 #include <unistd.h>
202
203 #define CFG_PATH "/moira/ldap/"
204 #define WINADCFG "ldap.cfg"
205 #define strnicmp(A,B,C) strncasecmp(A,B,C)
206 #define UCHAR unsigned char
207
208 #define UF_SCRIPT               0x0001
209 #define UF_ACCOUNTDISABLE       0x0002
210 #define UF_HOMEDIR_REQUIRED     0x0008
211 #define UF_LOCKOUT              0x0010
212 #define UF_PASSWD_NOTREQD       0x0020
213 #define UF_PASSWD_CANT_CHANGE   0x0040
214 #define UF_DONT_EXPIRE_PASSWD   0x10000
215
216 #define UF_TEMP_DUPLICATE_ACCOUNT       0x0100
217 #define UF_NORMAL_ACCOUNT               0x0200
218 #define UF_INTERDOMAIN_TRUST_ACCOUNT    0x0800
219 #define UF_WORKSTATION_TRUST_ACCOUNT    0x1000
220 #define UF_SERVER_TRUST_ACCOUNT         0x2000
221
222 #define OWNER_SECURITY_INFORMATION       (0x00000001L)
223 #define GROUP_SECURITY_INFORMATION       (0x00000002L)
224 #define DACL_SECURITY_INFORMATION        (0x00000004L)
225 #define SACL_SECURITY_INFORMATION        (0x00000008L)
226
227 #ifndef BYTE
228 #define BYTE unsigned char
229 #endif
230 typedef unsigned int DWORD;
231 typedef unsigned long ULONG;
232
233 typedef struct _GUID
234 {
235   unsigned long Data1;
236   unsigned short Data2;
237   unsigned short Data3;
238   unsigned char Data4[8];
239 } GUID;
240
241 typedef struct _SID_IDENTIFIER_AUTHORITY { 
242   BYTE Value[6]; 
243 } SID_IDENTIFIER_AUTHORITY, *PSID_IDENTIFIER_AUTHORITY; 
244
245 typedef struct _SID {
246   BYTE  Revision;
247   BYTE  SubAuthorityCount;
248   SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
249   DWORD SubAuthority[512];
250 } SID;
251 #endif/*!WIN32*/
252
253 #ifndef WINADCFG
254 #define WINADCFG "ldap.cfg"
255 #endif
256
257 #ifndef CFG_PATH
258 #define CFG_PATH ""
259 #endif 
260
261 #define AFS "/afs/"
262 #define WINAFS "\\\\afs\\all\\"
263
264 #define ADS_GROUP_TYPE_GLOBAL_GROUP         0x00000002
265 #define ADS_GROUP_TYPE_DOMAIN_LOCAL_GROUP   0x00000004
266 #define ADS_GROUP_TYPE_LOCAL_GROUP          0x00000004
267 #define ADS_GROUP_TYPE_UNIVERSAL_GROUP      0x00000008
268 #define ADS_GROUP_TYPE_SECURITY_ENABLED     0x80000000
269
270 #define QUERY_VERSION   -1
271 #define PRIMARY_REALM   "ATHENA.MIT.EDU"
272 #define PRIMARY_DOMAIN  "win.mit.edu"
273 #define PRODUCTION_PRINCIPAL "sms"
274 #define TEST_PRINCIPAL       "smstest"
275
276 #define SUBSTITUTE  1
277 #define REPLACE     2
278
279 #define USERS         0
280 #define GROUPS        1
281
282 #define MEMBER_ADD          1
283 #define MEMBER_REMOVE       2
284 #define MEMBER_CHANGE_NAME  3
285 #define MEMBER_ACTIVATE     4
286 #define MEMBER_DEACTIVATE   5
287 #define MEMBER_CREATE       6
288
289 #define MOIRA_ALL       0x0
290 #define MOIRA_USERS     0x1
291 #define MOIRA_KERBEROS  0x2
292 #define MOIRA_STRINGS   0x4
293 #define MOIRA_LISTS     0x8
294 #define MOIRA_MACHINE   0x16
295
296 #define CHECK_GROUPS    1
297 #define CLEANUP_GROUPS  2
298
299 #define AD_NO_GROUPS_FOUND        -1
300 #define AD_WRONG_GROUP_DN_FOUND   -2
301 #define AD_MULTIPLE_GROUPS_FOUND  -3
302 #define AD_INVALID_NAME           -4
303 #define AD_LDAP_FAILURE           -5
304 #define AD_INVALID_FILESYS        -6
305 #define AD_NO_ATTRIBUTE_FOUND     -7
306 #define AD_NO_OU_FOUND            -8
307 #define AD_NO_USER_FOUND          -9
308
309 /* container arguments */
310 #define CONTAINER_NAME       0
311 #define CONTAINER_DESC       1
312 #define CONTAINER_LOCATION   2
313 #define CONTAINER_CONTACT    3
314 #define CONTAINER_TYPE       4
315 #define CONTAINER_ID         5
316 #define CONTAINER_ROWID      6
317 #define CONTAINER_GROUP_NAME 7
318
319 /*mcntmap arguments*/
320 #define OU_MACHINE_NAME        0
321 #define OU_CONTAINER_NAME      1
322 #define OU_MACHINE_ID          2
323 #define OU_CONTAINER_ID        3
324 #define OU_CONTAINER_GROUP     4
325
326 typedef struct lk_entry {
327   int     op;
328   int     length;
329   int     ber_value;
330   char    *dn;
331   char    *attribute;
332   char    *value;
333   char    *member;
334   char    *type;
335   char    *list;
336   struct  lk_entry *next;
337 } LK_ENTRY;
338
339 #define STOP_FILE "/moira/ldap/noldap"
340 #define file_exists(file) (access((file), F_OK) == 0)
341
342 #define N_SD_BER_BYTES   5
343 #define LDAP_BERVAL struct berval
344 #define MAX_SERVER_NAMES 32
345
346 #define HIDDEN_GROUP                "HiddenGroup.g"
347 #define HIDDEN_GROUP_WITH_ADMIN     "HiddenGroupWithAdmin.g"
348 #define NOT_HIDDEN_GROUP            "NotHiddenGroup.g"
349 #define NOT_HIDDEN_GROUP_WITH_ADMIN "NotHiddenGroupWithAdmin.g"
350
351 #define ADDRESS_LIST_PREFIX "CN=MIT Directory,CN=All Address Lists,\
352 CN=Address Lists Container,CN=Massachusetts Institute of Technology,\
353 CN=Microsoft Exchange,CN=Services,CN=Configuration,"
354
355 #define ADD_ATTR(t, v, o)               \
356   mods[n] = malloc(sizeof(LDAPMod));    \
357   mods[n]->mod_op = o;                  \
358   mods[n]->mod_type = t;                \
359   mods[n++]->mod_values = v
360
361 #define DEL_ATTR(t, o)                  \
362   DelMods[i] = malloc(sizeof(LDAPMod)); \
363   DelMods[i]->mod_op = o;               \
364   DelMods[i]->mod_type = t;             \
365   DelMods[i++]->mod_values = NULL
366
367 #define DOMAIN_SUFFIX   "MIT.EDU"
368 #define DOMAIN  "DOMAIN:"
369 #define PRINCIPALNAME  "PRINCIPAL:"
370 #define SERVER  "SERVER:"
371 #define MSSFU   "SFU:"
372 #define SFUTYPE "30"
373 #define GROUP_SUFFIX "GROUP_SUFFIX:"
374 #define GROUP_TYPE   "GROUP_TYPE:"
375 #define SET_GROUP_ACE    "SET_GROUP_ACE:"
376 #define SET_PASSWORD "SET_PASSWORD:"
377 #define EXCHANGE "EXCHANGE:"
378 #define REALM "REALM:"
379 #define ACTIVE_DIRECTORY "ACTIVE_DIRECTORY:"
380 #define PORT "PORT:"
381 #define PROCESS_MACHINE_CONTAINER "PROCESS_MACHINE_CONTAINER:"
382 #define GROUP_POPULATE_MEMBERS "GROUP_POPULATE_MEMBERS:"
383 #define MAX_DOMAINS 10
384 char DomainNames[MAX_DOMAINS][128];
385
386 LK_ENTRY *member_base = NULL;
387
388 char   PrincipalName[128];
389 static char tbl_buf[1024];
390 char  kerberos_ou[] = "OU=kerberos,OU=moira";
391 char  contact_ou[] = "OU=strings,OU=moira";
392 char  user_ou[] = "OU=users,OU=moira";
393 char  group_ou_distribution[1024];
394 char  group_ou_root[1024];
395 char  group_ou_security[1024];
396 char  group_ou_neither[1024];
397 char  group_ou_both[1024]; 
398 char  orphans_machines_ou[] = "OU=Machines,OU=Orphans";
399 char  orphans_other_ou[] = "OU=Other,OU=Orphans";
400 char  security_template_ou[] = "OU=security_templates";
401 char *whoami;
402 char ldap_domain[256];
403 char ldap_realm[256];
404 char ldap_port[256];
405 char *ServerList[MAX_SERVER_NAMES];
406 char default_server[256];
407 static char tbl_buf[1024];
408 char group_suffix[256];
409 char exchange_acl[256];
410 int  mr_connections = 0;
411 int  callback_rc;
412 int  UseSFU30 = 0;
413 int  UseGroupSuffix = 1;
414 int  UseGroupUniversal = 0;
415 int  SetGroupAce = 1;
416 int  SetPassword = 1;
417 int  Exchange = 0;
418 int  ProcessMachineContainer = 1;
419 int  ActiveDirectory = 1;
420 int  UpdateDomainList;
421 int  fsgCount;
422 int  GroupPopulateDelete = 0;
423
424 extern int set_password(char *user, char *password, char *domain);
425
426 int ad_get_group(LDAP *ldap_handle, char *dn_path, char *group_name, 
427                  char *group_membership, char *MoiraId, char *attribute,
428                  LK_ENTRY **linklist_base, int *linklist_count,
429                  char *rFilter);
430 void AfsToWinAfs(char* path, char* winPath);
431 int ad_connect(LDAP **ldap_handle, char *ldap_domain, char *dn_path, 
432                char *Win2kPassword, char *Win2kUser, char *default_server,
433                int connect_to_kdc, char **ServerList, char *ldap_realm,
434                char *ldap_port);
435 void ad_kdc_disconnect();
436 int ad_server_connect(char *connectedServer, char *domain);
437 int attribute_update(LDAP *ldap_handle, char *distinguished_name, 
438                      char *attribute_value, char *attribute, char *user_name);
439 int BEREncodeSecurityBits(ULONG uBits, char *pBuffer);
440 int checkADname(LDAP *ldap_handle, char *dn_path, char *Name);
441 int check_winad(void);
442 int check_user(LDAP *ldap_handle, char *dn_path, char *UserName, 
443                char *MoiraId);
444 /* containers */
445 int container_adupdate(LDAP *ldap_handle, char *dn_path, char *dName, 
446                        char *distinguishedName, int count, char **av);
447 void container_check(LDAP *ldap_handle, char *dn_path, char *name);
448 int container_create(LDAP *ldap_handle, char *dn_path, int count, char **av);
449 int container_delete(LDAP *ldap_handle, char *dn_path, int count, char **av);
450 int container_get_distinguishedName(LDAP *ldap_handle, char *dn_path, 
451                                     char *distinguishedName, int count, 
452                                     char **av);
453 void container_get_dn(char *src, char *dest);
454 void container_get_name(char *src, char *dest);
455 int container_move_objects(LDAP *ldap_handle, char *dn_path, char *dName);
456 int container_rename(LDAP *ldap_handle, char *dn_path, int beforec, 
457                      char **before, int afterc, char **after);
458 int container_update(LDAP *ldap_handle, char *dn_path, int beforec, 
459                      char **before, int afterc, char **after);
460
461 int GetAceInfo(int ac, char **av, void *ptr);
462 int get_group_membership(char *group_membership, char *group_ou, 
463                          int *security_flag, char **av);
464 int get_machine_ou(LDAP *ldap_handle, char *dn_path, char *member, 
465                    char *machine_ou, char *pPtr);
466 int Moira_container_group_create(char **after);
467 int Moira_container_group_delete(char **before);
468 int Moira_groupname_create(char *GroupName, char *ContainerName,
469                            char *ContainerRowID);
470 int Moira_container_group_update(char **before, char **after);
471 int Moira_process_machine_container_group(char *MachineName, char* groupName,
472                                           int DeleteMachine);
473 int Moira_addGroupToParent(char *origContainerName, char *GroupName);
474 int Moira_getContainerGroup(int ac, char **av, void *ptr);
475 int Moira_getGroupName(char *origContainerName, char *GroupName,
476                        int ParentFlag);
477 int Moira_setContainerGroup(char *ContainerName, char *GroupName);
478 int ProcessAce(LDAP *ldap_handle, char *dn_path, char *group_name, char *Type,
479                int UpdateGroup, int *ProcessGroup, char *maillist);
480 int process_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
481                   char *group_name, char *group_ou, char *group_membership, 
482                   int group_security_flag, int type, char *maillist);
483 int process_lists(int ac, char **av, void *ptr);
484 int ProcessGroupSecurity(LDAP *ldap_handle, char *dn_path, 
485                          char *TargetGroupName, int HiddenGroup, 
486                          char *AceType, char *AceName);
487 int ProcessMachineName(int ac, char **av, void *ptr);
488 int ReadConfigFile(char *DomainName);
489 int ReadDomainList();
490 void StringTrim(char *StringToTrim);
491 char *escape_string(char *s);
492 int save_query_info(int argc, char **argv, void *hint);
493 int save_fsgroup_info(int argc, char **argv, void *hint);
494 int user_create(int ac, char **av, void *ptr);
495 int user_change_status(LDAP *ldap_handle, char *dn_path, 
496                        char *user_name, char *MoiraId, int operation);
497 int user_delete(LDAP *ldap_handle, char *dn_path, 
498                 char *u_name, char *MoiraId);
499 int user_rename(LDAP *ldap_handle, char *dn_path, char *before_user_name, 
500                 char *user_name);
501 int user_update(LDAP *ldap_handle, char *dn_path, char *user_name,
502                 char *uid, char *MitId, char *MoiraId, int State,
503                 char *WinHomeDir, char *WinProfileDir, char *first,
504                 char *middle, char *last, char *shell, char *class);
505 void change_to_lower_case(char *ptr);
506 int contact_create(LDAP *ld, char *bind_path, char *user, char *group_ou);
507 int contact_remove_email(LDAP *ld, char *bind_path,
508                          LK_ENTRY **linklist_entry, int linklist_current);
509 int group_create(int ac, char **av, void *ptr);
510 int group_delete(LDAP *ldap_handle, char *dn_path, 
511                  char *group_name, char *group_membership, char *MoiraId);
512 int group_rename(LDAP *ldap_handle, char *dn_path, 
513                  char *before_group_name, char *before_group_membership, 
514                  char *before_group_ou, int before_security_flag, 
515                  char *before_desc, char *after_group_name, 
516                  char *after_group_membership, char *after_group_ou, 
517                  int after_security_flag, char *after_desc,
518                  char *MoiraId, char *filter, char *maillist);
519 int machine_check(LDAP *ldap_handle, char *dn_path, char *machine_name);
520 int machine_GetMoiraContainer(int ac, char **av, void *ptr);
521 int machine_get_moira_container(LDAP *ldap_handle, char *dn_path, 
522                                 char *machine_name, char *container_name);
523 int machine_move_to_ou(LDAP *ldap_handle, char *dn_path, 
524                        char *MoiraMachineName, char *DestinationOu);
525 int make_new_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
526                    char *group_name, char *group_ou, char *group_membership, 
527                    int group_security_flag, int updateGroup, char *maillist);
528 int member_list_build(int ac, char **av, void *ptr);
529 int member_add(LDAP *ldap_handle, char *dn_path, char *group_name, 
530                char *group_ou, char *group_membership, 
531                char *user_name, char *pUserOu, char *MoiraId);
532 int member_remove(LDAP *ldap_handle, char *dn_path, char *group_name, 
533                   char *group_ou, char *group_membership, char *user_name,
534                   char *pUserOu, char *MoiraId);
535 int populate_group(LDAP *ldap_handle, char *dn_path, char *group_name, 
536                    char *group_ou, char *group_membership, 
537                    int group_security_flag, char *MoiraId);
538 int SetHomeDirectory(LDAP *ldap_handle, char *user_name, 
539                      char *DistinguishedName,
540                      char *WinHomeDir, char *WinProfileDir,
541                      char **homedir_v, char **winProfile_v,
542                      char **drives_v, LDAPMod **mods, 
543                      int OpType, int n);
544 int sid_update(LDAP *ldap_handle, char *dn_path);
545 void SwitchSFU(LDAPMod **mods, int *UseSFU30, int n);
546 int check_string(char *s);
547 int check_container_name(char* s);
548
549 int mr_connect_cl(char *server, char *client, int version, int auth);
550 void do_container(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
551                   char **before, int beforec, char **after, int afterc);
552 void do_filesys(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
553                 char **before, int beforec, char **after, int afterc);
554 void do_list(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
555              char **before, int beforec, char **after, int afterc);
556 void do_user(LDAP *ldap_handle, char *dn_path, char *ldap_hostname, 
557              char **before, int beforec, char **after, int afterc);
558 void do_member(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
559                char **before, int beforec, char **after, int afterc);
560 void do_mcntmap(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
561                 char **before, int beforec, char **after, int afterc);
562 int linklist_create_entry(char *attribute, char *value,
563                           LK_ENTRY **linklist_entry);
564 int linklist_build(LDAP *ldap_handle, char *dn_path, char *search_exp, 
565                    char **attr_array, LK_ENTRY **linklist_base, 
566                    int *linklist_count, unsigned long ScopeType);
567 void linklist_free(LK_ENTRY *linklist_base);
568
569 int retrieve_attributes(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
570                         char *distinguished_name, LK_ENTRY **linklist_current);
571 int retrieve_entries(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
572                      LK_ENTRY **linklist_base, int *linklist_count);
573 int retrieve_values(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
574                     char *Attribute, char *distinguished_name, 
575                     LK_ENTRY **linklist_current);
576
577 int construct_newvalues(LK_ENTRY *linklist_base, int modvalue_count, 
578                         char *oldValue, char *newValue,
579                         char ***modvalues, int type);
580 void free_values(char **modvalues);
581
582 int convert_domain_to_dn(char *domain, char **bind_path);
583 void get_distinguished_name(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
584                             char *distinguished_name);
585 int moira_disconnect(void);
586 int moira_connect(void);
587 void print_to_screen(const char *fmt, ...);
588 int GetMachineName(char *MachineName);
589 int tickets_get_k5();
590 int destroy_cache(void);
591 int dest_tkt(void);
592
593 int find_homeMDB(LDAP *ldap_handle, char *dn_path, char **homeMDB,
594                  char **homeServerName);
595
596 int main(int argc, char **argv)
597 {
598   unsigned long   rc;
599   int             beforec;
600   int             afterc;
601   int             i;
602   int             j;
603   int             k;
604   int             OldUseSFU30;
605   char            *table;
606   char            **before;
607   char            **after;
608   LDAP            *ldap_handle;
609   char            dn_path[256];
610   char            *orig_argv[64];
611   
612   whoami = ((whoami = (char *)strrchr(argv[0], '/')) ? whoami+1 : argv[0]);
613   
614   if (argc < 4)
615     {
616       com_err(whoami, 0, "Unable to process %s", "argc < 4");
617       exit(1);
618     }
619   
620   if (argc < (4 + atoi(argv[2]) + atoi(argv[3])))
621     {
622       com_err(whoami, 0, "Unable to process %s", 
623               "argc < (4 + beforec + afterc)");
624       exit(1);
625     }
626
627   if (!strcmp(argv[1], "filesys"))
628     exit(0);
629
630   for (i = 1; i < argc; i++)
631     {
632       strcat(tbl_buf, argv[i]);
633       strcat(tbl_buf, " ");
634     }
635
636   com_err(whoami, 0, "%s", tbl_buf);
637
638   if (check_winad())
639     {
640       com_err(whoami, 0, "%s failed", "check_winad()");
641       exit(1);
642     }
643
644   initialize_sms_error_table();
645   initialize_krb_error_table();
646
647   UpdateDomainList = 0;
648   memset(DomainNames, '\0', sizeof(DomainNames[0]) * MAX_DOMAINS);
649
650   if (ReadDomainList())
651     {
652       com_err(whoami, 0, "%s failed", "ReadDomainList()");
653       exit(1);
654     }
655
656   for (i = 0; i < argc; i++)
657      orig_argv[i] = NULL;
658
659   for (k = 0; k < MAX_DOMAINS; k++)
660     {
661       if (strlen(DomainNames[k]) == 0)
662         continue;
663       for (i = 0; i < argc; i++)
664         {
665           if (orig_argv[i] != NULL)
666             free(orig_argv[i]);
667           orig_argv[i] = strdup(argv[i]);
668         }
669
670       memset(PrincipalName, '\0', sizeof(PrincipalName));
671       memset(ldap_domain, '\0', sizeof(ldap_domain));
672       memset(ServerList, '\0', sizeof(ServerList[0]) * MAX_SERVER_NAMES);
673       memset(default_server, '\0', sizeof(default_server));
674       memset(dn_path, '\0', sizeof(dn_path));
675       memset(group_suffix, '\0', sizeof(group_suffix));
676       memset(exchange_acl, '\0', sizeof(exchange_acl));
677
678       UseSFU30 = 0;
679       UseGroupSuffix = 1;
680       UseGroupUniversal = 0;
681       SetGroupAce = 1;
682       SetPassword = 1;
683       Exchange = 0;
684       ProcessMachineContainer = 1;
685       ActiveDirectory = 1;
686
687       sprintf(group_suffix, "%s", "_group");
688       sprintf(exchange_acl, "%s", "exchange-acl");
689
690       beforec = atoi(orig_argv[2]);
691       afterc = atoi(orig_argv[3]);
692       table = orig_argv[1];
693       before = &orig_argv[4];
694       after = &orig_argv[4 + beforec];
695
696       if (afterc == 0)
697         after = NULL;
698
699       if (beforec == 0)
700         before = NULL;
701
702       if (ReadConfigFile(DomainNames[k]))
703         continue;
704
705       if(ActiveDirectory)
706         {
707           sprintf(group_ou_distribution, "OU=mail,OU=lists,OU=moira");
708           sprintf(group_ou_root, "OU=lists,OU=moira");
709           sprintf(group_ou_security, "OU=group,OU=lists,OU=moira");
710           sprintf(group_ou_neither, "OU=special,OU=lists,OU=moira");
711           sprintf(group_ou_both, "OU=mail,OU=group,OU=lists,OU=moira");
712         }
713       else
714         {
715           sprintf(group_ou_distribution, "OU=lists,OU=moira");
716           sprintf(group_ou_root, "OU=lists,OU=moira");
717           sprintf(group_ou_security, "OU=lists,OU=moira");
718           sprintf(group_ou_neither, "OU=lists,OU=moira");
719           sprintf(group_ou_both, "OU=lists,OU=moira");
720         }
721
722       OldUseSFU30 = UseSFU30;
723
724       for (i = 0; i < 5; i++)
725         {
726           ldap_handle = (LDAP *)NULL;
727           if (!(rc = ad_connect(&ldap_handle, ldap_domain, dn_path, "", "", 
728                                 default_server, SetPassword, ServerList, 
729                                 ldap_realm, ldap_port)))
730             {
731               com_err(whoami, 0, "connected to domain %s", DomainNames[k]);
732               break;
733             }
734         }
735
736       if ((rc) || (ldap_handle == NULL))
737         {
738           critical_alert("incremental",
739                          "ldap.incr cannot connect to any server in "
740                          "domain %s", DomainNames[k]);
741           continue;
742         }
743
744       for (i = 0; i < (int)strlen(table); i++)
745         table[i] = tolower(table[i]);
746
747       if (!strcmp(table, "users"))
748         do_user(ldap_handle, dn_path, ldap_domain, before, beforec, after,
749                 afterc);
750       else if (!strcmp(table, "list"))
751         do_list(ldap_handle, dn_path, ldap_domain, before, beforec, after,
752                 afterc);
753       else if (!strcmp(table, "imembers"))
754         do_member(ldap_handle, dn_path, ldap_domain, before, beforec, after,
755                   afterc);
756       else if (!strcmp(table, "containers"))
757         do_container(ldap_handle, dn_path, ldap_domain, before, beforec, after,
758                      afterc);
759       else if (!strcmp(table, "mcntmap"))
760         do_mcntmap(ldap_handle, dn_path, ldap_domain, before, beforec, after,
761                    afterc);
762
763       if(SetPassword) 
764         ad_kdc_disconnect();
765
766       for (i = 0; i < MAX_SERVER_NAMES; i++)
767         {
768           if (ServerList[i] != NULL)
769             {
770               free(ServerList[i]);
771               ServerList[i] = NULL;
772             }
773         }
774       
775       rc = ldap_unbind_s(ldap_handle);
776     }
777   
778   exit(0);
779 }
780
781 void do_mcntmap(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
782                 char **before, int beforec, char **after, int afterc)
783 {
784   char    MoiraContainerName[128];
785   char    ADContainerName[128];
786   char    MachineName[1024];
787   char    OriginalMachineName[1024];
788   long    rc;
789   int     DeleteMachine;
790   char    MoiraContainerGroup[64];
791
792   if (!ProcessMachineContainer)
793     {
794       com_err(whoami, 0, "Process machines and containers disabled, skipping");
795       return;
796     }
797   
798   DeleteMachine = 0;
799   memset(ADContainerName, '\0', sizeof(ADContainerName));
800   memset(MoiraContainerName, '\0', sizeof(MoiraContainerName));
801   
802   if ((beforec == 0) && (afterc == 0))
803     return;
804   
805   if (rc = moira_connect())
806     {
807       critical_alert("Ldap incremental",
808                      "Error contacting Moira server : %s",
809                      error_message(rc));
810       return;
811     }
812   
813   if ((beforec != 0) && (afterc == 0)) /*remove a machine*/
814     {
815       strcpy(OriginalMachineName, before[OU_MACHINE_NAME]);
816       strcpy(MachineName, before[OU_MACHINE_NAME]);
817       strcpy(MoiraContainerGroup, before[OU_CONTAINER_GROUP]);
818       DeleteMachine = 1;
819       com_err(whoami, 0, "removing machine %s from %s", 
820               OriginalMachineName, before[OU_CONTAINER_NAME]);
821     }
822   else if ((beforec == 0) && (afterc != 0)) /*add a machine*/
823     {
824       strcpy(OriginalMachineName, after[OU_MACHINE_NAME]);
825       strcpy(MachineName, after[OU_MACHINE_NAME]);
826       strcpy(MoiraContainerGroup, after[OU_CONTAINER_GROUP]);
827       com_err(whoami, 0, "adding machine %s to container %s", 
828               OriginalMachineName, after[OU_CONTAINER_NAME]);
829     }
830   else
831     {
832       moira_disconnect();
833       return;
834     }
835   
836   rc = GetMachineName(MachineName);
837
838   if (strlen(MachineName) == 0)
839     {
840       moira_disconnect();
841       com_err(whoami, 0, "Unable to find alais for machine %s in Moira", 
842               OriginalMachineName);
843       return;
844     }
845
846   Moira_process_machine_container_group(MachineName, MoiraContainerGroup,
847                                         DeleteMachine);
848
849   if (machine_check(ldap_handle, dn_path, MachineName))
850     {
851       com_err(whoami, 0, "Unable to find machine %s (alias %s) in directory.", 
852               OriginalMachineName, MachineName);
853       moira_disconnect();
854       return;
855     }
856
857   memset(MoiraContainerName, '\0', sizeof(MoiraContainerName));
858   machine_get_moira_container(ldap_handle, dn_path, MachineName, 
859                               MoiraContainerName);
860
861   if (strlen(MoiraContainerName) == 0)
862     {
863       com_err(whoami, 0, "Unable to fine machine %s (alias %s) container "
864               "in Moira - moving to orphans OU.",
865               OriginalMachineName, MachineName);
866       machine_move_to_ou(ldap_handle, dn_path, MachineName, 
867                          orphans_machines_ou);
868       moira_disconnect();
869       return;
870     }
871
872   container_get_dn(MoiraContainerName, ADContainerName);
873
874   if (MoiraContainerName[strlen(MoiraContainerName) - 1] != '/')
875     strcat(MoiraContainerName, "/");
876
877   container_check(ldap_handle, dn_path, MoiraContainerName);
878   machine_move_to_ou(ldap_handle, dn_path, MachineName, ADContainerName);
879   moira_disconnect();
880   return;
881 }
882
883 void do_container(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
884                   char **before, int beforec, char **after, int afterc)
885 {
886   long rc;
887
888   if (!ProcessMachineContainer)
889     {
890       com_err(whoami, 0, "Process machines and containers disabled, skipping");
891       return;
892     }
893
894   if ((beforec == 0) && (afterc == 0))
895     return;
896
897   if (rc = moira_connect())
898     {
899       critical_alert("Ldap incremental", "Error contacting Moira server : %s",
900                      error_message(rc));
901       return;
902     }
903
904   if ((beforec != 0) && (afterc == 0)) /*delete a new container*/
905     {
906       com_err(whoami, 0, "deleting container %s", before[CONTAINER_NAME]);
907       container_delete(ldap_handle, dn_path, beforec, before);
908       Moira_container_group_delete(before);
909       moira_disconnect();
910       return;
911     }
912
913   if ((beforec == 0) && (afterc != 0)) /*create a container*/
914     {
915       com_err(whoami, 0, "creating container %s", after[CONTAINER_NAME]);
916       container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
917       container_create(ldap_handle, dn_path, afterc, after);
918       Moira_container_group_create(after);
919       moira_disconnect();
920       return;
921     }
922
923   if (strcasecmp(before[CONTAINER_NAME], after[CONTAINER_NAME]))
924     {
925       com_err(whoami, 0, "renaming container %s to %s", 
926               before[CONTAINER_NAME], after[CONTAINER_NAME]);
927       container_rename(ldap_handle, dn_path, beforec, before, afterc, after);
928       Moira_container_group_update(before, after);
929       moira_disconnect();
930       return;
931     }
932
933   com_err(whoami, 0, "updating container %s information", 
934           after[CONTAINER_NAME]);
935   container_update(ldap_handle, dn_path, beforec, before, afterc, after);
936   Moira_container_group_update(before, after);
937   moira_disconnect();
938   return;
939 }
940
941 #define L_LIST_DESC 9
942 #define L_LIST_ID   10
943
944 void do_list(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
945              char **before, int beforec, char **after, int afterc)
946 {
947   int   updateGroup;
948   int   ProcessGroup;
949   long  rc;
950   char  group_membership[6];
951   char  list_id[32];
952   int   security_flag;
953   char  filter[128];
954   char  group_ou[256];
955   char  before_list_id[32];
956   char  before_group_membership[1];
957   int   before_security_flag;
958   char  before_group_ou[256];
959   LK_ENTRY *ptr = NULL;
960
961   if (beforec == 0 && afterc == 0)
962     return;
963
964   memset(list_id, '\0', sizeof(list_id));
965   memset(before_list_id, '\0', sizeof(before_list_id));
966   memset(before_group_ou, '\0', sizeof(before_group_ou));
967   memset(before_group_membership, '\0', sizeof(before_group_membership));
968   memset(group_ou, '\0', sizeof(group_ou));
969   memset(group_membership, '\0', sizeof(group_membership));
970   updateGroup = 0;
971
972   if (beforec > L_GID)
973     {
974       if (beforec < L_LIST_ID)
975         return;
976       if (beforec > L_LIST_DESC)
977         {
978           strcpy(before_list_id, before[L_LIST_ID]);
979         }
980       before_security_flag = 0;
981       get_group_membership(before_group_membership, before_group_ou, 
982                            &before_security_flag, before);
983     }
984
985   if (afterc > L_GID)
986     {
987       if (afterc < L_LIST_ID)
988         return;
989       if (afterc > L_LIST_DESC)
990         {
991           strcpy(list_id, after[L_LIST_ID]);
992         }
993       security_flag = 0;
994       get_group_membership(group_membership, group_ou, &security_flag, after);
995     }
996   
997   if ((beforec == 0) && (afterc == 0)) /*this case should never happen*/
998     return;
999
1000   updateGroup = 0;
1001   
1002   if (beforec)
1003     {
1004       updateGroup = 1;
1005
1006       if ((rc = process_group(ldap_handle, dn_path, before_list_id, 
1007                               before[L_NAME], before_group_ou, 
1008                               before_group_membership, 
1009                               before_security_flag, CHECK_GROUPS,
1010                               before[L_MAILLIST])))
1011         {
1012           if (rc == AD_NO_GROUPS_FOUND)
1013             updateGroup = 0;
1014           else
1015             {
1016               if ((rc == AD_WRONG_GROUP_DN_FOUND) || 
1017                   (rc == AD_MULTIPLE_GROUPS_FOUND))
1018                 {
1019                   rc = process_group(ldap_handle, dn_path, before_list_id, 
1020                                      before[L_NAME], before_group_ou, 
1021                                      before_group_membership, 
1022                                      before_security_flag, CLEANUP_GROUPS,
1023                                      before[L_MAILLIST]);
1024                 }
1025               if ((rc != AD_NO_GROUPS_FOUND) && (rc != 0))
1026                 {
1027                   com_err(whoami, 0, "Unable to process list %s",
1028                           before[L_NAME]);
1029                   return;
1030                 }
1031               if (rc == AD_NO_GROUPS_FOUND)
1032                 updateGroup = 0;
1033             }
1034         }
1035     }
1036
1037   if ((beforec != 0) && (afterc != 0))
1038     {
1039       if (((strcmp(after[L_NAME], before[L_NAME])) || 
1040            ((!strcmp(after[L_NAME], before[L_NAME])) && 
1041             (strcmp(before_group_ou, group_ou)))) &&
1042           (updateGroup == 1))
1043         {
1044           com_err(whoami, 0, "Changing list name from %s to %s",
1045                   before[L_NAME], after[L_NAME]);
1046
1047           if ((strlen(before_group_ou) == 0) || 
1048               (strlen(before_group_membership) == 0) ||
1049               (strlen(group_ou) == 0) || (strlen(group_membership) == 0))
1050             {
1051               com_err(whoami, 0, "%s", "Unable to find the group OU's");
1052               return;
1053             }
1054
1055           memset(filter, '\0', sizeof(filter));
1056
1057           if ((rc = group_rename(ldap_handle, dn_path, 
1058                                  before[L_NAME], before_group_membership, 
1059                                  before_group_ou, before_security_flag, 
1060                                  before[L_LIST_DESC], after[L_NAME], 
1061                                  group_membership, group_ou, security_flag, 
1062                                  after[L_LIST_DESC],
1063                                  list_id, filter, after[L_MAILLIST])))
1064             {
1065               if (rc != AD_NO_GROUPS_FOUND)
1066                 {
1067                   com_err(whoami, 0, 
1068                           "Unable to change list name from %s to %s",
1069                           before[L_NAME], after[L_NAME]);
1070                   return;
1071                 }
1072               updateGroup = 0;
1073             }
1074           beforec = 0;
1075         }
1076       else
1077         beforec = 0;
1078     }
1079   
1080   if (beforec)
1081     {
1082       if ((strlen(before_group_ou) == 0) || 
1083           (strlen(before_group_membership) == 0))
1084         {
1085           com_err(whoami, 0, 
1086                   "Unable to find the group OU for group %s", before[L_NAME]);
1087           return;
1088         }
1089
1090       com_err(whoami, 0, "Deleting group %s", before[L_NAME]);
1091       rc = group_delete(ldap_handle, dn_path, before[L_NAME], 
1092                         before_group_membership, before_list_id);
1093       return;
1094     }
1095
1096   if (afterc)
1097     {
1098       if (!updateGroup)
1099         {
1100           com_err(whoami, 0, "Creating group %s", after[L_NAME]);
1101
1102           if (rc = process_group(ldap_handle, dn_path, list_id, after[L_NAME], 
1103                                   group_ou, group_membership, 
1104                                   security_flag, CHECK_GROUPS,
1105                                  after[L_MAILLIST]))
1106             {
1107               if (rc != AD_NO_GROUPS_FOUND)
1108                 {
1109                   if ((rc == AD_WRONG_GROUP_DN_FOUND) || 
1110                       (rc == AD_MULTIPLE_GROUPS_FOUND))
1111                     {
1112                       rc = process_group(ldap_handle, dn_path, list_id, 
1113                                          after[L_NAME], 
1114                                          group_ou, group_membership, 
1115                                          security_flag, CLEANUP_GROUPS,
1116                                          after[L_MAILLIST]);
1117                     }
1118
1119                   if (rc)
1120                     {
1121                       com_err(whoami, 0, 
1122                               "Unable to create list %s", after[L_NAME]);
1123                       return;
1124                     }
1125                 }
1126             }
1127         }
1128       else
1129         com_err(whoami, 0, "Updating group %s information", after[L_NAME]);
1130
1131       if (rc = moira_connect())
1132         {
1133           critical_alert("Ldap incremental",
1134                          "Error contacting Moira server : %s",
1135                          error_message(rc));
1136           return;
1137         }
1138
1139       ProcessGroup = 0;
1140
1141       if (ProcessAce(ldap_handle, dn_path, after[L_NAME], "LIST", 0, 
1142                      &ProcessGroup, after[L_MAILLIST]))
1143         return;
1144
1145       if (ProcessGroup)
1146         {
1147           if (ProcessAce(ldap_handle, dn_path, after[L_NAME], "LIST", 1, 
1148                          &ProcessGroup, after[L_MAILLIST]))
1149             return;
1150         }
1151
1152       if (make_new_group(ldap_handle, dn_path, list_id, after[L_NAME], 
1153                          group_ou, group_membership, security_flag, 
1154                          updateGroup, after[L_MAILLIST]))
1155         {
1156           moira_disconnect();
1157           return;
1158         }
1159     
1160       if (atoi(after[L_ACTIVE]))
1161         {
1162           populate_group(ldap_handle, dn_path, after[L_NAME], group_ou, 
1163                          group_membership, security_flag, list_id);
1164         }
1165
1166       moira_disconnect();
1167     }
1168   return;
1169 }
1170
1171 #define LM_EXTRA_ACTIVE   (LM_END)
1172 #define LM_EXTRA_PUBLIC   (LM_END+1)
1173 #define LM_EXTRA_HIDDEN   (LM_END+2)
1174 #define LM_EXTRA_MAILLIST (LM_END+3)
1175 #define LM_EXTRA_GROUP    (LM_END+4)
1176 #define LM_EXTRA_GID      (LM_END+5)
1177 #define LMN_LIST_ID       (LM_END+6)
1178 #define LM_LIST_ID        (LM_END+7)
1179 #define LM_USER_ID        (LM_END+8)
1180 #define LM_EXTRA_END      (LM_END+9)
1181
1182 void do_member(LDAP *ldap_handle, char *dn_path, char *ldap_hostname,
1183                char **before, int beforec, char **after, int afterc)
1184 {
1185   LK_ENTRY *group_base;
1186   int group_count;
1187   char  filter[128];
1188   char *attr_array[3];
1189   char  group_name[128];
1190   char  user_name[128];
1191   char  user_type[128];
1192   char  moira_list_id[32];
1193   char  moira_user_id[32];
1194   char  group_membership[1];
1195   char  group_ou[256];
1196   char  machine_ou[256];
1197   char  member[256];
1198   char  *args[16];
1199   char  **ptr;
1200   char  *av[7];
1201   char  *call_args[7];
1202   char  *pUserOu;
1203   char  *s;
1204   char  NewMachineName[1024];
1205   int   security_flag;
1206   int   rc;
1207   int   ProcessGroup;
1208   char  *save_argv[U_END];
1209
1210   pUserOu = NULL;
1211   ptr = NULL;
1212   memset(moira_list_id, '\0', sizeof(moira_list_id));
1213   memset(moira_user_id, '\0', sizeof(moira_user_id));
1214
1215   if (afterc)
1216     {
1217       if (afterc < LM_EXTRA_GID)
1218         return;
1219
1220       if (!atoi(after[LM_EXTRA_ACTIVE]))
1221         {
1222           com_err(whoami, 0, 
1223                   "Unable to add %s to group %s : group not active", 
1224                   after[2], after[0]);
1225           return;
1226         }
1227
1228       ptr = after;
1229
1230       if (!strcasecmp(ptr[LM_TYPE], "LIST"))
1231         return;
1232
1233       strcpy(user_name, after[LM_MEMBER]);
1234       strcpy(group_name, after[LM_LIST]);
1235       strcpy(user_type, after[LM_TYPE]);
1236
1237       if (!strcasecmp(ptr[LM_TYPE], "MACHINE"))
1238         {
1239           if (afterc > LM_EXTRA_GROUP)
1240             {
1241               strcpy(moira_list_id, after[LMN_LIST_ID]);
1242               strcpy(moira_user_id, after[LM_LIST_ID]);
1243             }
1244         }
1245       else if (!strcasecmp(ptr[LM_TYPE], "USER"))
1246         {
1247           if (afterc > LMN_LIST_ID)
1248             {
1249               strcpy(moira_list_id, after[LM_LIST_ID]);
1250               strcpy(moira_user_id, after[LM_USER_ID]);
1251             }
1252         }
1253       else
1254         {
1255           if (afterc > LM_EXTRA_GID)
1256             strcpy(moira_list_id, after[LMN_LIST_ID]);
1257         }
1258     }
1259   else if (beforec)
1260     {
1261       if (beforec < LM_EXTRA_GID)
1262         return;
1263       if (!atoi(before[LM_EXTRA_ACTIVE]))
1264         {
1265           com_err(whoami, 0, 
1266                   "Unable to remove %s from group %s : group not active", 
1267                   before[2], before[0]);
1268           return;
1269         }
1270
1271       ptr = before;
1272
1273       if (!strcasecmp(ptr[LM_TYPE], "LIST"))
1274         return;
1275
1276       strcpy(user_name, before[LM_MEMBER]);
1277       strcpy(group_name, before[LM_LIST]);
1278       strcpy(user_type, before[LM_TYPE]);
1279
1280       if (!strcasecmp(ptr[LM_TYPE], "MACHINE"))
1281         {
1282           if (beforec > LM_EXTRA_GROUP)
1283             {
1284               strcpy(moira_list_id, before[LMN_LIST_ID]);
1285               strcpy(moira_user_id, before[LM_LIST_ID]);
1286             }
1287         }
1288       else if (!strcasecmp(ptr[LM_TYPE], "USER"))
1289         {
1290           if (beforec > LMN_LIST_ID)
1291             {
1292               strcpy(moira_list_id, before[LM_LIST_ID]);
1293               strcpy(moira_user_id, before[LM_USER_ID]);
1294             }
1295         }
1296       else
1297         {
1298           if (beforec > LM_EXTRA_GID)
1299             strcpy(moira_list_id, before[LMN_LIST_ID]);
1300         }
1301     }
1302
1303   if (ptr == NULL)
1304     {
1305       com_err(whoami, 0, 
1306               "Unable to process group : beforec = %d, afterc = %d", 
1307               beforec, afterc);
1308       return;
1309     }
1310
1311   args[L_NAME] = ptr[LM_LIST];
1312   args[L_ACTIVE] = ptr[LM_EXTRA_ACTIVE];
1313   args[L_PUBLIC] = ptr[LM_EXTRA_PUBLIC];
1314   args[L_HIDDEN] = ptr[LM_EXTRA_HIDDEN];
1315   args[L_MAILLIST] = ptr[LM_EXTRA_MAILLIST];
1316   args[L_GROUP] = ptr[LM_EXTRA_GROUP];
1317   args[L_GID] = ptr[LM_EXTRA_GID];
1318
1319   security_flag = 0;
1320   memset(group_ou, '\0', sizeof(group_ou));
1321   get_group_membership(group_membership, group_ou, &security_flag, args);
1322
1323   if (strlen(group_ou) == 0)
1324     {
1325       com_err(whoami, 0, "Unable to find the group OU for group %s", 
1326               group_name);
1327       return;
1328     }
1329
1330   if (rc = process_group(ldap_handle, dn_path, moira_list_id, group_name, 
1331                          group_ou, group_membership, security_flag, 
1332                          CHECK_GROUPS, args[L_MAILLIST]))
1333     {
1334       if (rc != AD_NO_GROUPS_FOUND)
1335         {
1336           if (rc = process_group(ldap_handle, dn_path, moira_list_id, 
1337                                  group_name, group_ou, group_membership, 
1338                                  security_flag, CLEANUP_GROUPS,
1339                                  args[L_MAILLIST]))
1340             {
1341               if (rc != AD_NO_GROUPS_FOUND)
1342                 {
1343                   if (afterc)
1344                     com_err(whoami, 0, "Unable to add %s to group %s - " 
1345                             "unable to process group", user_name, group_name);
1346                   else
1347                     com_err(whoami, 0, "Unable to remove %s from group %s - "
1348                             "unable to process group", user_name, group_name);
1349                   return;
1350                 }
1351             }
1352         }
1353     }
1354
1355   if (rc == AD_NO_GROUPS_FOUND)
1356     {
1357       if (rc = moira_connect())
1358         {
1359           critical_alert("Ldap incremental",
1360                          "Error contacting Moira server : %s",
1361                          error_message(rc));
1362           return;
1363         }
1364       
1365       com_err(whoami, 0, "creating group %s", group_name);
1366       ProcessGroup = 0;
1367
1368       if (ProcessAce(ldap_handle, dn_path, ptr[LM_LIST], "LIST", 0, 
1369                      &ProcessGroup, ptr[LM_EXTRA_MAILLIST]))
1370         return;
1371
1372       if (ProcessGroup)
1373         {
1374           if (ProcessAce(ldap_handle, dn_path, ptr[LM_LIST], "LIST", 1, 
1375                          &ProcessGroup, ptr[LM_EXTRA_MAILLIST]))
1376             return;
1377         }
1378
1379       if (make_new_group(ldap_handle, dn_path, moira_list_id, ptr[LM_LIST], 
1380                          group_ou, group_membership, security_flag, 0,
1381                          ptr[LM_EXTRA_MAILLIST]))
1382         {
1383           moira_disconnect();
1384           return;
1385         }
1386     
1387       if (atoi(ptr[LM_EXTRA_ACTIVE]))
1388         {
1389           populate_group(ldap_handle, dn_path, ptr[LM_LIST], group_ou, 
1390                          group_membership, security_flag, moira_list_id);
1391         }
1392
1393       moira_disconnect();
1394     }
1395
1396   rc = 0;
1397
1398   if (beforec)
1399     {
1400       com_err(whoami, 0, "removing user %s from list %s", user_name, 
1401               group_name);
1402       pUserOu = user_ou;
1403  
1404       if (!strcasecmp(ptr[LM_TYPE], "MACHINE"))
1405         {
1406           if (!ProcessMachineContainer)
1407             {
1408               com_err(whoami, 0, "Process machines and containers disabled, "
1409                       "skipping");
1410               return;
1411             }
1412
1413           memset(machine_ou, '\0', sizeof(machine_ou));
1414           memset(NewMachineName, '\0', sizeof(NewMachineName));
1415           if (get_machine_ou(ldap_handle, dn_path, ptr[LM_MEMBER], 
1416                              machine_ou, NewMachineName))
1417             return;
1418           if (ptr[LM_MEMBER] != NULL)     
1419             free(ptr[LM_MEMBER]);
1420           ptr[LM_MEMBER] = strdup(NewMachineName);
1421           pUserOu = machine_ou;
1422         }
1423
1424       if (!strcasecmp(ptr[LM_TYPE], "STRING"))
1425         {
1426           strcpy(member, ptr[LM_MEMBER]);
1427
1428           if (Exchange) 
1429             {
1430               if((s = strchr(member, '@')) == (char *) NULL)
1431                 { 
1432                   strcat(member, "@mit.edu");
1433                   
1434                   if (ptr[LM_MEMBER] != NULL)
1435                     free(ptr[LM_MEMBER]);
1436                   ptr[LM_MEMBER] = strdup(member);
1437                 }
1438           
1439               if(!strncasecmp(&member[strlen(member) - 6], ".LOCAL", 6)) 
1440                 {
1441                   s = strrchr(member, '.');
1442                   *s = '\0';
1443                   strcat(s, ".mit.edu");
1444                   
1445                   if (ptr[LM_MEMBER] != NULL)
1446                     free(ptr[LM_MEMBER]);
1447                   ptr[LM_MEMBER] = strdup(member);
1448                 }
1449             }
1450
1451           if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], 
1452                              contact_ou))
1453                 return;
1454
1455           pUserOu = contact_ou;
1456         }
1457       else if (!strcasecmp(ptr[LM_TYPE], "KERBEROS"))
1458         {
1459           if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], 
1460                              kerberos_ou))
1461             return;
1462
1463           pUserOu = kerberos_ou;
1464         }
1465
1466       if (rc = moira_connect()) {
1467         critical_alert("Ldap incremental",
1468                        "Error contacting Moira server : %s",
1469                        error_message(rc));              
1470         return;
1471       }
1472       
1473       if (rc = populate_group(ldap_handle, dn_path, group_name,
1474                               group_ou, group_membership, 
1475                               security_flag, moira_list_id))
1476         com_err(whoami, 0, "Unable to remove %s from group %s", user_name, 
1477                 group_name);
1478       
1479       moira_disconnect();
1480       
1481       if (!strcasecmp(ptr[LM_TYPE], "STRING"))
1482         {
1483           if (rc = moira_connect())
1484             {
1485               critical_alert("Ldap incremental",
1486                              "Error contacting Moira server : %s",
1487                              error_message(rc));
1488               return;
1489             }
1490           
1491           if (rc = populate_group(ldap_handle, dn_path, group_name,
1492                                   group_ou, group_membership, security_flag,
1493                                   moira_list_id))
1494             com_err(whoami, 0, "Unable to remove %s from group %s",
1495                     user_name, group_name);
1496
1497           moira_disconnect();
1498         }
1499       return;
1500     }
1501   
1502   com_err(whoami, 0, "Adding %s to list %s", user_name, group_name);
1503   pUserOu = user_ou;
1504   
1505   if (!strcasecmp(ptr[LM_TYPE], "MACHINE"))
1506     {
1507       memset(machine_ou, '\0', sizeof(machine_ou));
1508       memset(NewMachineName, '\0', sizeof(NewMachineName));
1509
1510       if (get_machine_ou(ldap_handle, dn_path, ptr[LM_MEMBER], machine_ou, 
1511                          NewMachineName))
1512         return;
1513
1514       if (ptr[LM_MEMBER] != NULL)
1515         free(ptr[LM_MEMBER]);
1516
1517       ptr[LM_MEMBER] = strdup(NewMachineName);
1518       pUserOu = machine_ou;
1519     }
1520   else if (!strcasecmp(ptr[LM_TYPE], "STRING"))
1521     {
1522       strcpy(member, ptr[LM_MEMBER]);
1523
1524       if (Exchange) 
1525         {
1526           if((s = strchr(member, '@')) == (char *) NULL)
1527             { 
1528               strcat(member, "@mit.edu");
1529               
1530               if (ptr[LM_MEMBER] != NULL)
1531                 free(ptr[LM_MEMBER]);
1532               ptr[LM_MEMBER] = strdup(member);
1533             }
1534           
1535           if(!strncasecmp(&member[strlen(member) - 6], ".LOCAL", 6)) 
1536             {
1537               s = strrchr(member, '.');
1538               *s = '\0';
1539               strcat(s, ".mit.edu");
1540               
1541               if (ptr[LM_MEMBER] != NULL)
1542                 free(ptr[LM_MEMBER]);
1543               ptr[LM_MEMBER] = strdup(member);
1544             }
1545         }
1546       
1547       if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], 
1548                          contact_ou))
1549         return;
1550
1551       pUserOu = contact_ou;
1552     }
1553   else if (!strcasecmp(ptr[LM_TYPE], "KERBEROS"))
1554     {
1555       if (contact_create(ldap_handle, dn_path, ptr[LM_MEMBER], 
1556                          kerberos_ou))
1557         return;
1558
1559       pUserOu = kerberos_ou;
1560     }
1561   else if (!strcasecmp(ptr[LM_TYPE], "USER"))
1562     {
1563       if ((rc = check_user(ldap_handle, dn_path, ptr[LM_MEMBER], 
1564                            moira_user_id)) == AD_NO_USER_FOUND)
1565         {
1566           if (rc = moira_connect())
1567             {
1568               critical_alert("Ldap incremental", 
1569                              "Error connection to Moira : %s",
1570                              error_message(rc));
1571               return;
1572             }
1573
1574           com_err(whoami, 0, "creating user %s", ptr[LM_MEMBER]);
1575           av[0] = ptr[LM_MEMBER];
1576           call_args[0] = (char *)ldap_handle;
1577           call_args[1] = dn_path;
1578           call_args[2] = moira_user_id;
1579           call_args[3] = NULL;
1580           
1581           callback_rc = 0;
1582
1583           if (Exchange)
1584             {
1585               group_count = 0;
1586               group_base = NULL;
1587           
1588               sprintf(filter, "(&(objectClass=group)(cn=%s))", ptr[LM_MEMBER]);
1589               attr_array[0] = "cn";
1590               attr_array[1] = NULL;
1591               if ((rc = linklist_build(ldap_handle, dn_path, filter, 
1592                                        attr_array, &group_base, &group_count,
1593                                        LDAP_SCOPE_SUBTREE)) != 0)
1594                 {
1595                   com_err(whoami, 0, "Unable to process user %s : %s",
1596                           ptr[LM_MEMBER], ldap_err2string(rc));
1597                   return;
1598                 }
1599               
1600               if (group_count)
1601                 {
1602                   com_err(whoami, 0, "Object already exists with name %s",
1603                           ptr[LM_MEMBER]);
1604                   return;
1605                 }
1606           
1607               linklist_free(group_base);
1608               group_count = 0;
1609               group_base = NULL;
1610             }
1611
1612           if (rc = mr_query("get_user_account_by_login", 1, av, 
1613                             save_query_info, save_argv))
1614             {
1615               moira_disconnect();
1616               com_err(whoami, 0, "Unable to create user %s : %s",
1617                       ptr[LM_MEMBER], error_message(rc));
1618               return;
1619             }
1620         
1621           if (rc = user_create(U_END, save_argv, call_args)) 
1622             {
1623               moira_disconnect();
1624               com_err(whoami, 0, "Unable to create user %s", ptr[LM_MEMBER]);
1625               return;
1626             }
1627
1628           if (callback_rc)
1629             {
1630               moira_disconnect();
1631               com_err(whoami, 0, "Unable to create user %s", ptr[LM_MEMBER]);
1632               return;
1633             }
1634         }
1635       else
1636         {
1637           if (rc != 0)
1638             return;
1639         }
1640       pUserOu = user_ou;
1641     }
1642
1643   if (rc = moira_connect()) {
1644     critical_alert("Ldap incremental",
1645                    "Error contacting Moira server : %s",
1646                    error_message(rc));              
1647     return;
1648   }
1649
1650   if (rc = populate_group(ldap_handle, dn_path, group_name,
1651                           group_ou, group_membership, security_flag,
1652                           moira_list_id))
1653     com_err(whoami, 0, "Unable to add %s to group %s", user_name, 
1654             group_name);
1655   
1656   moira_disconnect();
1657
1658   if (!strcasecmp(ptr[LM_TYPE], "STRING"))
1659     {
1660       if (rc = moira_connect())
1661         {
1662           critical_alert("Ldap incremental",
1663                          "Error contacting Moira server : %s",
1664                          error_message(rc));
1665           return;
1666         }
1667       
1668       if (rc = populate_group(ldap_handle, dn_path, group_name,
1669                               group_ou, group_membership, security_flag,
1670                               moira_list_id))
1671         com_err(whoami, 0, "Unable to add %s to group %s",
1672                 user_name, group_name);
1673       
1674       moira_disconnect();
1675     }
1676
1677   return;
1678 }
1679
1680
1681 #define U_USER_ID    10
1682 #define U_HOMEDIR    11
1683 #define U_PROFILEDIR 12
1684
1685 void do_user(LDAP *ldap_handle, char *dn_path, char *ldap_hostname, 
1686              char **before, int beforec, char **after, 
1687              int afterc)
1688 {
1689   LK_ENTRY *group_base;
1690   int   group_count;
1691   char  filter[128];
1692   char  *attr_array[3];
1693   int   rc;
1694   char  *av[7];
1695   char  after_user_id[32];
1696   char  before_user_id[32];
1697   char  *call_args[7];
1698   char  *save_argv[U_END];
1699
1700   if ((beforec == 0) && (afterc == 0))
1701     return;
1702
1703   memset(after_user_id, '\0', sizeof(after_user_id));
1704   memset(before_user_id, '\0', sizeof(before_user_id));
1705
1706   if (beforec > U_USER_ID)
1707     strcpy(before_user_id, before[U_USER_ID]);
1708
1709   if (afterc > U_USER_ID)
1710     strcpy(after_user_id, after[U_USER_ID]);
1711
1712   if ((beforec == 0) && (afterc == 0)) /*this case should never happen */
1713     return;
1714
1715   if ((beforec == 0) && (afterc != 0)) 
1716     {
1717       /*this case only happens when the account*/
1718       /*account is first created but not usable*/
1719
1720       com_err(whoami, 0, "Unable to process user %s because the user account "
1721               "is not yet usable", after[U_NAME]);
1722       return;
1723     }
1724
1725   /*this case only happens when the account is expunged */
1726
1727   if ((beforec != 0) && (afterc == 0)) 
1728     {                                 
1729       if (atoi(before[U_STATE]) == 0)
1730         {
1731           com_err(whoami, 0, "expunging user %s from directory", 
1732                   before[U_NAME]);
1733           user_delete(ldap_handle, dn_path, before[U_NAME], before_user_id);
1734         }
1735       else
1736         {
1737           com_err(whoami, 0, "Unable to process because user %s has been "
1738                   "previously expungeded", before[U_NAME]);
1739         }
1740       return;
1741     }
1742
1743   /*process anything that gets here*/
1744
1745   if ((rc = check_user(ldap_handle, dn_path, before[U_NAME], 
1746                        before_user_id)) == AD_NO_USER_FOUND)
1747     {
1748       if (!check_string(after[U_NAME]))
1749         return;
1750
1751       if (rc = moira_connect())
1752         {
1753           critical_alert("Ldap incremental", 
1754                          "Error connection to Moira : %s",
1755                          error_message(rc));
1756           return;
1757         }
1758
1759       com_err(whoami, 0, "creating user %s", after[U_NAME]);
1760       
1761       av[0] = after[U_NAME];
1762       call_args[0] = (char *)ldap_handle;
1763       call_args[1] = dn_path;
1764       call_args[2] = after_user_id;
1765       call_args[3] = NULL;
1766       callback_rc = 0;
1767
1768       if (Exchange) 
1769         {
1770           group_count = 0;
1771           group_base = NULL;
1772           
1773           sprintf(filter, "(&(objectClass=group)(cn=%s))", after[U_NAME]);
1774           attr_array[0] = "cn";
1775           attr_array[1] = NULL;
1776           
1777           if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
1778                                    &group_base, &group_count,
1779                                    LDAP_SCOPE_SUBTREE)) != 0)
1780             {
1781               com_err(whoami, 0, "Unable to process user %s : %s",
1782                       after[U_NAME], ldap_err2string(rc));
1783               return;
1784             }
1785           
1786           if (group_count >= 1)
1787             {
1788               com_err(whoami, 0, "Object already exists with name %s",
1789                       after[U_NAME]);
1790               return;
1791             }
1792       
1793           linklist_free(group_base);
1794           group_count = 0;
1795           group_base = NULL;
1796         }
1797
1798       if (rc = mr_query("get_user_account_by_login", 1, av,
1799                         save_query_info, save_argv))
1800         {
1801           moira_disconnect();
1802           com_err(whoami, 0, "Unable to create user %s : %s",
1803                   after[U_NAME], error_message(rc));
1804           return;
1805         }
1806
1807       if (rc = user_create(U_END, save_argv, call_args)) 
1808         {
1809           com_err(whoami, 0, "Unable to create user %s : %s",
1810                   after[U_NAME], error_message(rc));
1811           return;
1812         }
1813       
1814       if (callback_rc)
1815         {
1816           moira_disconnect();
1817           com_err(whoami, 0, "Unable to create user %s", after[U_NAME]);
1818           return;
1819         }
1820
1821       return;
1822     }
1823   else
1824     {
1825       if (rc != 0)
1826         return;
1827     }
1828
1829   if (strcmp(before[U_NAME], after[U_NAME]))
1830     {
1831       if ((check_string(before[U_NAME])) && (check_string(after[U_NAME])))
1832         {
1833           com_err(whoami, 0, "changing user %s to %s", 
1834                   before[U_NAME], after[U_NAME]);
1835
1836           if ((rc = user_rename(ldap_handle, dn_path, before[U_NAME], 
1837                                 after[U_NAME])) != LDAP_SUCCESS)
1838             {
1839               return;
1840             }
1841         }
1842     }
1843
1844   com_err(whoami, 0, "updating user %s information", after[U_NAME]);
1845   rc = user_update(ldap_handle, dn_path, after[U_NAME],
1846                    after[U_UID], after[U_MITID], 
1847                    after_user_id, atoi(after[U_STATE]),
1848                    after[U_HOMEDIR], after[U_PROFILEDIR],
1849                    after[U_FIRST], after[U_MIDDLE], after[U_LAST], 
1850                    after[U_SHELL], after[U_CLASS]);
1851
1852   return;
1853 }
1854
1855 int construct_newvalues(LK_ENTRY *linklist_base, int modvalue_count, 
1856                         char *oldValue, char *newValue,
1857                         char ***modvalues, int type)
1858 {
1859   LK_ENTRY    *linklist_ptr;
1860   int         i;
1861   char        *cPtr;
1862   
1863   if (((*modvalues) = calloc(1, 
1864                              (modvalue_count + 1) * sizeof(char *))) == NULL)
1865     {
1866       return(1);
1867     }
1868
1869   for (i = 0; i < (modvalue_count + 1); i++)
1870     (*modvalues)[i] = NULL;
1871
1872   if (modvalue_count != 0)
1873     {
1874       linklist_ptr = linklist_base;
1875       for (i = 0; i < modvalue_count; i++)
1876         {
1877           if ((oldValue != NULL) && (newValue != NULL))
1878             {
1879               if ((cPtr = (char *)strstr(linklist_ptr->value, oldValue))
1880                   != (char *)NULL)
1881                 {
1882                   if (type == REPLACE)
1883                     {
1884                       if (((*modvalues)[i] = calloc(1, strlen(newValue) + 1))
1885                           == NULL)
1886                         return(1);
1887                       memset((*modvalues)[i], '\0', strlen(newValue) + 1);
1888                       strcpy((*modvalues)[i], newValue);
1889                     }
1890                   else
1891                     {
1892                       if (((*modvalues)[i] = calloc(1, 
1893                                         (int)(cPtr - linklist_ptr->value) + 
1894                                                (linklist_ptr->length - 
1895                                                strlen(oldValue)) + 
1896                                                strlen(newValue) + 1)) == NULL)
1897                         return(1);
1898                       memset((*modvalues)[i], '\0', 
1899                              (int)(cPtr - linklist_ptr->value) + 
1900                              (linklist_ptr->length - strlen(oldValue)) + 
1901                              strlen(newValue) + 1);
1902                       memcpy((*modvalues)[i], linklist_ptr->value, 
1903                              (int)(cPtr - linklist_ptr->value));
1904                       strcat((*modvalues)[i], newValue);
1905                       strcat((*modvalues)[i], 
1906                              &linklist_ptr->value[(int)(cPtr - 
1907                                      linklist_ptr->value) + strlen(oldValue)]);
1908                     }
1909                 }
1910               else
1911                 {
1912                   (*modvalues)[i] = calloc(1, linklist_ptr->length + 1);
1913                   memset((*modvalues)[i], '\0', linklist_ptr->length + 1);
1914                   memcpy((*modvalues)[i], linklist_ptr->value,
1915                          linklist_ptr->length);
1916                 }
1917             }
1918         else
1919             {
1920               (*modvalues)[i] = calloc(1, linklist_ptr->length + 1);
1921               memset((*modvalues)[i], '\0', linklist_ptr->length + 1);
1922               memcpy((*modvalues)[i], linklist_ptr->value,
1923                      linklist_ptr->length);
1924             }
1925           linklist_ptr = linklist_ptr->next;
1926         }
1927       (*modvalues)[i] = NULL;
1928     }
1929   return(0);
1930 }
1931
1932
1933 int linklist_build(LDAP *ldap_handle, char *dn_path, char *search_exp, 
1934                    char **attr_array, LK_ENTRY **linklist_base,
1935                    int *linklist_count, unsigned long ScopeType)
1936 {
1937   ULONG       rc;
1938   LDAPMessage *ldap_entry;
1939
1940   rc = 0;
1941   ldap_entry = NULL;
1942   (*linklist_base) = NULL;
1943   (*linklist_count) = 0;
1944
1945   if ((rc = ldap_search_s(ldap_handle, dn_path, ScopeType, 
1946                           search_exp, attr_array, 0, 
1947                           &ldap_entry)) != LDAP_SUCCESS)
1948       {
1949         if (rc != LDAP_SIZELIMIT_EXCEEDED)
1950           return(0);
1951       }
1952
1953   rc = retrieve_entries(ldap_handle, ldap_entry, linklist_base, 
1954                         linklist_count);
1955
1956   ldap_msgfree(ldap_entry);
1957   return(rc);
1958 }
1959
1960 int retrieve_entries(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
1961                      LK_ENTRY **linklist_base, int *linklist_count)
1962 {
1963   char        distinguished_name[1024];
1964   LK_ENTRY    *linklist_ptr;
1965   int         rc;
1966
1967   if ((ldap_entry = ldap_first_entry(ldap_handle, ldap_entry)) == NULL)
1968     return(0);
1969   
1970   memset(distinguished_name, '\0', sizeof(distinguished_name));
1971   get_distinguished_name(ldap_handle, ldap_entry, distinguished_name);
1972
1973   if ((rc = retrieve_attributes(ldap_handle, ldap_entry, distinguished_name,
1974                                 linklist_base)) != 0)
1975     return(rc);
1976
1977   while ((ldap_entry = ldap_next_entry(ldap_handle, ldap_entry)) != NULL)
1978     {
1979       memset(distinguished_name, '\0', sizeof(distinguished_name));
1980       get_distinguished_name(ldap_handle, ldap_entry, distinguished_name);
1981       
1982       if ((rc = retrieve_attributes(ldap_handle, ldap_entry, 
1983                                     distinguished_name, linklist_base)) != 0)
1984         return(rc);
1985     }
1986
1987   linklist_ptr = (*linklist_base);
1988   (*linklist_count) = 0;
1989
1990   while (linklist_ptr != NULL)
1991     {
1992       ++(*linklist_count);
1993       linklist_ptr = linklist_ptr->next;
1994     }
1995
1996   return(0);
1997 }
1998
1999 int retrieve_attributes(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
2000                         char *distinguished_name, LK_ENTRY **linklist_current)
2001 {
2002   char        *Attribute;
2003   BerElement  *ptr;
2004
2005   ptr = NULL;
2006
2007   if ((Attribute = ldap_first_attribute(ldap_handle, ldap_entry, 
2008                                         &ptr)) != NULL)
2009     {
2010       retrieve_values(ldap_handle, ldap_entry, Attribute, distinguished_name,
2011                       linklist_current);
2012       ldap_memfree(Attribute);
2013       while ((Attribute = ldap_next_attribute(ldap_handle, ldap_entry, 
2014                                               ptr)) != NULL)
2015         {
2016           retrieve_values(ldap_handle, ldap_entry, Attribute,
2017                           distinguished_name, linklist_current);
2018           ldap_memfree(Attribute);
2019         }
2020     }
2021
2022   ldap_ber_free(ptr, 0);
2023
2024   return(0);
2025 }
2026
2027 int retrieve_values(LDAP *ldap_handle, LDAPMessage *ldap_entry,
2028                     char *Attribute, char *distinguished_name,
2029                     LK_ENTRY **linklist_current)
2030 {
2031   char        **str_value;
2032   char        temp[256];
2033   void        **Ptr;
2034   int         use_bervalue;
2035   LK_ENTRY    *linklist_previous;
2036   LDAP_BERVAL **ber_value;
2037   DWORD       ber_length;
2038
2039 #ifdef LDAP_DEBUG
2040   SID         *sid;
2041   GUID        *guid;
2042   int         i;
2043   int         intValue;
2044   DWORD       *subauth;
2045   SID_IDENTIFIER_AUTHORITY    *sid_auth;
2046   unsigned char   *subauth_count;
2047 #endif /*LDAP_BEGUG*/
2048
2049   use_bervalue = 0;
2050   memset(temp, '\0', sizeof(temp));
2051
2052   if ((!strcmp(Attribute, "objectSid")) ||
2053       (!strcmp(Attribute, "objectGUID")))
2054     use_bervalue = 1;
2055   
2056   if (use_bervalue)
2057     {
2058       ber_value = ldap_get_values_len(ldap_handle, ldap_entry, Attribute);
2059       Ptr = (void **)ber_value;
2060       str_value = NULL;
2061     }
2062   else
2063     {
2064       str_value = ldap_get_values(ldap_handle, ldap_entry, Attribute);
2065       Ptr = (void **)str_value;
2066       ber_value = NULL;
2067     }
2068
2069   if (Ptr != NULL)
2070     {
2071       for (; *Ptr; Ptr++) 
2072         {
2073           if ((linklist_previous = calloc(1, sizeof(LK_ENTRY))) == NULL)
2074             return(1);
2075
2076           memset(linklist_previous, '\0', sizeof(LK_ENTRY));
2077           linklist_previous->next = (*linklist_current);
2078           (*linklist_current) = linklist_previous;
2079           
2080           if (((*linklist_current)->attribute = calloc(1, 
2081                                               strlen(Attribute) + 1)) == NULL)
2082             return(1);
2083
2084           memset((*linklist_current)->attribute, '\0', strlen(Attribute) + 1);
2085           strcpy((*linklist_current)->attribute, Attribute);
2086
2087           if (use_bervalue)
2088             {
2089               ber_length = (*(LDAP_BERVAL **)Ptr)->bv_len;
2090
2091               if (((*linklist_current)->value = calloc(1, ber_length)) == NULL)
2092                 return(1);
2093
2094               memset((*linklist_current)->value, '\0', ber_length);
2095               memcpy((*linklist_current)->value, 
2096                      (*(LDAP_BERVAL **)Ptr)->bv_val, ber_length);
2097               (*linklist_current)->length = ber_length;
2098             }
2099           else
2100             {
2101               if (((*linklist_current)->value = calloc(1, 
2102                                                     strlen(*Ptr) + 1)) == NULL)
2103                 return(1);
2104
2105               memset((*linklist_current)->value, '\0', strlen(*Ptr) + 1);
2106               (*linklist_current)->length = strlen(*Ptr);
2107               strcpy((*linklist_current)->value, *Ptr);
2108             }
2109
2110           (*linklist_current)->ber_value = use_bervalue;
2111
2112           if (((*linklist_current)->dn = calloc(1, 
2113                                       strlen(distinguished_name) + 1)) == NULL)
2114             return(1);
2115
2116           memset((*linklist_current)->dn, '\0', 
2117                  strlen(distinguished_name) + 1);
2118           strcpy((*linklist_current)->dn, distinguished_name);
2119
2120 #ifdef LDAP_DEBUG
2121           if (!strcmp(Attribute, "objectGUID"))
2122             {
2123               guid = (GUID *)((*linklist_current)->value);
2124               sprintf(temp, 
2125                       "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x", 
2126                       guid->Data1, guid->Data2, guid->Data3, 
2127                       guid->Data4[0], guid->Data4[1], guid->Data4[2], 
2128                       guid->Data4[3], guid->Data4[4], guid->Data4[5], 
2129                       guid->Data4[6], guid->Data4[7]);
2130               print_to_screen("     %20s : {%s}\n", Attribute, temp);
2131             }
2132           else if (!strcmp(Attribute, "objectSid"))
2133             {
2134               sid = (SID *)((*(LDAP_BERVAL **)Ptr)->bv_val);
2135
2136 #ifdef _WIN32
2137               print_to_screen("        Revision = %d\n", sid->Revision);
2138               print_to_screen("        SID Identifier Authority:\n");
2139               sid_auth = &sid->IdentifierAuthority;
2140               if (sid_auth->Value[0])
2141                 print_to_screen("            SECURITY_NULL_SID_AUTHORITY\n");
2142               else if (sid_auth->Value[1])
2143                 print_to_screen("            SECURITY_WORLD_SID_AUTHORITY\n");
2144               else if (sid_auth->Value[2])
2145                 print_to_screen("            SECURITY_LOCAL_SID_AUTHORITY\n");
2146               else if (sid_auth->Value[3])
2147                 print_to_screen("           SECURITY_CREATOR_SID_AUTHORITY\n");
2148               else if (sid_auth->Value[5])
2149                 print_to_screen("            SECURITY_NT_AUTHORITY\n");
2150               else
2151                 print_to_screen("            UNKNOWN SID AUTHORITY\n");
2152               subauth_count = GetSidSubAuthorityCount(sid);
2153               print_to_screen("        SidSubAuthorityCount = %d\n", 
2154                               *subauth_count);
2155               print_to_screen("        SidSubAuthority:\n");
2156               for (i = 0; i < *subauth_count; i++)
2157                 {
2158                   if ((subauth = GetSidSubAuthority(sid, i)) != NULL)
2159                     print_to_screen("            %u\n", *subauth);
2160                 }
2161 #endif
2162             }
2163           else if ((!memcmp(Attribute, "userAccountControl", 
2164                             strlen("userAccountControl"))) ||
2165                    (!memcmp(Attribute, "sAMAccountType", 
2166                             strlen("sAmAccountType"))))
2167             {
2168               intValue = atoi(*Ptr);
2169               print_to_screen("     %20s : %ld\n",Attribute, intValue);
2170
2171               if (!memcmp(Attribute, "userAccountControl", 
2172                           strlen("userAccountControl")))
2173                 {
2174                   if (intValue & UF_ACCOUNTDISABLE)
2175                     print_to_screen("     %20s :    %s\n", 
2176                                     "", "Account disabled");
2177                   else
2178                     print_to_screen("     %20s :    %s\n", 
2179                                     "", "Account active");
2180                   if (intValue & UF_HOMEDIR_REQUIRED)
2181                     print_to_screen("     %20s :    %s\n", 
2182                                     "", "Home directory required");
2183                   if (intValue & UF_LOCKOUT)
2184                     print_to_screen("     %20s :    %s\n", 
2185                                     "", "Account locked out");
2186                   if (intValue & UF_PASSWD_NOTREQD)
2187                     print_to_screen("     %20s :    %s\n", 
2188                                     "", "No password required");
2189                   if (intValue & UF_PASSWD_CANT_CHANGE)
2190                     print_to_screen("     %20s :    %s\n",
2191                                     "", "Cannot change password");
2192                   if (intValue & UF_TEMP_DUPLICATE_ACCOUNT)
2193                     print_to_screen("     %20s :    %s\n", 
2194                                     "", "Temp duplicate account");
2195                   if (intValue & UF_NORMAL_ACCOUNT)
2196                     print_to_screen("     %20s :    %s\n", 
2197                                     "", "Normal account");
2198                   if (intValue & UF_INTERDOMAIN_TRUST_ACCOUNT)
2199                     print_to_screen("     %20s :    %s\n", 
2200                                     "", "Interdomain trust account");
2201                   if (intValue & UF_WORKSTATION_TRUST_ACCOUNT)
2202                     print_to_screen("     %20s :    %s\n", 
2203                                     "", "Workstation trust account");
2204                   if (intValue & UF_SERVER_TRUST_ACCOUNT)
2205                     print_to_screen("     %20s :    %s\n", 
2206                                     "", "Server trust account");
2207                 }
2208             }
2209           else
2210             {
2211               print_to_screen("     %20s : %s\n",Attribute, *Ptr);
2212             }
2213 #endif /*LDAP_DEBUG*/
2214         }
2215
2216       if (str_value != NULL)
2217         ldap_value_free(str_value);
2218
2219       if (ber_value != NULL)
2220         ldap_value_free_len(ber_value);
2221     }
2222
2223   (*linklist_current) = linklist_previous;
2224
2225   return(0);
2226 }
2227
2228 int moira_connect(void)
2229 {
2230   long    rc;
2231   char    HostName[64];
2232
2233   if (!mr_connections++)
2234     {
2235
2236 #ifdef _WIN32
2237       memset(HostName, '\0', sizeof(HostName));
2238       strcpy(HostName, "ttsp");
2239       rc = mr_connect_cl(HostName, "ldap.incr", QUERY_VERSION, 1);
2240 #else
2241       struct utsname uts;
2242       uname(&uts);
2243       rc = mr_connect_cl(uts.nodename, "ldap.incr", QUERY_VERSION, 1);
2244 #endif /*WIN32*/
2245
2246       return rc;
2247     }
2248
2249   return 0;
2250 }
2251
2252 int check_winad(void)
2253 {
2254   int i;
2255   
2256   for (i = 0; file_exists(STOP_FILE); i++)
2257     {
2258       if (i > 30)
2259         {
2260           critical_alert("Ldap incremental",
2261                          "Ldap incremental failed (%s exists): %s",
2262                          STOP_FILE, tbl_buf);
2263           return(1);
2264         }
2265
2266       sleep(60);
2267     }
2268
2269   return(0);
2270 }
2271
2272 int moira_disconnect(void)
2273 {
2274
2275   if (!--mr_connections)
2276     {
2277       mr_disconnect();
2278     }
2279
2280   return 0;
2281 }
2282
2283 void get_distinguished_name(LDAP *ldap_handle, LDAPMessage *ldap_entry, 
2284                             char *distinguished_name)
2285 {
2286   char    *CName;
2287   
2288   CName = ldap_get_dn(ldap_handle, ldap_entry);
2289
2290   if (CName == NULL)
2291     return;
2292
2293   strcpy(distinguished_name, CName);
2294   ldap_memfree(CName);
2295 }
2296
2297 int linklist_create_entry(char *attribute, char *value, 
2298                           LK_ENTRY **linklist_entry)
2299 {
2300   (*linklist_entry) = calloc(1, sizeof(LK_ENTRY));
2301
2302   if (!(*linklist_entry))
2303     {
2304       return(1);
2305     }
2306
2307   memset((*linklist_entry), '\0', sizeof(LK_ENTRY));
2308   (*linklist_entry)->attribute = calloc(1, strlen(attribute) + 1);
2309   memset((*linklist_entry)->attribute, '\0', strlen(attribute) + 1);
2310   strcpy((*linklist_entry)->attribute, attribute);
2311   (*linklist_entry)->value = calloc(1, strlen(value) + 1);
2312   memset((*linklist_entry)->value, '\0', strlen(value) + 1);
2313   strcpy((*linklist_entry)->value, value);
2314   (*linklist_entry)->length = strlen(value);
2315   (*linklist_entry)->next = NULL;
2316
2317   return(0);
2318 }
2319
2320 void print_to_screen(const char *fmt, ...)
2321 {
2322   va_list pvar;
2323
2324   va_start(pvar, fmt);
2325   vfprintf(stderr, fmt, pvar);
2326   fflush(stderr);
2327   va_end(pvar);
2328 }
2329
2330 int get_group_membership(char *group_membership, char *group_ou, 
2331                          int *security_flag, char **av)
2332 {
2333   int  maillist_flag;
2334   int  group_flag;
2335   
2336   maillist_flag = atoi(av[L_MAILLIST]);
2337   group_flag = atoi(av[L_GROUP]);
2338
2339   if (security_flag != NULL)
2340     (*security_flag) = 0;
2341   
2342   if ((maillist_flag) && (group_flag))
2343     {
2344       if (group_membership != NULL)
2345         group_membership[0] = 'B';
2346
2347       if (security_flag != NULL)
2348         (*security_flag) = 1;
2349
2350       if (group_ou != NULL)
2351         strcpy(group_ou, group_ou_both);
2352     }
2353   else if ((!maillist_flag) && (group_flag))
2354     {
2355       if (group_membership != NULL)
2356         group_membership[0] = 'S';
2357
2358       if (security_flag != NULL)
2359         (*security_flag) = 1;
2360
2361       if (group_ou != NULL)
2362         strcpy(group_ou, group_ou_security);
2363     }
2364   else if ((maillist_flag) && (!group_flag))
2365     {
2366       if (group_membership != NULL)
2367         group_membership[0] = 'D';
2368
2369       if (group_ou != NULL)
2370         strcpy(group_ou, group_ou_distribution);
2371     }
2372   else
2373     {
2374       if (group_membership != NULL)
2375         group_membership[0] = 'N';
2376
2377       if (group_ou != NULL)
2378         strcpy(group_ou, group_ou_neither);
2379     }
2380
2381   return(0);
2382 }
2383
2384 int group_rename(LDAP *ldap_handle, char *dn_path, 
2385                  char *before_group_name, char *before_group_membership, 
2386                  char *before_group_ou, int before_security_flag, 
2387                  char *before_desc, char *after_group_name, 
2388                  char *after_group_membership, char *after_group_ou, 
2389                  int after_security_flag, char *after_desc,
2390                  char *MoiraId, char *filter, char *maillist)
2391 {
2392   LDAPMod   *mods[20];
2393   char      old_dn[512];
2394   char      new_dn[512];
2395   char      new_dn_path[512];
2396   char      sam_name[256];
2397   char      mail[256];
2398   char      mail_nickname[256];
2399   char      proxy_address[256];
2400   char      address_book[256];
2401   char      *attr_array[3];
2402   char      *mitMoiraId_v[] = {NULL, NULL};
2403   char      *name_v[] = {NULL, NULL};
2404   char      *samAccountName_v[] = {NULL, NULL};
2405   char      *groupTypeControl_v[] = {NULL, NULL};
2406   char      *mail_v[] = {NULL, NULL};
2407   char      *proxy_address_v[] = {NULL, NULL};
2408   char      *mail_nickname_v[] = {NULL, NULL};
2409   char      *report_to_originator_v[] = {NULL, NULL};
2410   char      *address_book_v[] = {NULL, NULL};
2411   char      *legacy_exchange_dn_v[] = {NULL, NULL};
2412   char      *null_v[] = {NULL, NULL};
2413   u_int     groupTypeControl;
2414   char      groupTypeControlStr[80];
2415   char      contact_mail[256];
2416   int       n;
2417   int       i;
2418   int       rc;
2419   LK_ENTRY  *group_base;
2420   int       group_count;
2421   int       MailDisabled = 0;
2422
2423   if(UseGroupUniversal)
2424     groupTypeControl = ADS_GROUP_TYPE_UNIVERSAL_GROUP;
2425   else
2426     groupTypeControl = ADS_GROUP_TYPE_GLOBAL_GROUP;
2427      
2428   if (!check_string(before_group_name))
2429     {
2430       com_err(whoami, 0, 
2431               "Unable to process invalid LDAP list name %s", 
2432               before_group_name);
2433       return(AD_INVALID_NAME);
2434     }
2435
2436   if (!check_string(after_group_name))
2437     {
2438       com_err(whoami, 0, 
2439               "Unable to process invalid LDAP list name %s", after_group_name);
2440       return(AD_INVALID_NAME);
2441     }
2442
2443   if (Exchange) 
2444     {
2445       if(atoi(maillist)) 
2446         {
2447           group_count = 0;
2448           group_base = NULL;
2449           
2450           sprintf(filter, "(&(objectClass=user)(cn=%s))", after_group_name);
2451           attr_array[0] = "cn";
2452           attr_array[1] = NULL;
2453
2454           if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
2455                                    &group_base, &group_count,
2456                                    LDAP_SCOPE_SUBTREE)) != 0)
2457           {
2458             com_err(whoami, 0, "Unable to process group %s : %s",
2459                     after_group_name, ldap_err2string(rc));
2460             return(rc);
2461           }
2462           
2463           if (group_count)
2464             {
2465               com_err(whoami, 0, "Object already exists with name %s",
2466                       after_group_name);
2467               MailDisabled++;
2468             }
2469         
2470           linklist_free(group_base);
2471           group_base = NULL;
2472           group_count = 0;
2473         }
2474     }
2475
2476   group_count = 0;
2477   group_base = NULL;
2478
2479   if (rc = ad_get_group(ldap_handle, dn_path, before_group_name, 
2480                         before_group_membership, 
2481                         MoiraId, "samAccountName", &group_base, 
2482                         &group_count, filter))
2483     return(rc);
2484
2485   if (group_count == 0)
2486     {
2487       return(AD_NO_GROUPS_FOUND);
2488     }
2489
2490   if (group_count != 1)
2491     {
2492       com_err(whoami, 0, "Unable to process multiple groups with "
2493               "MoiraId = %s exist in the directory", MoiraId);
2494       return(AD_MULTIPLE_GROUPS_FOUND);
2495     }
2496
2497   strcpy(old_dn, group_base->dn);
2498
2499   linklist_free(group_base);
2500   group_base = NULL;
2501   group_count = 0;
2502   attr_array[0] = "sAMAccountName";
2503   attr_array[1] = NULL;
2504
2505   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
2506                            &group_base, &group_count, 
2507                            LDAP_SCOPE_SUBTREE)) != 0)
2508     {
2509       com_err(whoami, 0, "Unable to get list %s dn : %s",
2510               after_group_name, ldap_err2string(rc));
2511       return(rc);
2512     }
2513
2514   if (group_count != 1)
2515     {
2516       com_err(whoami, 0,
2517               "Unable to get sAMAccountName for group %s", 
2518               before_group_name);
2519       return(AD_LDAP_FAILURE);
2520     }
2521   
2522   strcpy(sam_name, group_base->value);
2523   linklist_free(group_base);
2524   group_base = NULL;
2525   group_count = 0;
2526   
2527   sprintf(new_dn_path, "%s,%s", after_group_ou, dn_path);
2528   sprintf(new_dn, "cn=%s", after_group_name);
2529   sprintf(mail, "%s@%s", after_group_name, lowercase(ldap_domain));
2530   sprintf(contact_mail, "%s@mit.edu", after_group_name); 
2531   sprintf(proxy_address, "SMTP:%s@%s", after_group_name, 
2532           lowercase(ldap_domain));
2533   sprintf(mail_nickname, "%s", after_group_name);
2534
2535   com_err(whoami, 0, "Old %s New %s,%s", old_dn, new_dn, new_dn_path);
2536
2537   if ((rc = ldap_rename_s(ldap_handle, old_dn, new_dn, new_dn_path,
2538                               TRUE, NULL, NULL)) != LDAP_SUCCESS)
2539     {
2540       com_err(whoami, 0, "Unable to rename list from %s to %s : %s",
2541               before_group_name, after_group_name, ldap_err2string(rc));
2542       return(rc);
2543     }
2544   
2545   name_v[0] = after_group_name;
2546
2547   if (!strncmp(&sam_name[strlen(sam_name) - strlen(group_suffix)], 
2548                group_suffix, strlen(group_suffix)))
2549     {
2550       sprintf(sam_name, "%s%s", after_group_name, group_suffix);
2551     }
2552   else
2553     {
2554       com_err(whoami, 0, 
2555               "Unable to rename list from %s to %s : sAMAccountName not found",
2556               before_group_name, after_group_name);
2557       return(rc);
2558     }
2559
2560   samAccountName_v[0] = sam_name;
2561
2562   if (after_security_flag)
2563     groupTypeControl |= ADS_GROUP_TYPE_SECURITY_ENABLED;
2564
2565   sprintf(groupTypeControlStr, "%ld", groupTypeControl);
2566   groupTypeControl_v[0] = groupTypeControlStr;
2567   mitMoiraId_v[0] = MoiraId;
2568
2569   sprintf(new_dn, "cn=%s,%s,%s", after_group_name, after_group_ou, dn_path);
2570   rc = attribute_update(ldap_handle, new_dn, after_desc, "description", 
2571                         after_group_name);
2572   n = 0;
2573   ADD_ATTR("samAccountName", samAccountName_v, LDAP_MOD_REPLACE);
2574   ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
2575   ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
2576   ADD_ATTR("groupType", groupTypeControl_v, LDAP_MOD_REPLACE);
2577
2578   if (Exchange)
2579     {
2580       if(atoi(maillist) && !MailDisabled && email_isvalid(mail)) 
2581         {
2582           mail_nickname_v[0] = mail_nickname;
2583           proxy_address_v[0] = proxy_address;
2584           mail_v[0] = mail;
2585           report_to_originator_v[0] = "TRUE";
2586
2587           ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_REPLACE);
2588           ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
2589           ADD_ATTR("proxyAddresses", proxy_address_v, LDAP_MOD_REPLACE);
2590           ADD_ATTR("reportToOriginator", report_to_originator_v, 
2591                    LDAP_MOD_REPLACE);
2592         } 
2593       else 
2594         {
2595           mail_nickname_v[0] = NULL;
2596           proxy_address_v[0] = NULL;
2597           mail_v[0] = NULL;
2598           legacy_exchange_dn_v[0] = NULL;
2599           address_book_v[0] = NULL;
2600           report_to_originator_v[0] = NULL;
2601
2602           ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_REPLACE);
2603           ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
2604           ADD_ATTR("proxyAddresses", proxy_address_v, LDAP_MOD_REPLACE);
2605           ADD_ATTR("legacyExchangeDN", legacy_exchange_dn_v, LDAP_MOD_REPLACE);
2606           ADD_ATTR("showInAddressBook", address_book_v, LDAP_MOD_REPLACE);
2607           ADD_ATTR("reportToOriginator", report_to_originator_v, 
2608                    LDAP_MOD_REPLACE);
2609         }
2610     }
2611   else
2612     {
2613       if(atoi(maillist) && email_isvalid(contact_mail)) 
2614         {
2615           mail_v[0] = contact_mail;
2616           ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
2617
2618           if(!ActiveDirectory)
2619             {
2620               null_v[0] = "/dev/null";
2621               ADD_ATTR("mailRoutingAddress", null_v, LDAP_MOD_REPLACE);
2622             }
2623         }
2624     }
2625
2626   mods[n] = NULL;
2627
2628   if ((rc = ldap_modify_s(ldap_handle, new_dn, mods)) != LDAP_SUCCESS)
2629     {
2630       com_err(whoami, 0, 
2631               "Unable to modify list data for %s after renaming: %s",
2632               after_group_name, ldap_err2string(rc));
2633     }
2634
2635   for (i = 0; i < n; i++)
2636     free(mods[i]);
2637
2638   return(rc);
2639 }
2640
2641 int group_create(int ac, char **av, void *ptr)
2642 {
2643   LDAPMod *mods[20];
2644   char new_dn[256];
2645   char group_ou[256];
2646   char new_group_name[256];
2647   char sam_group_name[256];
2648   char cn_group_name[256];
2649   char mail[256];
2650   char contact_mail[256];
2651   char mail_nickname[256];
2652   char proxy_address[256];
2653   char address_book[256];
2654   char *cn_v[] = {NULL, NULL};
2655   char *objectClass_v[] = {"top", "group", NULL};
2656   char *objectClass_ldap_v[] = {"top", "microsoftComTop", "securityPrincipal",
2657                                 "group", "mailRecipient", NULL};
2658   char info[256];
2659   char *samAccountName_v[] = {NULL, NULL};
2660   char *altSecurityIdentities_v[] = {NULL, NULL};
2661   char *member_v[] = {NULL, NULL};
2662   char *name_v[] = {NULL, NULL};
2663   char *desc_v[] = {NULL, NULL};
2664   char *info_v[] = {NULL, NULL};
2665   char *mitMoiraId_v[] = {NULL, NULL};
2666   char *mitMoiraPublic_v[] = {NULL, NULL};
2667   char *mitMoiraHidden_v[] = {NULL, NULL};
2668   char *groupTypeControl_v[] = {NULL, NULL};
2669   char *mail_v[] = {NULL, NULL};
2670   char *proxy_address_v[] = {NULL, NULL};
2671   char *mail_nickname_v[] = {NULL, NULL};
2672   char *report_to_originator_v[] = {NULL, NULL};
2673   char *address_book_v[] = {NULL, NULL};
2674   char *legacy_exchange_dn_v[] = {NULL, NULL};
2675   char *gidNumber_v[] = {NULL, NULL};
2676   char *null_v[] = {NULL, NULL};
2677   char groupTypeControlStr[80];
2678   char group_membership[1];
2679   int  i;
2680   int  security_flag;
2681   u_int groupTypeControl;
2682   int  n;
2683   int  rc;
2684   int  updateGroup;
2685   int  MailDisabled = 0;
2686   char **call_args;
2687   LK_ENTRY *group_base;
2688   int  group_count;
2689   char filter[1024];
2690   char *attr_array[3];
2691   
2692   call_args = ptr;
2693
2694   if(UseGroupUniversal)
2695     groupTypeControl = ADS_GROUP_TYPE_UNIVERSAL_GROUP;
2696   else 
2697     groupTypeControl = ADS_GROUP_TYPE_GLOBAL_GROUP;
2698
2699   if (!check_string(av[L_NAME]))
2700     {
2701       com_err(whoami, 0, "Unable to process invalid LDAP list name %s", 
2702               av[L_NAME]);
2703       return(AD_INVALID_NAME);
2704     }
2705
2706   updateGroup = (int)call_args[4];
2707   memset(group_ou, 0, sizeof(group_ou));
2708   memset(group_membership, 0, sizeof(group_membership));
2709   security_flag = 0;
2710
2711   get_group_membership(group_membership, group_ou, &security_flag, av);
2712
2713   strcpy(new_group_name, av[L_NAME]);
2714   sprintf(new_dn, "cn=%s,%s,%s", new_group_name, group_ou, call_args[1]);
2715   sprintf(contact_mail, "%s@mit.edu", av[L_NAME]);
2716   sprintf(mail, "%s@%s", av[L_NAME], lowercase(ldap_domain));
2717   sprintf(mail_nickname, "%s", av[L_NAME]);
2718
2719   if (security_flag)
2720     groupTypeControl |= ADS_GROUP_TYPE_SECURITY_ENABLED;
2721   
2722   sprintf(sam_group_name, "%s%s", av[L_NAME], group_suffix);
2723
2724   if (!updateGroup)
2725     {
2726       sprintf(groupTypeControlStr, "%ld", groupTypeControl);
2727       groupTypeControl_v[0] = groupTypeControlStr;
2728
2729       strcpy(cn_group_name, av[L_NAME]);
2730       
2731       samAccountName_v[0] = sam_group_name;
2732       name_v[0] = new_group_name;
2733       cn_v[0] = new_group_name;
2734
2735       n = 0;
2736       ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
2737
2738       if(ActiveDirectory)
2739         {
2740           ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
2741         } 
2742       else
2743         {
2744           mitMoiraPublic_v[0] = av[L_PUBLIC];
2745           mitMoiraHidden_v[0] = av[L_HIDDEN];
2746           ADD_ATTR("objectClass", objectClass_ldap_v, LDAP_MOD_ADD);
2747           ADD_ATTR("mitMoiraPublic", mitMoiraPublic_v, LDAP_MOD_ADD);
2748           ADD_ATTR("mitMoiraHidden", mitMoiraHidden_v, LDAP_MOD_ADD);
2749           
2750           if(atoi(av[L_GROUP])) 
2751             {
2752               gidNumber_v[0] = av[L_GID];
2753               ADD_ATTR("gidNumber", gidNumber_v, LDAP_MOD_ADD);
2754             }
2755         }
2756
2757       ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
2758       ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
2759       ADD_ATTR("name", name_v, LDAP_MOD_ADD);
2760
2761       if (Exchange)
2762         {
2763           if(atoi(av[L_MAILLIST])) 
2764             {
2765               group_count = 0;
2766               group_base = NULL;
2767               
2768               sprintf(filter, "(&(objectClass=user)(cn=%s))", av[L_NAME]);
2769               attr_array[0] = "cn";
2770               attr_array[1] = NULL;
2771               
2772               if ((rc = linklist_build((LDAP *)call_args[0], call_args[1], 
2773                                        filter, attr_array, &group_base, 
2774                                        &group_count,
2775                                        LDAP_SCOPE_SUBTREE)) != 0)
2776                 {
2777                   com_err(whoami, 0, "Unable to process group %s : %s",
2778                           av[L_NAME], ldap_err2string(rc));
2779                   return(rc);
2780                 }
2781               
2782               if (group_count)
2783                 {
2784                   com_err(whoami, 0, "Object already exists with name %s",
2785                           av[L_NAME]);
2786                   MailDisabled++;
2787                 }
2788         
2789               linklist_free(group_base);
2790               group_base = NULL;
2791               group_count = 0;
2792             }
2793           
2794           if(atoi(av[L_MAILLIST]) && !MailDisabled && email_isvalid(mail)) 
2795             {
2796               mail_nickname_v[0] = mail_nickname;
2797               report_to_originator_v[0] = "TRUE";
2798
2799               ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_ADD);
2800               ADD_ATTR("reportToOriginator", report_to_originator_v, 
2801                        LDAP_MOD_ADD);
2802             }
2803         }
2804       else
2805         {
2806           if(atoi(av[L_MAILLIST]) && email_isvalid(contact_mail)) 
2807             {
2808               mail_v[0] = contact_mail;
2809               ADD_ATTR("mail", mail_v, LDAP_MOD_ADD);
2810
2811               if(!ActiveDirectory)
2812                 {
2813                   null_v[0] = "/dev/null";
2814                   ADD_ATTR("mailRoutingAddress", null_v, LDAP_MOD_ADD);
2815                 }
2816             }
2817         }
2818       
2819       if (strlen(av[L_DESC]) != 0)
2820         {
2821           desc_v[0] = av[L_DESC];
2822           ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
2823         }
2824       
2825       ADD_ATTR("groupType", groupTypeControl_v, LDAP_MOD_ADD);
2826
2827       if (strlen(av[L_ACE_NAME]) != 0)
2828         {
2829           sprintf(info, "The Administrator of this list is: %s", 
2830                   av[L_ACE_NAME]);
2831           info_v[0] = info;
2832           ADD_ATTR("info", info_v, LDAP_MOD_ADD);
2833         }
2834
2835       if (strlen(call_args[5]) != 0)
2836         {
2837           mitMoiraId_v[0] = call_args[5];
2838           ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_ADD);
2839         }
2840           
2841       mods[n] = NULL;
2842       
2843       rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
2844       
2845       for (i = 0; i < n; i++)
2846         free(mods[i]);
2847
2848       if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
2849         {
2850           com_err(whoami, 0, "Unable to create list %s in directory : %s",
2851                   av[L_NAME], ldap_err2string(rc));
2852           callback_rc = rc;
2853           return(rc);
2854         }
2855     }
2856
2857   if ((rc == LDAP_ALREADY_EXISTS) || (updateGroup))
2858     {
2859       rc = attribute_update((LDAP *)call_args[0], new_dn, av[L_DESC], 
2860                             "description", av[L_NAME]);
2861       sprintf(info, "The Administrator of this list is: %s", av[L_ACE_NAME]);
2862
2863       rc = attribute_update((LDAP *)call_args[0], new_dn, info, "info", 
2864                                 av[L_NAME]);
2865
2866       n = 0;
2867
2868       if (strlen(call_args[5]) != 0)
2869         {
2870           mitMoiraId_v[0] = call_args[5];
2871           ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
2872         }
2873
2874       if (!(atoi(av[L_ACTIVE])))
2875         {
2876           member_v[0] = NULL;
2877           ADD_ATTR("member", member_v, LDAP_MOD_REPLACE);
2878         }
2879    
2880       if (!ActiveDirectory) 
2881         {
2882           mitMoiraPublic_v[0] = av[L_PUBLIC];
2883           mitMoiraHidden_v[0] = av[L_HIDDEN];
2884           ADD_ATTR("mitMoiraPublic", mitMoiraPublic_v, LDAP_MOD_REPLACE);
2885           ADD_ATTR("mitMoiraHidden", mitMoiraHidden_v, LDAP_MOD_REPLACE);
2886
2887           if(atoi(av[L_GROUP])) 
2888             {
2889               gidNumber_v[0] = av[L_GID];
2890               ADD_ATTR("gidNumber", gidNumber_v, LDAP_MOD_REPLACE);
2891             }
2892           else
2893             {
2894               ADD_ATTR("gidNumber", gidNumber_v, LDAP_MOD_REPLACE);
2895             }
2896         }
2897
2898       if (Exchange)
2899         {
2900           if(atoi(av[L_MAILLIST])) 
2901             {
2902               group_count = 0;
2903               group_base = NULL;
2904               
2905               sprintf(filter, "(&(objectClass=user)(cn=%s))", av[L_NAME]);
2906               attr_array[0] = "cn";
2907               attr_array[1] = NULL;
2908               
2909               if ((rc = linklist_build((LDAP *)call_args[0], call_args[1], 
2910                                        filter, attr_array, &group_base, 
2911                                        &group_count,
2912                                        LDAP_SCOPE_SUBTREE)) != 0)
2913                 {
2914                   com_err(whoami, 0, "Unable to process group %s : %s",
2915                           av[L_NAME], ldap_err2string(rc));
2916                   return(rc);
2917                 }
2918               
2919               if (group_count)
2920                 {
2921                   com_err(whoami, 0, "Object already exists with name %s",
2922                           av[L_NAME]);
2923                   MailDisabled++;
2924                 }
2925               
2926               linklist_free(group_base);
2927               group_base = NULL;
2928               group_count = 0;
2929             }
2930
2931           if (atoi(av[L_MAILLIST]) && !MailDisabled && email_isvalid(mail)) 
2932             {
2933               mail_nickname_v[0] = mail_nickname;
2934               report_to_originator_v[0] = "TRUE";
2935
2936               ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_REPLACE);
2937               ADD_ATTR("reportToOriginator", report_to_originator_v, 
2938                        LDAP_MOD_REPLACE);
2939             }
2940           else 
2941             {
2942               mail_v[0] = NULL;
2943               mail_nickname_v[0] = NULL;
2944               proxy_address_v[0] = NULL;
2945               legacy_exchange_dn_v[0] = NULL;
2946               address_book_v[0] = NULL;
2947               report_to_originator_v[0] = NULL;
2948
2949               ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_REPLACE);
2950               ADD_ATTR("proxyAddresses", proxy_address_v, LDAP_MOD_REPLACE);
2951               ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
2952               ADD_ATTR("legacyExchangeDN", legacy_exchange_dn_v, 
2953                        LDAP_MOD_REPLACE);
2954               ADD_ATTR("showInAddressBook", address_book_v, LDAP_MOD_REPLACE);
2955               ADD_ATTR("reportToOriginator", report_to_originator_v, 
2956                        LDAP_MOD_REPLACE);
2957             }
2958         }
2959       else
2960         {
2961           if (atoi(av[L_MAILLIST]) && email_isvalid(contact_mail)) 
2962             {
2963               mail_v[0] = contact_mail;
2964               ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
2965
2966               if(!ActiveDirectory)
2967                 {
2968                   null_v[0] = "/dev/null";
2969                   ADD_ATTR("mailRoutingAddress", null_v, LDAP_MOD_REPLACE);
2970                 }
2971             }
2972           else
2973             {
2974               mail_v[0] = NULL;
2975               ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
2976
2977               if(!ActiveDirectory)
2978                 {
2979                   null_v[0] = NULL;
2980                   ADD_ATTR("mailRoutingAddress", null_v, LDAP_MOD_REPLACE);
2981                 }
2982             }
2983         }
2984    
2985       mods[n] = NULL;
2986       rc = LDAP_SUCCESS;
2987
2988       if (n != 0)
2989         {
2990           rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
2991
2992           for (i = 0; i < n; i++)
2993               free(mods[i]);
2994
2995           if (rc != LDAP_SUCCESS)
2996             {
2997               com_err(whoami, 0, "Unable to update list %s in directory : %s",
2998                       av[L_NAME], ldap_err2string(rc));
2999               callback_rc = rc;
3000               return(rc);
3001             }
3002         }
3003     }
3004
3005   ProcessGroupSecurity((LDAP *)call_args[0], call_args[1], av[L_NAME], 
3006                        atoi(av[L_HIDDEN]),  av[L_ACE_TYPE], av[L_ACE_NAME]);
3007
3008   return(LDAP_SUCCESS);
3009 }
3010
3011 int ProcessGroupSecurity(LDAP *ldap_handle, char *dn_path, 
3012                          char *TargetGroupName, int HiddenGroup, 
3013                          char *AceType, char *AceName)
3014 {
3015   char          filter_exp[1024];
3016   char          *attr_array[5];
3017   char          search_path[512];
3018   char          root_ou[128];
3019   char          TemplateDn[512];
3020   char          TemplateSamName[128];
3021   char          TargetDn[512];
3022   char          TargetSamName[128];
3023   char          AceSamAccountName[128];
3024   char          AceDn[256];
3025   unsigned char AceSid[128];
3026   unsigned char UserTemplateSid[128];
3027   char          acBERBuf[N_SD_BER_BYTES];
3028   char          GroupSecurityTemplate[256];
3029   char          hide_addres_lists[256];
3030   char          address_book[256];
3031   char          *hide_address_lists_v[] = {NULL, NULL};
3032   char          *address_book_v[] = {NULL, NULL};
3033   char          *owner_v[] = {NULL, NULL};
3034   int           AceSidCount;
3035   int           UserTemplateSidCount;
3036   int           group_count;
3037   int           n;
3038   int           i;
3039   int           rc;
3040   int           nVal;
3041   ULONG         dwInfo;
3042   int           array_count = 0;
3043   LDAPMod       *mods[20];
3044   LK_ENTRY      *group_base;
3045   LDAP_BERVAL   **ppsValues;
3046   LDAPControl sControl = {"1.2.840.113556.1.4.801",
3047                           { N_SD_BER_BYTES, acBERBuf },
3048                           TRUE
3049                          };
3050   LDAPControl *apsServerControls[] = {&sControl, NULL};
3051   LDAPMessage *psMsg;
3052
3053   dwInfo = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | 
3054     DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION;
3055   BEREncodeSecurityBits(dwInfo, acBERBuf);
3056
3057   sprintf(search_path, "%s,%s", group_ou_root, dn_path);
3058   sprintf(filter_exp, "(sAMAccountName=%s%s)", TargetGroupName, group_suffix);
3059   attr_array[0] = "sAMAccountName";
3060   attr_array[1] = NULL;
3061   group_count = 0;
3062   group_base = NULL;
3063
3064   if ((rc = linklist_build(ldap_handle, search_path, filter_exp, attr_array, 
3065                            &group_base, &group_count, 
3066                            LDAP_SCOPE_SUBTREE) != 0))
3067     return(1);
3068
3069   if (group_count != 1)
3070     {
3071       linklist_free(group_base);
3072       return(1);
3073     }
3074
3075   strcpy(TargetDn, group_base->dn);
3076   strcpy(TargetSamName, group_base->value);
3077   linklist_free(group_base);
3078   group_base = NULL;
3079   group_count = 0;
3080
3081   UserTemplateSidCount = 0;
3082   memset(UserTemplateSid, '\0', sizeof(UserTemplateSid));
3083   memset(AceSamAccountName, '\0', sizeof(AceSamAccountName));
3084   memset(AceSid, '\0', sizeof(AceSid));
3085   AceSidCount = 0;
3086   group_base = NULL;
3087   group_count = 0;
3088
3089   if (strlen(AceName) != 0)
3090     {
3091       if (!strcmp(AceType, "LIST"))
3092         {
3093           sprintf(AceSamAccountName, "%s%s", AceName, group_suffix);
3094           strcpy(root_ou, group_ou_root);
3095         }
3096       else if (!strcmp(AceType, "USER"))
3097         {
3098           sprintf(AceSamAccountName, "%s", AceName);
3099           strcpy(root_ou, user_ou);
3100         }
3101
3102       if (ActiveDirectory)
3103         {
3104           if (strlen(AceSamAccountName) != 0)
3105             {
3106               sprintf(search_path, "%s", dn_path);
3107               sprintf(filter_exp, "(sAMAccountName=%s)", AceSamAccountName);
3108               attr_array[0] = "objectSid";
3109               attr_array[1] = NULL;
3110               group_count = 0;
3111               group_base = NULL;
3112               
3113               if ((rc = linklist_build(ldap_handle, search_path, filter_exp, 
3114                                        attr_array, &group_base, &group_count, 
3115                                        LDAP_SCOPE_SUBTREE) != 0))
3116                 return(1);
3117               if (group_count == 1)
3118                 {
3119                   strcpy(AceDn, group_base->dn);
3120                   AceSidCount = group_base->length;
3121                   memcpy(AceSid, group_base->value, AceSidCount);
3122                 }
3123               linklist_free(group_base);
3124               group_base = NULL;
3125               group_count = 0;
3126             }
3127         }
3128       else
3129         {
3130           if (strlen(AceSamAccountName) != 0)
3131             {
3132               sprintf(search_path, "%s", dn_path);
3133               sprintf(filter_exp, "(sAMAccountName=%s)", AceSamAccountName);
3134               attr_array[0] = "samAccountName";
3135               attr_array[1] = NULL;
3136               group_count = 0;
3137               group_base = NULL;
3138               
3139               if ((rc = linklist_build(ldap_handle, search_path, filter_exp, 
3140                                        attr_array, &group_base, &group_count, 
3141                                        LDAP_SCOPE_SUBTREE) != 0))
3142                 return(1);
3143               if (group_count == 1)
3144                 {
3145                   strcpy(AceDn, group_base->dn);
3146                 }
3147               linklist_free(group_base);
3148               group_base = NULL;
3149               group_count = 0;
3150             }
3151         }
3152     }
3153
3154   if (!ActiveDirectory) 
3155     {
3156       if (strlen(AceDn) != 0) 
3157         {
3158           owner_v[0] = strdup(AceDn);
3159           n = 0;
3160           ADD_ATTR("owner", owner_v, LDAP_MOD_REPLACE);
3161
3162           mods[n] = NULL;
3163
3164           rc = ldap_modify_s(ldap_handle, TargetDn, mods);
3165           
3166           for (i = 0; i < n; i++)
3167             free(mods[i]);
3168
3169           if (rc != LDAP_SUCCESS)
3170             com_err(whoami, 0, "Unable to set owner for group %s : %s",
3171               TargetGroupName, ldap_err2string(rc));
3172         }
3173
3174       return(rc);
3175     }
3176   
3177   if (AceSidCount == 0)
3178     {
3179       com_err(whoami, 0, "Group %s: Administrator: %s, Type: %s - does not "
3180               "have a directory SID.", TargetGroupName, AceName, AceType);
3181       com_err(whoami, 0, "   Non-admin security group template will be used.");
3182     }
3183   else
3184     {
3185       sprintf(search_path, "%s,%s", security_template_ou, dn_path);
3186       sprintf(filter_exp, "(sAMAccountName=%s)", "UserTemplate.u");
3187       attr_array[0] = "objectSid";
3188       attr_array[1] = NULL;
3189
3190       group_count = 0;
3191       group_base = NULL;
3192
3193       if ((rc = linklist_build(ldap_handle, search_path, filter_exp, 
3194                                attr_array, &group_base, &group_count, 
3195                                LDAP_SCOPE_SUBTREE) != 0))
3196         return(1);
3197
3198       if ((rc != 0) || (group_count != 1))
3199         {
3200           com_err(whoami, 0, "Unable to process user security template: %s", 
3201                   "UserTemplate");
3202           AceSidCount = 0;
3203         }
3204       else
3205         {
3206           UserTemplateSidCount = group_base->length;
3207           memcpy(UserTemplateSid, group_base->value, UserTemplateSidCount);
3208         }
3209       linklist_free(group_base);
3210       group_base = NULL;
3211       group_count = 0;
3212     }
3213
3214   if (HiddenGroup)
3215     {
3216       if (AceSidCount == 0)
3217         {
3218           strcpy(GroupSecurityTemplate, HIDDEN_GROUP);
3219           sprintf(filter_exp, "(sAMAccountName=%s)", HIDDEN_GROUP);
3220         }
3221       else
3222         {
3223           strcpy(GroupSecurityTemplate, HIDDEN_GROUP_WITH_ADMIN);
3224           sprintf(filter_exp, "(sAMAccountName=%s)", HIDDEN_GROUP_WITH_ADMIN);
3225         }
3226     }
3227   else
3228     {
3229       if (AceSidCount == 0)
3230         {
3231           strcpy(GroupSecurityTemplate, NOT_HIDDEN_GROUP);
3232           sprintf(filter_exp, "(sAMAccountName=%s)", NOT_HIDDEN_GROUP);
3233         }
3234       else
3235         {
3236           strcpy(GroupSecurityTemplate, NOT_HIDDEN_GROUP_WITH_ADMIN);
3237           sprintf(filter_exp, "(sAMAccountName=%s)", 
3238                   NOT_HIDDEN_GROUP_WITH_ADMIN);
3239         }
3240     }
3241
3242   sprintf(search_path, "%s,%s", security_template_ou, dn_path);
3243   attr_array[0] = "sAMAccountName";
3244   attr_array[1] = NULL;
3245   group_count = 0;
3246   group_base = NULL;
3247
3248   if ((rc = linklist_build(ldap_handle, search_path, filter_exp, attr_array, 
3249                            &group_base, &group_count, 
3250                            LDAP_SCOPE_SUBTREE) != 0))
3251     return(1);
3252
3253   if (group_count != 1)
3254     {
3255       linklist_free(group_base);
3256       com_err(whoami, 0, "Unable to process group security template: %s - "
3257               "security not set", GroupSecurityTemplate);
3258       return(1);
3259     }
3260
3261   strcpy(TemplateDn, group_base->dn);
3262   strcpy(TemplateSamName, group_base->value);
3263   linklist_free(group_base);
3264   group_base = NULL;
3265   group_count = 0;
3266   
3267   sprintf(filter_exp, "(sAMAccountName=%s)", TemplateSamName);
3268   rc = ldap_search_ext_s(ldap_handle,
3269                          TemplateDn,
3270                          LDAP_SCOPE_SUBTREE,
3271                          filter_exp,
3272                          NULL,
3273                          0,
3274                          apsServerControls,
3275                          NULL,
3276                          NULL,
3277                          0,
3278                          &psMsg);
3279
3280   if ((psMsg = ldap_first_entry(ldap_handle, psMsg)) == NULL)
3281     {
3282       com_err(whoami, 0, "Unable to find group security template: %s - "
3283               "security not set", GroupSecurityTemplate);
3284       return(1);
3285     }
3286
3287   ppsValues = ldap_get_values_len(ldap_handle, psMsg, "ntSecurityDescriptor");
3288
3289   if (ppsValues == NULL)
3290     {
3291       com_err(whoami, 0, "Unable to find group security descriptor for group "
3292               "%s - security not set", GroupSecurityTemplate);
3293       return(1);
3294     }
3295   
3296   if (AceSidCount != 0)
3297     {
3298       for (nVal = 0; ppsValues[nVal] != NULL; nVal++)
3299         {
3300           for (i = 0; 
3301                i < (int)(ppsValues[nVal]->bv_len - UserTemplateSidCount); i++)
3302             {
3303               if (!memcmp(&ppsValues[nVal]->bv_val[i], UserTemplateSid, 
3304                           UserTemplateSidCount))
3305                 {
3306                   memcpy(&ppsValues[nVal]->bv_val[i], AceSid, AceSidCount);
3307                   break;
3308                 }
3309             }
3310         }
3311     }
3312
3313   n = 0;
3314   ADD_ATTR("ntSecurityDescriptor", (char **)ppsValues, 
3315            LDAP_MOD_REPLACE | LDAP_MOD_BVALUES);
3316
3317   if (Exchange)
3318     {
3319       if(HiddenGroup) 
3320         {
3321           hide_address_lists_v[0] = "TRUE";
3322           address_book_v[0] = NULL;
3323           ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v, 
3324                    LDAP_MOD_REPLACE);
3325           ADD_ATTR("showInAddressBook", address_book_v, LDAP_MOD_REPLACE);
3326         } else {
3327           hide_address_lists_v[0] = NULL;
3328           ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v, 
3329                    LDAP_MOD_REPLACE);
3330         }
3331     }
3332
3333   mods[n] = NULL;
3334
3335   rc = ldap_modify_s(ldap_handle, TargetDn, mods);
3336
3337   for (i = 0; i < n; i++)
3338     free(mods[i]);
3339
3340   ldap_value_free_len(ppsValues);
3341   ldap_msgfree(psMsg);
3342
3343   if (rc != LDAP_SUCCESS)
3344     {
3345       com_err(whoami, 0, "Unable to set security settings for group %s : %s",
3346               TargetGroupName, ldap_err2string(rc));
3347
3348       if (AceSidCount != 0)
3349         {
3350           com_err(whoami, 0, 
3351                   "Trying to set security for group %s without admin.",
3352                   TargetGroupName);
3353
3354           if (rc = ProcessGroupSecurity(ldap_handle, dn_path, TargetGroupName, 
3355                                         HiddenGroup, "", ""))
3356             {
3357               com_err(whoami, 0, "Unable to set security for group %s.",
3358                       TargetGroupName);
3359               return(rc);
3360             }
3361         }
3362       return(rc);
3363     }
3364
3365   return(rc);
3366 }
3367
3368 int group_delete(LDAP *ldap_handle, char *dn_path, char *group_name, 
3369                  char *group_membership, char *MoiraId)
3370 {
3371   LK_ENTRY  *group_base;
3372   char      temp[512];
3373   char      filter[128];
3374   int       group_count;
3375   int       rc;
3376
3377   if (!check_string(group_name))
3378     {
3379       com_err(whoami, 0, 
3380               "Unable to process invalid LDAP list name %s", group_name);
3381       return(AD_INVALID_NAME);
3382     }
3383
3384   memset(filter, '\0', sizeof(filter));
3385   group_count = 0;
3386   group_base = NULL;
3387   sprintf(temp, "%s,%s", group_ou_root, dn_path);
3388
3389   if (rc = ad_get_group(ldap_handle, temp, group_name, 
3390                         group_membership, MoiraId, 
3391                         "samAccountName", &group_base, 
3392                         &group_count, filter))
3393     return(rc);
3394
3395   if (group_count == 1)
3396     {
3397       if ((rc = ldap_delete_s(ldap_handle, group_base->dn)) != LDAP_SUCCESS)
3398         {
3399           linklist_free(group_base);
3400           com_err(whoami, 0, "Unable to delete list %s from directory : %s",
3401                   group_name, ldap_err2string(rc));
3402           return(rc);
3403         }
3404       linklist_free(group_base);
3405     }
3406   else
3407     {
3408       linklist_free(group_base);
3409       com_err(whoami, 0, "Unable to find list %s in directory.", group_name);
3410       return(AD_NO_GROUPS_FOUND);
3411     }
3412   
3413   return(0);
3414 }
3415
3416 int BEREncodeSecurityBits(ULONG uBits, char *pBuffer)
3417 {
3418     *pBuffer++ = 0x30;
3419     *pBuffer++ = 0x03;
3420     *pBuffer++ = 0x02;
3421     *pBuffer++ = 0x00;
3422     return(N_SD_BER_BYTES);
3423 }
3424
3425 int process_lists(int ac, char **av, void *ptr)
3426 {
3427   int   rc;
3428   int   security_flag;
3429   char  group_ou[256];
3430   char  group_membership[2];
3431   char  **call_args;
3432
3433   call_args = ptr;
3434
3435   security_flag = 0;
3436   memset(group_ou, '\0', sizeof(group_ou));
3437   memset(group_membership, '\0', sizeof(group_membership));
3438   get_group_membership(group_membership, group_ou, &security_flag, av);
3439   rc = populate_group((LDAP *)call_args[0], (char *)call_args[1], 
3440                       av[L_NAME], group_ou, group_membership, 
3441                       security_flag, "");
3442
3443   return(0);
3444 }
3445
3446 int member_list_build(int ac, char **av, void *ptr)
3447 {
3448   LK_ENTRY  *linklist;
3449   char      temp[1024];
3450   char      **call_args;
3451   char      *s;
3452   call_args = ptr;
3453
3454   strcpy(temp, av[ACE_NAME]);
3455   StringTrim(temp);
3456   
3457   if (!check_string(temp))
3458     return(0);
3459
3460   if (!strcmp(av[ACE_TYPE], "USER"))
3461     {
3462       if (!((int)call_args[3] & MOIRA_USERS))
3463         return(0);
3464     }
3465   else if (!strcmp(av[ACE_TYPE], "STRING"))
3466     {
3467       if (Exchange)
3468         {
3469           if((s = strchr(temp, '@')) == (char *) NULL) 
3470             {
3471               strcat(temp, "@mit.edu");
3472             }
3473           
3474           if(!strncasecmp(&temp[strlen(temp) - 6], ".LOCAL", 6))
3475             {
3476               s = strrchr(temp, '.');
3477               *s = '\0';
3478               strcat(s, ".mit.edu");
3479             }
3480         }
3481
3482       if (!((int)call_args[3] & MOIRA_STRINGS))
3483         return(0);
3484         
3485       if (contact_create((LDAP *)call_args[0], call_args[1], temp, contact_ou))
3486         return(0);
3487     }
3488   else if (!strcmp(av[ACE_TYPE], "LIST"))
3489     {
3490       if (!((int)call_args[3] & MOIRA_LISTS))
3491         return(0);
3492     }
3493   else if (!strcmp(av[ACE_TYPE], "KERBEROS"))
3494     {
3495       if (!((int)call_args[3] & MOIRA_KERBEROS))
3496         return(0);
3497
3498       if (contact_create((LDAP *)call_args[0], call_args[1], temp, 
3499                          kerberos_ou))
3500         return(0);
3501
3502     }
3503   else if (!strcmp(av[ACE_TYPE], "MACHINE"))
3504     {
3505       if (!((int)call_args[3] & MOIRA_MACHINE))
3506         return(0);
3507     }
3508   else
3509     return(0);
3510
3511   linklist = member_base;
3512
3513   while (linklist)
3514     {
3515     if (!strcasecmp(temp, linklist->member) &&
3516         !strcasecmp(av[ACE_TYPE], linklist->type))
3517       return(0);
3518
3519     linklist = linklist->next;
3520     }
3521
3522   linklist = calloc(1, sizeof(LK_ENTRY));
3523   linklist->op = 1;
3524   linklist->dn = NULL;
3525   linklist->list = calloc(1, strlen(call_args[2]) + 1);
3526   strcpy(linklist->list, call_args[2]);
3527   linklist->type = calloc(1, strlen(av[ACE_TYPE]) + 1);
3528   strcpy(linklist->type, av[ACE_TYPE]);
3529   linklist->member = calloc(1, strlen(temp) + 1);
3530   strcpy(linklist->member, temp);
3531   linklist->next = member_base;
3532   member_base = linklist;
3533
3534   return(0);
3535 }
3536
3537 int member_remove(LDAP *ldap_handle, char *dn_path, char *group_name, 
3538                   char *group_ou, char *group_membership, char *user_name,
3539                   char *UserOu, char *MoiraId)
3540 {
3541   char        distinguished_name[1024];
3542   char        *modvalues[2];
3543   char        temp[256];
3544   char        filter[128];
3545   char        *attr_array[3];
3546   int         group_count;
3547   int         i;
3548   int         n;
3549   LDAPMod     *mods[20];
3550   LK_ENTRY    *group_base;
3551   ULONG       rc;
3552   char        *s;
3553
3554   if (!check_string(group_name))
3555     return(AD_INVALID_NAME);
3556
3557   memset(filter, '\0', sizeof(filter));
3558   group_base = NULL;
3559   group_count = 0;
3560
3561   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
3562                         group_membership, MoiraId, 
3563                         "samAccountName", &group_base, 
3564                         &group_count, filter))
3565     return(rc);
3566
3567   if (group_count != 1)
3568     {
3569       com_err(whoami, 0, "Unable to find list %s in directory",
3570               group_name);
3571       linklist_free(group_base);
3572       group_base = NULL;
3573       group_count = 0;
3574       goto cleanup;
3575     }
3576
3577   strcpy(distinguished_name, group_base->dn);
3578   linklist_free(group_base);
3579   group_base = NULL;
3580   group_count = 0;
3581
3582   if(ActiveDirectory)
3583     {
3584       sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
3585     }
3586   else
3587     {
3588       if(!strcmp(UserOu, user_ou))
3589         sprintf(temp, "uid=%s,%s,%s", user_name, UserOu, dn_path);
3590       else
3591         sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
3592     }
3593
3594   modvalues[0] = temp;
3595   modvalues[1] = NULL;
3596
3597   n = 0;
3598   ADD_ATTR("member", modvalues, LDAP_MOD_DELETE);
3599   mods[n] = NULL;
3600   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
3601
3602   for (i = 0; i < n; i++)
3603     free(mods[i]);
3604
3605   if (rc == LDAP_UNWILLING_TO_PERFORM)
3606     rc = LDAP_SUCCESS;
3607
3608   if (rc != LDAP_SUCCESS)
3609     {
3610       com_err(whoami, 0, "Unable to modify list %s members : %s",
3611               group_name, ldap_err2string(rc));
3612       goto cleanup;
3613     }
3614
3615   if ((!strcmp(UserOu, contact_ou)) || (!strcmp(UserOu, kerberos_ou))) 
3616     {
3617       if (Exchange)
3618         {
3619           if(!strcmp(UserOu, contact_ou) && 
3620              ((s = strstr(user_name, "@mit.edu")) != (char *) NULL))
3621             {
3622               memset(temp, '\0', sizeof(temp));
3623               strcpy(temp, user_name);
3624               s = strchr(temp, '@');
3625               *s = '\0';
3626               
3627               sprintf(filter, "(&(objectClass=user)(mailNickName=%s))", temp);
3628           
3629               if ((rc = linklist_build(ldap_handle, dn_path, filter, NULL,
3630                                        &group_base, &group_count, 
3631                                        LDAP_SCOPE_SUBTREE) != 0))
3632                 return(rc);       
3633               
3634               if(group_count)
3635                 goto cleanup;
3636               
3637               linklist_free(group_base);
3638               group_base = NULL;
3639               group_count = 0;
3640             }
3641           
3642           sprintf(filter, "(distinguishedName=%s)", temp);
3643           attr_array[0] = "memberOf";
3644           attr_array[1] = NULL;
3645           
3646           if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array,
3647                                    &group_base, &group_count, 
3648                                    LDAP_SCOPE_SUBTREE) != 0))
3649             return(rc);
3650           
3651
3652           if(!group_count) 
3653             {
3654               com_err(whoami, 0, "Removing unreferenced object %s", temp);
3655           
3656               if ((rc = ldap_delete_s(ldap_handle, temp)) != 0) 
3657                 return(rc);
3658             }
3659         }
3660     }
3661
3662  cleanup:
3663   return(rc);
3664 }
3665
3666 int member_add(LDAP *ldap_handle, char *dn_path, char *group_name, 
3667                char *group_ou, char *group_membership, char *user_name, 
3668                char *UserOu, char *MoiraId)
3669 {
3670   char        distinguished_name[1024];
3671   char        *modvalues[2];
3672   char        temp[256];
3673   char        filter[128];
3674   int         group_count;
3675   int         n;
3676   int         i;
3677   LDAPMod     *mods[20];
3678   LK_ENTRY    *group_base;
3679   ULONG       rc;
3680
3681   if (!check_string(group_name))
3682     return(AD_INVALID_NAME);
3683
3684   rc = 0;
3685   memset(filter, '\0', sizeof(filter));
3686   group_base = NULL;
3687   group_count = 0;
3688
3689   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
3690                         group_membership, MoiraId, 
3691                         "samAccountName", &group_base, 
3692                         &group_count, filter))
3693     return(rc);
3694
3695   if (group_count != 1)
3696     {
3697       linklist_free(group_base);
3698       group_base = NULL;
3699       group_count = 0;
3700       com_err(whoami, 0, "Unable to find list %s %d in directory",
3701               group_name, group_count);
3702       return(AD_MULTIPLE_GROUPS_FOUND);
3703     }
3704
3705   strcpy(distinguished_name, group_base->dn);
3706   linklist_free(group_base);
3707   group_base = NULL;
3708   group_count = 0;
3709
3710   if(ActiveDirectory)
3711     {
3712       sprintf(temp, "CN=%s,%s,%s", user_name, UserOu, dn_path);
3713     }
3714   else 
3715     {
3716       if(!strcmp(UserOu, user_ou))
3717         sprintf(temp, "uid=%s,%s,%s", user_name, UserOu, dn_path);
3718       else
3719         sprintf(temp, "cn=%s,%s,%s", user_name, UserOu, dn_path);
3720     }
3721
3722   modvalues[0] = temp;
3723   modvalues[1] = NULL;
3724
3725   n = 0;
3726   ADD_ATTR("member", modvalues, LDAP_MOD_ADD);
3727   mods[n] = NULL;
3728   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
3729
3730   if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
3731     rc = LDAP_SUCCESS;
3732
3733   if ((!strcmp(UserOu, contact_ou)) || (!strcmp(UserOu, kerberos_ou)))
3734     {
3735       if (rc == LDAP_UNWILLING_TO_PERFORM)
3736         rc = LDAP_SUCCESS;
3737     }
3738
3739   for (i = 0; i < n; i++)
3740     free(mods[i]);
3741
3742   if (rc != LDAP_SUCCESS)
3743     {
3744       com_err(whoami, 0, "Unable to add %s to list %s as a member : %s",
3745               user_name, group_name, ldap_err2string(rc));
3746     }
3747
3748   return(rc);
3749 }
3750
3751 int contact_remove_email(LDAP *ld, char *bind_path,
3752                          LK_ENTRY **linklist_base, int linklist_current)
3753 {
3754   LK_ENTRY  *gPtr;
3755   int       rc;
3756   char      *mail_v[] = {NULL, NULL};
3757   LDAPMod   *mods[20];
3758   int n;
3759   int i;
3760
3761   mail_v[0] = NULL;
3762
3763   n = 0;
3764   ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
3765   ADD_ATTR("mailNickName", mail_v, LDAP_MOD_REPLACE);
3766   ADD_ATTR("proxyAddresses", mail_v, LDAP_MOD_REPLACE);
3767   ADD_ATTR("targetAddress", mail_v, LDAP_MOD_REPLACE);
3768   mods[n] = NULL;
3769
3770   gPtr = (*linklist_base);
3771   
3772   while(gPtr) {
3773     rc = ldap_modify_s(ld, gPtr->dn, mods);
3774     
3775     if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
3776       {
3777         com_err(whoami, 0, "Unable to modify contact %s in directory : %s",
3778                 gPtr->dn, ldap_err2string(rc));
3779         return(rc);
3780       }
3781
3782     gPtr = gPtr->next;
3783   }
3784
3785   for (i = 0; i < n; i++)
3786     free(mods[i]);
3787   
3788     return(rc);
3789 }
3790
3791 int contact_create(LDAP *ld, char *bind_path, char *user, char *group_ou)
3792 {
3793   LDAPMod *mods[20];
3794   LK_ENTRY  *group_base;
3795   int  group_count;
3796   char new_dn[256];
3797   char cn_user_name[256];
3798   char contact_name[256];
3799   char mail_nickname[256];
3800   char proxy_address_internal[256];
3801   char proxy_address_external[256];
3802   char target_address[256];
3803   char internal_contact_name[256];
3804   char filter[128];
3805   char mail[256];
3806   char principal[256];
3807   char mit_address_book[256];
3808   char default_address_book[256];
3809   char contact_address_book[256];
3810   char uid[256];
3811   char *email_v[] = {NULL, NULL};
3812   char *cn_v[] = {NULL, NULL};
3813   char *contact_v[] = {NULL, NULL};
3814   char *uid_v[] = {NULL, NULL};
3815   char *mail_nickname_v[] = {NULL, NULL};
3816   char *proxy_address_internal_v[] = {NULL, NULL};
3817   char *proxy_address_external_v[] = {NULL, NULL};
3818   char *target_address_v[] = {NULL, NULL};
3819   char *mit_address_book_v[] = {NULL, NULL};
3820   char *default_address_book_v[] = {NULL, NULL};
3821   char *contact_address_book_v[] = {NULL, NULL};
3822   char *hide_address_lists_v[] = {NULL, NULL};
3823   char *attr_array[3];
3824   char *objectClass_v[] = {"top", "person", 
3825                            "organizationalPerson", 
3826                            "contact", NULL};
3827   char *objectClass_ldap_v[] = {"top", "person", "microsoftComTop", 
3828                                 "inetOrgPerson", "organizationalPerson",
3829                                 "contact", "mailRecipient", "eduPerson",
3830                                 NULL};
3831   char *name_v[] = {NULL, NULL};
3832   char *desc_v[] = {NULL, NULL};
3833   char *s;
3834   int  n;
3835   int  rc;
3836   int  i;
3837   char temp[256];
3838   char *c;
3839   char *mail_routing_v[] = {NULL, NULL};
3840   char *principal_v[] = {NULL, NULL};
3841
3842   if (!check_string(user))
3843     {
3844       com_err(whoami, 0, "Unable to process invalid LDAP name %s", user);
3845       return(AD_INVALID_NAME);
3846     }
3847
3848   strcpy(mail, user);
3849   strcpy(contact_name, mail);
3850   strcpy(internal_contact_name, mail);
3851   
3852   if((s = strchr(internal_contact_name, '@')) != NULL) {
3853     *s = '?';
3854   }
3855
3856   sprintf(cn_user_name,"CN=%s,%s,%s", escape_string(contact_name), group_ou, 
3857           bind_path);
3858
3859   sprintf(target_address, "SMTP:%s", contact_name);
3860   sprintf(proxy_address_external, "SMTP:%s", contact_name);
3861   sprintf(mail_nickname, "%s", internal_contact_name);
3862  
3863   cn_v[0] = cn_user_name;
3864   contact_v[0] = contact_name;
3865   uid_v[0] = uid;
3866   name_v[0] = user;
3867   desc_v[0] = "Auto account created by Moira";
3868   email_v[0] = mail;
3869   proxy_address_internal_v[0] = proxy_address_internal;
3870   proxy_address_external_v[0] = proxy_address_external;
3871   mail_nickname_v[0] = mail_nickname;
3872   target_address_v[0] = target_address;
3873   mit_address_book_v[0] = mit_address_book;
3874   default_address_book_v[0] = default_address_book;
3875   contact_address_book_v[0] = contact_address_book;
3876   strcpy(new_dn, cn_user_name);
3877   n = 0;
3878
3879   ADD_ATTR("cn", contact_v, LDAP_MOD_ADD);
3880
3881   if(!ActiveDirectory)
3882     {
3883       if(!strcmp(group_ou, contact_ou))
3884         sprintf(uid, "%s%s", contact_name, "_strings");
3885       
3886       if(!strcmp(group_ou, kerberos_ou))
3887         sprintf(uid, "%s%s", contact_name, "_kerberos");
3888
3889       uid_v[0] = uid;
3890
3891       ADD_ATTR("sn", contact_v, LDAP_MOD_ADD);
3892       ADD_ATTR("uid", uid_v, LDAP_MOD_ADD);
3893     }
3894
3895   if(ActiveDirectory)
3896     {
3897       ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
3898     }
3899   else
3900     {
3901       ADD_ATTR("objectClass", objectClass_ldap_v, LDAP_MOD_ADD);
3902     }
3903
3904   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
3905   ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
3906   ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
3907
3908   if (Exchange)
3909     {
3910       if (!strcmp(group_ou, contact_ou) && email_isvalid(mail))
3911         {
3912           group_count = 0;
3913           group_base = NULL;
3914           
3915           sprintf(filter, "(&(objectClass=user)(cn=%s))", mail);
3916           attr_array[0] = "cn";
3917           attr_array[1] = NULL;
3918
3919           if ((rc = linklist_build(ld, bind_path, filter, attr_array,
3920                                    &group_base, &group_count, 
3921                                    LDAP_SCOPE_SUBTREE)) != 0) 
3922             {
3923               com_err(whoami, 0, "Unable to process contact %s : %s", 
3924                       user, ldap_err2string(rc));
3925               return(rc);
3926             }
3927       
3928           if (group_count) 
3929             {
3930               com_err(whoami, 0, "Object already exists with name %s",
3931                       user);
3932               return(1);
3933             }
3934
3935           linklist_free(group_base);
3936           group_base = NULL;
3937           group_count = 0;
3938       
3939           sprintf(filter, "(&(objectClass=group)(cn=%s))", mail);
3940           attr_array[0] = "cn";
3941           attr_array[1] = NULL;
3942
3943           if ((rc = linklist_build(ld, bind_path, filter, attr_array,
3944                                    &group_base, &group_count, 
3945                                    LDAP_SCOPE_SUBTREE)) != 0) 
3946             {
3947               com_err(whoami, 0, "Unable to process contact %s : %s", 
3948                       user, ldap_err2string(rc));
3949               return(rc);
3950             }
3951           
3952           if (group_count) 
3953             {
3954               com_err(whoami, 0, "Object already exists with name %s",
3955                       user);
3956               return(1);
3957             }
3958   
3959           linklist_free(group_base);
3960           group_count = 0;
3961           group_base = NULL;
3962           
3963           sprintf(filter, "(&(objectClass=user)(mail=%s))", mail);
3964           attr_array[0] = "cn";
3965           attr_array[1] = NULL;
3966
3967           if ((rc = linklist_build(ld, bind_path, filter, attr_array,
3968                                    &group_base, &group_count, 
3969                                    LDAP_SCOPE_SUBTREE)) != 0) 
3970             {
3971               com_err(whoami, 0, "Unable to process contact %s : %s", 
3972                       user, ldap_err2string(rc));
3973               return(rc);
3974             }
3975           
3976           if (group_count) 
3977             {
3978               com_err(whoami, 0, "Object already exists with name %s",
3979                       user);
3980               return(1);
3981             }
3982
3983           linklist_free(group_base);
3984           group_base = NULL;
3985           group_count = 0;
3986
3987           sprintf(filter, "(&(objectClass=group)(mail=%s))", mail);
3988           attr_array[0] = "cn";
3989           attr_array[1] = NULL;
3990
3991           if ((rc = linklist_build(ld, bind_path, filter, attr_array,
3992                                    &group_base, &group_count, 
3993                                    LDAP_SCOPE_SUBTREE)) != 0) 
3994             {
3995               com_err(whoami, 0, "Unable to process contact %s : %s", 
3996                       user, ldap_err2string(rc));
3997               return(rc);
3998             }
3999       
4000           if (group_count) 
4001             {
4002               com_err(whoami, 0, "Object already exists with name %s",
4003                       user);
4004               return(1);
4005             }
4006           
4007           linklist_free(group_base);
4008           group_base = NULL;
4009           group_count = 0;
4010           
4011           ADD_ATTR("mail", email_v, LDAP_MOD_ADD);
4012           ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_ADD);
4013           ADD_ATTR("proxyAddresses", proxy_address_external_v, LDAP_MOD_ADD);
4014           ADD_ATTR("targetAddress", target_address_v, LDAP_MOD_ADD);
4015           
4016           hide_address_lists_v[0] = "TRUE";
4017           ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
4018                    LDAP_MOD_ADD);
4019         }
4020     }
4021
4022   if(!ActiveDirectory) 
4023     {
4024       if((c = strchr(mail, '@')) == NULL)
4025           sprintf(temp, "%s@mit.edu", mail);
4026       else
4027           sprintf(temp, "%s", mail);
4028
4029       mail_routing_v[0] = temp;
4030       email_v[0] = temp;
4031       principal_v[0] = principal;
4032
4033       if(!strcmp(group_ou, contact_ou))
4034         {
4035           ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
4036           ADD_ATTR("eduPersonPrincipalName", mail_routing_v, LDAP_MOD_ADD);
4037         }
4038     }
4039
4040   mods[n] = NULL;
4041
4042   rc = ldap_add_ext_s(ld, new_dn, mods, NULL, NULL);
4043
4044   for (i = 0; i < n; i++)
4045     free(mods[i]);
4046   
4047   if (Exchange)
4048     {
4049       if ((rc != LDAP_SUCCESS) && (rc == LDAP_ALREADY_EXISTS) &&
4050           !strcmp(group_ou, contact_ou) && email_isvalid(mail))
4051         {
4052           n = 0;
4053           
4054           ADD_ATTR("mail", email_v, LDAP_MOD_REPLACE);
4055           ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_REPLACE);
4056           ADD_ATTR("proxyAddresses", proxy_address_external_v, 
4057                    LDAP_MOD_REPLACE);
4058           ADD_ATTR("targetAddress", target_address_v, LDAP_MOD_REPLACE);
4059
4060           hide_address_lists_v[0] = "TRUE";
4061           ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
4062                    LDAP_MOD_REPLACE);
4063     
4064           mods[n] = NULL;
4065           rc = ldap_modify_s(ld, new_dn, mods);
4066       
4067           if (rc) 
4068             {
4069               com_err(whoami, 0, "Unable to update contact %s", mail);
4070             }
4071       
4072           for (i = 0; i < n; i++)
4073             free(mods[i]);
4074         }
4075     }
4076
4077   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
4078     {
4079       com_err(whoami, 0, "Unable to create contact %s : %s",
4080               user, ldap_err2string(rc));
4081       return(rc);
4082     }
4083
4084   return(0);
4085 }
4086
4087 int user_update(LDAP *ldap_handle, char *dn_path, char *user_name,
4088                 char *Uid, char *MitId, char *MoiraId, int State,
4089                 char *WinHomeDir, char *WinProfileDir, char *first,
4090                 char *middle, char *last, char *shell, char *class)
4091 {
4092   LDAPMod   *mods[20];
4093   LK_ENTRY  *group_base;
4094   int  group_count;
4095   char distinguished_name[512];
4096   char displayName[256];
4097   char *mitMoiraId_v[] = {NULL, NULL};
4098   char *mitMoiraClass_v[] = {NULL, NULL};
4099   char *mitMoiraStatus_v[] = {NULL, NULL};
4100   char *uid_v[] = {NULL, NULL};
4101   char *mitid_v[] = {NULL, NULL};
4102   char *homedir_v[] = {NULL, NULL};
4103   char *winProfile_v[] = {NULL, NULL};
4104   char *drives_v[] = {NULL, NULL};
4105   char *userAccountControl_v[] = {NULL, NULL};
4106   char *alt_recipient_v[] = {NULL, NULL};
4107   char *hide_address_lists_v[] = {NULL, NULL};
4108   char *mail_v[] = {NULL, NULL};
4109   char *gid_v[] = {NULL, NULL};
4110   char *loginshell_v[] = {NULL, NULL};
4111   char *principal_v[] = {NULL, NULL};
4112   char userAccountControlStr[80];
4113   int  n;
4114   int  rc;
4115   int  i;
4116   int  OldUseSFU30;
4117   u_int userAccountControl = UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD | 
4118     UF_PASSWD_CANT_CHANGE;
4119   char filter[128];
4120   char *attr_array[3];
4121   char temp[1024];
4122   char mail[256];
4123   char contact_mail[256];
4124   char filter_exp[1024];
4125   char search_path[512];
4126   char TemplateDn[512];
4127   char TemplateSamName[128];
4128   char alt_recipient[256];
4129   char principal[256];
4130   char status[256];
4131   char acBERBuf[N_SD_BER_BYTES];
4132   LDAPControl sControl = {"1.2.840.113556.1.4.801",
4133                           { N_SD_BER_BYTES, acBERBuf },
4134                           TRUE};
4135   LDAPControl *apsServerControls[] = {&sControl, NULL};
4136   LDAPMessage *psMsg;
4137   LDAP_BERVAL   **ppsValues;
4138   ULONG dwInfo;
4139   char *argv[3];
4140   char *homeMDB;
4141   char *homeServerName;
4142   char *save_argv[7];
4143   char search_string[256];
4144   char *p, *q;
4145   char *mail_routing_v[] = {NULL, NULL};
4146   char *c;
4147
4148   dwInfo = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
4149     DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION;
4150   BEREncodeSecurityBits(dwInfo, acBERBuf);
4151
4152   if (!check_string(user_name))
4153     {
4154       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", 
4155               user_name);
4156       return(AD_INVALID_NAME);
4157     }
4158   
4159   memset(contact_mail, '\0', sizeof(contact_mail));
4160   sprintf(contact_mail, "%s@mit.edu", user_name);
4161   memset(mail, '\0', sizeof(mail));
4162   sprintf(mail, "%s@%s", user_name, lowercase(ldap_domain));
4163   memset(alt_recipient, '\0', sizeof(alt_recipient));
4164   sprintf(alt_recipient, "cn=%s@mit.edu,%s,%s", user_name, contact_ou, 
4165           dn_path);
4166   sprintf(search_string, "@%s", uppercase(ldap_domain));
4167
4168   if (Exchange)
4169     {
4170       if(contact_create(ldap_handle, dn_path, contact_mail, contact_ou))
4171         {
4172           com_err(whoami, 0, "Unable to create user contact %s", contact_mail);
4173         }
4174     }
4175
4176   group_count = 0;
4177   group_base = NULL;
4178
4179   memset(displayName, '\0', sizeof(displayName));
4180
4181   if (strlen(MoiraId) != 0)
4182     {
4183       if(ActiveDirectory)
4184         {
4185           sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
4186         }
4187       else
4188         {
4189           sprintf(filter, 
4190                   "(&(objectClass=mitPerson)(mitMoiraId=%s))", MoiraId);
4191         }
4192
4193       attr_array[0] = "cn";
4194       attr_array[1] = NULL;
4195       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
4196                                &group_base, &group_count, 
4197                                LDAP_SCOPE_SUBTREE)) != 0)
4198         {
4199           com_err(whoami, 0, "Unable to process user %s : %s",
4200                   user_name, ldap_err2string(rc));
4201           return(rc);
4202         }
4203     }
4204
4205   if (group_count != 1)
4206     {
4207       linklist_free(group_base);
4208       group_base = NULL;
4209       group_count = 0;
4210       sprintf(filter, "(sAMAccountName=%s)", user_name);
4211       attr_array[0] = "cn";
4212       attr_array[1] = NULL;
4213       sprintf(temp, "%s,%s", user_ou, dn_path);
4214       if ((rc = linklist_build(ldap_handle, temp, filter, attr_array, 
4215                                &group_base, &group_count, 
4216                                LDAP_SCOPE_SUBTREE)) != 0)
4217         {
4218           com_err(whoami, 0, "Unable to process user %s : %s",
4219                   user_name, ldap_err2string(rc));
4220           return(rc);
4221         }
4222     }
4223
4224   if (group_count != 1)
4225     {
4226       com_err(whoami, 0, "Unable to find user %s in directory",
4227               user_name);
4228       linklist_free(group_base);
4229       return(AD_NO_USER_FOUND);
4230     }
4231
4232   strcpy(distinguished_name, group_base->dn);
4233
4234   linklist_free(group_base);
4235   group_count = 0;
4236
4237   if(!ActiveDirectory) 
4238     {
4239       if (rc = moira_connect())
4240         {
4241           critical_alert("Ldap incremental", 
4242                          "Error contacting Moira server : %s",
4243                          error_message(rc));
4244           return;
4245         }
4246   
4247       argv[0] = user_name;
4248       
4249       if (!(rc = mr_query("get_pobox", 1, argv, save_query_info, save_argv)))
4250         {
4251           n = 0;
4252           ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_REPLACE);
4253           mods[n] = NULL;
4254           rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4255           
4256           if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
4257             rc = LDAP_SUCCESS;
4258
4259           if(rc)
4260             com_err(whoami, 0, 
4261                     "Unable to set the mailRoutingAddress for %s : %s",
4262                     user_name, ldap_err2string(rc));
4263           
4264           p = strdup(save_argv[3]);
4265           
4266           if((c = strchr(p, ',')) != NULL) 
4267             {
4268               q = strtok(p, ",");
4269               StringTrim(q);
4270
4271               if ((c = strchr(q, '@')) == NULL)
4272                 sprintf(temp, "%s@mit.edu", q);
4273               else
4274                 sprintf(temp, "%s", q);
4275               
4276               if(email_isvalid(temp) && State != US_DELETED) 
4277                 {
4278                   mail_routing_v[0]  = temp;
4279                   
4280                   n = 0;
4281                   ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
4282                   mods[n] = NULL;
4283                   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4284
4285                   if (rc == LDAP_ALREADY_EXISTS || 
4286                       rc == LDAP_TYPE_OR_VALUE_EXISTS)
4287                     rc = LDAP_SUCCESS;
4288     
4289                   if(rc)
4290                     com_err(whoami, 0, 
4291                             "Unable to set the mailRoutingAddress for %s : %s",
4292                             user_name, ldap_err2string(rc));
4293                 }
4294
4295               while((q = strtok(NULL, ",")) != NULL) {
4296                 StringTrim(q);
4297                 
4298                 if((c = strchr(q, '@')) == NULL) 
4299                   sprintf(temp, "%s@mit.edu", q);
4300                 else
4301                   sprintf(temp, "%s", q);
4302
4303                 if(email_isvalid(temp) && State != US_DELETED) 
4304                   {
4305                     mail_routing_v[0]  = temp;
4306                 
4307                     n = 0;
4308                     ADD_ATTR("mailRoutingAddress", mail_routing_v, 
4309                              LDAP_MOD_ADD);
4310                     mods[n] = NULL;
4311                     rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4312                     
4313                     if (rc == LDAP_ALREADY_EXISTS || 
4314                         rc == LDAP_TYPE_OR_VALUE_EXISTS)
4315                       rc = LDAP_SUCCESS;
4316                     
4317                     if(rc)
4318                       com_err(whoami, 0, 
4319                               "Unable to set the mailRoutingAddress for " 
4320                               "%s : %s",
4321                               user_name, ldap_err2string(rc));
4322                   }
4323               }
4324             } else {
4325               StringTrim(p);
4326
4327             if((c = strchr(p, '@')) == NULL)
4328               sprintf(temp, "%s@mit.edu", p);
4329             else
4330               sprintf(temp, "%s", p);
4331             
4332             if(email_isvalid(temp) && State != US_DELETED) 
4333               {
4334                 mail_routing_v[0]  = temp;
4335                 
4336                 n = 0;
4337                 ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
4338                 mods[n] = NULL;
4339                 rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4340                 
4341                 if (rc == LDAP_ALREADY_EXISTS || 
4342                     rc == LDAP_TYPE_OR_VALUE_EXISTS)
4343                   rc = LDAP_SUCCESS;
4344                 
4345                 if(rc)
4346                   com_err(whoami, 0, 
4347                           "Unable to set the mailRoutingAddress for %s : %s",
4348                           user_name, ldap_err2string(rc));
4349               }
4350             }
4351         }
4352       moira_disconnect();
4353     }
4354
4355   if ((strlen(MitId) != 0) && (MitId[0] == '9'))
4356     rc = attribute_update(ldap_handle, distinguished_name, MitId, 
4357                           "employeeID", user_name);
4358   else
4359     rc = attribute_update(ldap_handle, distinguished_name, "none", 
4360                           "employeeID", user_name);
4361
4362   if(strlen(first)) {
4363     strcat(displayName, first);
4364   }
4365
4366   if(strlen(middle)) {
4367     if(strlen(first)) 
4368       strcat(displayName, " ");
4369
4370     strcat(displayName, middle);
4371   }
4372
4373   if(strlen(last)) {
4374     if(strlen(middle) || strlen(first))
4375       strcat(displayName, " ");
4376
4377     strcat(displayName, last);
4378   }
4379
4380   if(strlen(displayName))
4381     rc = attribute_update(ldap_handle, distinguished_name, displayName, 
4382                           "displayName", user_name);
4383   else
4384     rc = attribute_update(ldap_handle, distinguished_name, user_name,
4385                           "displayName", user_name);
4386
4387   if(!ActiveDirectory)
4388     {
4389       if(strlen(displayName))
4390         rc = attribute_update(ldap_handle, distinguished_name, displayName, 
4391                               "cn", user_name);
4392       else
4393         rc = attribute_update(ldap_handle, distinguished_name, user_name,
4394                               "cn", user_name);
4395     }
4396
4397   if(!ActiveDirectory)
4398     {
4399       rc = attribute_update(ldap_handle, distinguished_name, displayName, 
4400                             "eduPersonNickname", user_name);
4401     }
4402
4403   if(strlen(first))
4404     rc = attribute_update(ldap_handle, distinguished_name, first, 
4405                           "givenName", user_name);
4406   else
4407     rc = attribute_update(ldap_handle, distinguished_name, "",
4408                           "givenName", user_name);
4409
4410   if(strlen(middle) == 1) 
4411     rc = attribute_update(ldap_handle, distinguished_name, middle,
4412                           "initials", user_name);
4413   else 
4414     rc = attribute_update(ldap_handle, distinguished_name, "",
4415                           "initials", user_name);
4416   
4417   if(strlen(last))
4418     rc = attribute_update(ldap_handle, distinguished_name, last,
4419                           "sn", user_name);
4420   else 
4421     rc = attribute_update(ldap_handle, distinguished_name, "",
4422                           "sn", user_name);
4423
4424   if(ActiveDirectory)
4425     {
4426       rc = attribute_update(ldap_handle, distinguished_name, Uid, "uid", 
4427                             user_name);
4428     }
4429   else
4430     {
4431       rc = attribute_update(ldap_handle, distinguished_name, user_name, "uid", 
4432                             user_name);
4433     }
4434     
4435   rc = attribute_update(ldap_handle, distinguished_name, MoiraId, 
4436                         "mitMoiraId", user_name);
4437
4438   n = 0;
4439   uid_v[0] = Uid;
4440
4441   if(ActiveDirectory)
4442     {
4443       if (!UseSFU30)
4444         {
4445           ADD_ATTR("uidNumber", uid_v, LDAP_MOD_REPLACE);
4446         }
4447       else
4448         {
4449           ADD_ATTR("msSFU30UidNumber", uid_v, LDAP_MOD_REPLACE);
4450         }
4451     }
4452   else
4453     {
4454       sprintf(principal, "%s@%s", user_name, PRIMARY_REALM);
4455       sprintf(status, "%d", State);
4456       principal_v[0] = principal;
4457       loginshell_v[0] = shell;
4458       mitMoiraClass_v[0] = class;
4459       mitMoiraStatus_v[0] = status;
4460       gid_v[0] = "101";
4461       ADD_ATTR("uidNumber", uid_v, LDAP_MOD_REPLACE);
4462       ADD_ATTR("gidNumber", gid_v, LDAP_MOD_REPLACE);
4463       ADD_ATTR("loginShell", loginshell_v, LDAP_MOD_REPLACE);
4464       ADD_ATTR("eduPersonPrincipalName", mail_v, LDAP_MOD_REPLACE);
4465       ADD_ATTR("mitMoiraClass", mitMoiraClass_v, LDAP_MOD_REPLACE);
4466       ADD_ATTR("mitMoiraStatus", mitMoiraStatus_v, LDAP_MOD_REPLACE);
4467     }
4468
4469   if ((State != US_NO_PASSWD) && (State != US_REGISTERED))
4470     {
4471       userAccountControl |= UF_ACCOUNTDISABLE;
4472
4473       if (Exchange)
4474         {
4475           hide_address_lists_v[0] = "TRUE";
4476           ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
4477                    LDAP_MOD_REPLACE);
4478         }
4479     }
4480   else
4481     {
4482       if (Exchange)
4483         {
4484           hide_address_lists_v[0] = NULL;
4485           ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
4486                    LDAP_MOD_REPLACE);
4487         }
4488     }
4489
4490   sprintf(userAccountControlStr, "%ld", userAccountControl);
4491   userAccountControl_v[0] = userAccountControlStr;
4492   ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_REPLACE);
4493
4494   if (Exchange)
4495     {
4496       if (rc = moira_connect())
4497         {
4498           critical_alert("Ldap incremental", 
4499                          "Error contacting Moira server : %s",
4500                          error_message(rc));
4501           return;
4502         }
4503  
4504       argv[0] = user_name;
4505
4506       if (!(rc = mr_query("get_pobox", 1, argv, save_query_info, save_argv)))
4507         {
4508           if(!strcmp(save_argv[1], "EXCHANGE") || 
4509              (strstr(save_argv[3], search_string) != NULL))
4510             {
4511               alt_recipient_v[0] = NULL;
4512               ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_REPLACE);
4513
4514               argv[0] = exchange_acl;
4515               argv[1] = "USER";
4516               argv[2] = user_name;
4517               
4518               rc = mr_query("add_member_to_list", 3, argv, NULL, NULL);
4519               
4520               if ((rc) && (rc != MR_EXISTS))
4521                 {
4522                   com_err(whoami, 0, "Unable to add user %s to %s: %s",
4523                           user_name, exchange_acl, error_message(rc));
4524                 }
4525             }
4526           else 
4527             {
4528               alt_recipient_v[0] = alt_recipient;
4529               ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_REPLACE);
4530               
4531               argv[0] = exchange_acl;
4532               argv[1] = "USER";
4533               argv[2] = user_name;
4534               
4535               rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL);
4536               
4537               if ((rc) && (rc != MR_NO_MATCH))
4538                 {  
4539                   com_err(whoami, 0,
4540                           "Unable to remove user %s from %s: %s, %d",
4541                           user_name, exchange_acl, error_message(rc), rc);
4542                 }  
4543             }
4544         }
4545       else
4546         {
4547           alt_recipient_v[0] = alt_recipient;
4548           ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_REPLACE);
4549           
4550           argv[0] = exchange_acl;
4551           argv[1] = "USER";
4552           argv[2] = user_name;
4553           
4554           rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL);
4555           
4556           if ((rc) && (rc != MR_NO_MATCH))
4557             {  
4558               com_err(whoami, 0,
4559                       "Unable to remove user %s from %s: %s, %d",
4560                       user_name, exchange_acl, error_message(rc), rc);
4561             }  
4562         }
4563       
4564       moira_disconnect();
4565     }
4566   else
4567     {
4568       mail_v[0] = contact_mail;
4569       ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE);
4570
4571       if(!ActiveDirectory)
4572         {
4573           ADD_ATTR("mitMoiraMail", mail_v, LDAP_MOD_REPLACE);
4574         }
4575     }
4576
4577   n = SetHomeDirectory(ldap_handle, user_name, distinguished_name, WinHomeDir, 
4578                        WinProfileDir, homedir_v, winProfile_v,
4579                        drives_v, mods, LDAP_MOD_REPLACE, n);
4580
4581   if(ActiveDirectory)
4582     {
4583       sprintf(filter_exp, "(sAMAccountName=%s)", "UserTemplate.u");
4584       sprintf(search_path, "%s,%s", security_template_ou, dn_path);
4585       attr_array[0] = "sAMAccountName";
4586       attr_array[1] = NULL;
4587       group_count = 0;
4588       group_base = NULL;
4589     
4590       if ((rc = linklist_build(ldap_handle, search_path, filter_exp, 
4591                                attr_array,
4592                                &group_base, &group_count, 
4593                                LDAP_SCOPE_SUBTREE) != 0))
4594         return(1);
4595       
4596       if (group_count != 1)
4597         {
4598           com_err(whoami, 0, "Unable to process user security template: %s - "
4599                   "security not set", "UserTemplate.u");
4600           return(1);
4601         }
4602
4603       strcpy(TemplateDn, group_base->dn);
4604       strcpy(TemplateSamName, group_base->value);
4605       linklist_free(group_base);
4606       group_base = NULL;
4607       group_count = 0;
4608       
4609       rc = ldap_search_ext_s(ldap_handle, search_path, LDAP_SCOPE_SUBTREE,
4610                              filter_exp, NULL, 0, apsServerControls, NULL,
4611                              NULL, 0, &psMsg);
4612
4613       if ((psMsg = ldap_first_entry(ldap_handle, psMsg)) == NULL)
4614         {
4615           com_err(whoami, 0, "Unable to find user security template: %s - "
4616                   "security not set", "UserTemplate.u");
4617           return(1);
4618         }
4619       
4620       ppsValues = ldap_get_values_len(ldap_handle, psMsg, 
4621                                       "ntSecurityDescriptor");
4622
4623       if (ppsValues == NULL)
4624         {
4625           com_err(whoami, 0, "Unable to find user security template: %s - "
4626                   "security not set", "UserTemplate.u");
4627           return(1);
4628         }
4629       
4630       ADD_ATTR("ntSecurityDescriptor", (char **)ppsValues,
4631                LDAP_MOD_REPLACE | LDAP_MOD_BVALUES);
4632     }
4633
4634   mods[n] = NULL;
4635
4636   if ((rc = ldap_modify_s(ldap_handle, distinguished_name, 
4637                           mods)) != LDAP_SUCCESS)
4638     {
4639       OldUseSFU30 = UseSFU30;
4640       SwitchSFU(mods, &UseSFU30, n);
4641       if (OldUseSFU30 != UseSFU30)
4642         rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
4643       if (rc)
4644         {
4645           com_err(whoami, 0, "Unable to modify user data for %s : %s",
4646                   user_name, ldap_err2string(rc));
4647         }
4648     }
4649   
4650   for (i = 0; i < n; i++)
4651     free(mods[i]);
4652
4653   return(rc);
4654 }
4655
4656 int user_rename(LDAP *ldap_handle, char *dn_path, char *before_user_name, 
4657                 char *user_name)
4658 {
4659   LDAPMod *mods[20];
4660   char new_dn[256];
4661   char old_dn[256];
4662   char upn[256];
4663   char mail[256];
4664   char contact_mail[256];
4665   char proxy_address[256];
4666   char query_base_dn[256];
4667   char temp[256];
4668   char *userPrincipalName_v[] = {NULL, NULL};
4669   char *altSecurityIdentities_v[] = {NULL, NULL};
4670   char *name_v[] = {NULL, NULL};
4671   char *samAccountName_v[] = {NULL, NULL};
4672   char *mail_v[] = {NULL, NULL};
4673   char *mail_nickname_v[] = {NULL, NULL};
4674   char *proxy_address_v[] = {NULL, NULL};
4675   char *query_base_dn_v[] = {NULL, NULL};
4676   char *principal_v[] = {NULL, NULL};
4677   char principal[256];
4678   int  n;
4679   int  rc;
4680   int  i;
4681
4682   if (!check_string(before_user_name))
4683     {
4684       com_err(whoami, 0, 
4685               "Unable to process invalid LDAP user name %s", before_user_name);
4686       return(AD_INVALID_NAME);
4687     }
4688
4689   if (!check_string(user_name))
4690     {
4691       com_err(whoami, 0, 
4692               "Unable to process invalid LDAP user name %s", user_name);
4693       return(AD_INVALID_NAME);
4694     }
4695
4696   strcpy(user_name, user_name);
4697  
4698   if(ActiveDirectory)
4699     sprintf(old_dn, "cn=%s,%s,%s", before_user_name, user_ou, dn_path);
4700   else
4701     sprintf(old_dn, "uid=%s,%s,%s", before_user_name, user_ou, dn_path);
4702
4703   if(ActiveDirectory)
4704     sprintf(new_dn, "cn=%s", user_name);
4705   else
4706     sprintf(new_dn, "uid=%s", user_name);
4707
4708   sprintf(mail, "%s@%s", user_name, lowercase(ldap_domain));
4709   sprintf(contact_mail, "%s@mit.edu", user_name);
4710   sprintf(proxy_address, "SMTP:%s@%s", user_name, lowercase(ldap_domain)); 
4711   sprintf(principal, "%s@%s", user_name, PRIMARY_REALM);
4712
4713   if ((rc = ldap_rename_s(ldap_handle, old_dn, new_dn, NULL, TRUE, 
4714                            NULL, NULL)) != LDAP_SUCCESS)
4715     {
4716       com_err(whoami, 0, "Unable to rename user from %s to %s : %s",
4717               before_user_name, user_name, ldap_err2string(rc));
4718       return(rc);
4719     }
4720
4721   if (Exchange)
4722     {
4723       sprintf(temp, "cn=%s@mit.edu,%s,%s", before_user_name, contact_ou, 
4724               dn_path);
4725
4726       if(rc = ldap_delete_s(ldap_handle, temp))
4727         {
4728           com_err(whoami, 0, "Unable to delete user contact for %s",
4729                   user_name);
4730         }
4731       
4732       if(contact_create(ldap_handle, dn_path, contact_mail, contact_ou))
4733         {
4734           com_err(whoami, 0, "Unable to create user contact %s", contact_mail);
4735         }
4736     }
4737
4738   name_v[0] = user_name;
4739   sprintf(upn, "%s@%s", user_name, ldap_domain);
4740   userPrincipalName_v[0] = upn;
4741   principal_v[0] = principal;
4742   sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
4743   sprintf(query_base_dn, "%s%s", ADDRESS_LIST_PREFIX, dn_path);
4744   altSecurityIdentities_v[0] = temp;
4745   samAccountName_v[0] = user_name;
4746   mail_v[0] = mail;
4747   mail_nickname_v[0] = user_name;
4748   proxy_address_v[0] = proxy_address; 
4749   query_base_dn_v[0] = query_base_dn;
4750
4751   n = 0;
4752   ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_REPLACE);
4753   ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_REPLACE);
4754   ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
4755   ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_REPLACE);
4756
4757   if(!ActiveDirectory)
4758     {
4759       ADD_ATTR("uid", samAccountName_v, LDAP_MOD_REPLACE);
4760       ADD_ATTR("eduPersonPrincipalName", mail_v, LDAP_MOD_REPLACE);
4761       ADD_ATTR("displayName", name_v, LDAP_MOD_REPLACE);
4762       ADD_ATTR("eduPersonNickname", name_v, LDAP_MOD_REPLACE);
4763     }
4764
4765   if (Exchange)
4766     {
4767       ADD_ATTR("msExchQueryBaseDN", query_base_dn_v, LDAP_MOD_REPLACE);
4768       ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_REPLACE); 
4769       ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE); 
4770       ADD_ATTR("proxyAddresses", proxy_address_v, LDAP_MOD_REPLACE);
4771     }
4772   else
4773     {
4774       mail_v[0] = contact_mail;
4775       ADD_ATTR("mail", mail_v, LDAP_MOD_REPLACE); 
4776
4777       if(!ActiveDirectory)
4778         {
4779           ADD_ATTR("mitMoiraMail", mail_v, LDAP_MOD_REPLACE);
4780         }
4781     }
4782
4783   mods[n] = NULL;
4784   
4785   if(ActiveDirectory)
4786     sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, dn_path);
4787   else
4788     sprintf(new_dn, "uid=%s,%s,%s", user_name, user_ou, dn_path);
4789
4790   if ((rc = ldap_modify_s(ldap_handle, new_dn, mods)) != LDAP_SUCCESS)
4791     {
4792       com_err(whoami, 0, 
4793               "Unable to modify user data for %s after renaming : %s",
4794               user_name, ldap_err2string(rc));
4795     }
4796   
4797   for (i = 0; i < n; i++)
4798     free(mods[i]);
4799
4800   return(rc);
4801 }
4802
4803 int user_create(int ac, char **av, void *ptr)
4804 {
4805   LDAPMod *mods[20];
4806   char new_dn[256];
4807   char user_name[256];
4808   char sam_name[256];
4809   char upn[256];
4810   char mail[256];
4811   char contact_mail[256];
4812   char proxy_address[256];
4813   char mail_nickname[256];
4814   char query_base_dn[256];
4815   char displayName[256];
4816   char address_book[256];
4817   char alt_recipient[256];
4818   char *cn_v[] = {NULL, NULL};
4819   char *objectClass_v[] = {"top", "person", "organizationalPerson",
4820                            "user", NULL};
4821   char *objectClass_ldap_v[] = {"top", 
4822                                 "eduPerson", "posixAccount", 
4823                                 "apple-user", "shadowAccount",
4824                                 "microsoftComTop", "securityPrincipal",
4825                                 "inetOrgPerson", "user", 
4826                                 "organizationalPerson", "person",
4827                                 "mailRecipient", NULL};
4828
4829   char *samAccountName_v[] = {NULL, NULL};
4830   char *altSecurityIdentities_v[] = {NULL, NULL};
4831   char *mitMoiraId_v[] = {NULL, NULL};
4832   char *mitMoiraClass_v[] = {NULL, NULL};
4833   char *mitMoiraStatus_v[] = {NULL, NULL};
4834   char *name_v[] = {NULL, NULL};
4835   char *desc_v[] = {NULL, NULL};
4836   char *userPrincipalName_v[] = {NULL, NULL};
4837   char *userAccountControl_v[] = {NULL, NULL};
4838   char *uid_v[] = {NULL, NULL};
4839   char *gid_v[] = {NULL, NULL};
4840   char *mitid_v[] = {NULL, NULL};
4841   char *homedir_v[] = {NULL, NULL};
4842   char *winProfile_v[] = {NULL, NULL};
4843   char *drives_v[] = {NULL, NULL};
4844   char *mail_v[] = {NULL, NULL};
4845   char *givenName_v[] = {NULL, NULL};
4846   char *sn_v[] = {NULL, NULL};
4847   char *initials_v[] = {NULL, NULL};
4848   char *displayName_v[] = {NULL, NULL};
4849   char *proxy_address_v[] = {NULL, NULL};
4850   char *mail_nickname_v[] = {NULL, NULL};
4851   char *query_base_dn_v[] = {NULL, NULL};
4852   char *address_book_v[] = {NULL, NULL};
4853   char *homeMDB_v[] = {NULL, NULL};
4854   char *homeServerName_v[] = {NULL, NULL};
4855   char *mdbUseDefaults_v[] = {NULL, NULL};
4856   char *mailbox_guid_v[] = {NULL, NULL};
4857   char *user_culture_v[] = {NULL, NULL};
4858   char *user_account_control_v[] = {NULL, NULL};
4859   char *msexch_version_v[] = {NULL, NULL};
4860   char *alt_recipient_v[] = {NULL, NULL};
4861   char *hide_address_lists_v[] = {NULL, NULL};
4862   char *principal_v[] = {NULL, NULL};
4863   char *loginshell_v[] = {NULL, NULL};
4864   char userAccountControlStr[80];
4865   char temp[1024];
4866   char principal[256];
4867   char filter_exp[1024];
4868   char search_path[512];
4869   char *attr_array[3];
4870   u_int userAccountControl = UF_NORMAL_ACCOUNT | UF_DONT_EXPIRE_PASSWD | 
4871     UF_PASSWD_CANT_CHANGE; 
4872   int  n;
4873   int  rc;
4874   int  i;
4875   int  OldUseSFU30;
4876   char **call_args;
4877   char WinHomeDir[1024];
4878   char WinProfileDir[1024];
4879   char *homeMDB;
4880   char *homeServerName;
4881   ULONG dwInfo;
4882   char acBERBuf[N_SD_BER_BYTES];
4883   LK_ENTRY  *group_base;
4884   int    group_count;
4885   char TemplateDn[512];
4886   char TemplateSamName[128];
4887   LDAP_BERVAL **ppsValues;
4888   LDAPControl sControl = {"1.2.840.113556.1.4.801",
4889                           { N_SD_BER_BYTES, acBERBuf },
4890                           TRUE};
4891   LDAPControl *apsServerControls[] = {&sControl, NULL};
4892   LDAPMessage *psMsg;
4893   char *argv[3];
4894   char *save_argv[7];
4895   char search_string[256];
4896   char *o_v[] = {NULL, NULL};
4897   char *p, *q;
4898   char *mail_routing_v[] = {NULL, NULL};
4899   char *c;
4900
4901   call_args = ptr;
4902
4903   dwInfo = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION |
4904     DACL_SECURITY_INFORMATION | SACL_SECURITY_INFORMATION;
4905   BEREncodeSecurityBits(dwInfo, acBERBuf);
4906
4907   if (!check_string(av[U_NAME]))
4908     {
4909       callback_rc = AD_INVALID_NAME;
4910       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", 
4911               av[U_NAME]);
4912       return(AD_INVALID_NAME);
4913     }
4914
4915   memset(WinHomeDir, '\0', sizeof(WinHomeDir));
4916   memset(WinProfileDir, '\0', sizeof(WinProfileDir));
4917   memset(displayName, '\0', sizeof(displayName));
4918   memset(query_base_dn, '\0', sizeof(query_base_dn));
4919   strcpy(WinHomeDir, av[U_WINHOMEDIR]);
4920   strcpy(WinProfileDir, av[U_WINPROFILEDIR]);
4921   strcpy(user_name, av[U_NAME]);
4922   sprintf(upn, "%s@%s", user_name, ldap_domain);
4923   sprintf(sam_name, "%s", av[U_NAME]);
4924
4925   if(strlen(av[U_FIRST])) {
4926     strcat(displayName, av[U_FIRST]);
4927   }
4928
4929   if(strlen(av[U_MIDDLE])) {
4930     if(strlen(av[U_FIRST]))
4931        strcat(displayName, " "); 
4932   
4933     strcat(displayName, av[U_MIDDLE]);
4934   }
4935
4936   if(strlen(av[U_LAST])) {
4937     if(strlen(av[U_FIRST]) || strlen(av[U_MIDDLE]))
4938       strcat(displayName, " ");
4939
4940     strcat(displayName, av[U_LAST]);
4941   }
4942
4943   samAccountName_v[0] = sam_name;
4944   if ((atoi(av[U_STATE]) != US_NO_PASSWD) && 
4945       (atoi(av[U_STATE]) != US_REGISTERED))
4946     {
4947       userAccountControl |= UF_ACCOUNTDISABLE;
4948
4949       if (Exchange)
4950         {
4951           hide_address_lists_v[0] = "TRUE";
4952           ADD_ATTR("msExchHideFromAddressLists", hide_address_lists_v,
4953                    LDAP_MOD_ADD);
4954         }
4955     }
4956
4957   sprintf(userAccountControlStr, "%ld", userAccountControl);
4958   userAccountControl_v[0] = userAccountControlStr;
4959   userPrincipalName_v[0] = upn;
4960   
4961   if(ActiveDirectory)
4962     cn_v[0] = user_name;
4963   else
4964     cn_v[0] = displayName;
4965     
4966   name_v[0] = user_name;
4967   desc_v[0] = "Auto account created by Moira";
4968   mail_v[0] = mail;
4969   givenName_v[0] = av[U_FIRST];
4970
4971   if(ActiveDirectory)
4972     sn_v[0] = av[U_LAST];
4973   else
4974     if(strlen(av[U_LAST]))
4975       sn_v[0] = av[U_LAST];
4976     else
4977       sn_v[0] = av[U_NAME];
4978
4979   displayName_v[0] = displayName;
4980   mail_nickname_v[0] = user_name;
4981   o_v[0] = "Massachusetts Institute of Technology";
4982
4983   sprintf(temp, "Kerberos:%s@%s", user_name, PRIMARY_REALM);
4984   sprintf(principal, "%s@%s", user_name, PRIMARY_REALM);
4985   altSecurityIdentities_v[0] = temp;    
4986   principal_v[0] = principal;
4987
4988   if(ActiveDirectory)
4989     sprintf(new_dn, "cn=%s,%s,%s", user_name, user_ou, call_args[1]);
4990   else
4991     sprintf(new_dn, "uid=%s,%s,%s", user_name, user_ou, call_args[1]);
4992
4993   sprintf(mail,"%s@%s", user_name, lowercase(ldap_domain));
4994   sprintf(contact_mail, "%s@mit.edu", user_name);
4995   sprintf(query_base_dn, "%s%s", ADDRESS_LIST_PREFIX, call_args[1]);
4996   query_base_dn_v[0] = query_base_dn;
4997   sprintf(alt_recipient, "cn=%s@mit.edu,%s,%s", user_name, contact_ou, 
4998           call_args[1]);
4999   sprintf(search_string, "@%s", uppercase(ldap_domain));
5000
5001   if (Exchange)
5002     {
5003       if(contact_create((LDAP *)call_args[0], call_args[1], contact_mail, 
5004                         contact_ou))
5005         {
5006           com_err(whoami, 0, "Unable to create user contact %s", 
5007                   contact_mail);
5008         }
5009       
5010       if(find_homeMDB((LDAP *)call_args[0], call_args[1], &homeMDB, 
5011                       &homeServerName)) 
5012         {
5013           com_err(whoami, 0, "Unable to locate homeMB and homeServerName");
5014           return(1);
5015         }
5016       
5017       com_err(whoami, 0, "homeMDB:%s", homeMDB);
5018       com_err(whoami, 0, "homeServerName:%s", homeServerName);
5019   
5020       homeMDB_v[0] = homeMDB;
5021       homeServerName_v[0] = homeServerName; 
5022     }
5023
5024   n = 0;
5025
5026   ADD_ATTR("cn", cn_v, LDAP_MOD_ADD);
5027   
5028   if(ActiveDirectory) 
5029     {
5030       ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
5031     }
5032   else
5033     {
5034       ADD_ATTR("objectClass", objectClass_ldap_v, LDAP_MOD_ADD);
5035     }
5036
5037   ADD_ATTR("sAMAccountName", samAccountName_v, LDAP_MOD_ADD);
5038   ADD_ATTR("userPrincipalName", userPrincipalName_v, LDAP_MOD_ADD);
5039   ADD_ATTR("userAccountControl", userAccountControl_v, LDAP_MOD_ADD);
5040   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
5041   ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
5042
5043   if (Exchange)
5044     {
5045       ADD_ATTR("msExchQueryBaseDN", query_base_dn_v, LDAP_MOD_ADD);
5046       ADD_ATTR("mailNickName", mail_nickname_v, LDAP_MOD_ADD);
5047       ADD_ATTR("homeMDB", homeMDB_v, LDAP_MOD_ADD);
5048       mdbUseDefaults_v[0] = "TRUE";
5049       ADD_ATTR("mdbUseDefaults", mdbUseDefaults_v, LDAP_MOD_ADD);
5050       ADD_ATTR("msExchHomeServerName", homeServerName_v, LDAP_MOD_ADD); 
5051       
5052       argv[0] = user_name;
5053     
5054       if (!(rc = mr_query("get_pobox", 1, argv, save_query_info, save_argv)))
5055         {
5056           if(!strcmp(save_argv[1], "EXCHANGE") || 
5057              (strstr(save_argv[3], search_string) != NULL))
5058             {
5059               argv[0] = exchange_acl;
5060               argv[1] = "USER";
5061               argv[2] = user_name;
5062               
5063               rc = mr_query("add_member_to_list", 3, argv, NULL, NULL);
5064               
5065               if ((rc) && (rc != MR_EXISTS))
5066                 {
5067                   com_err(whoami, 0, "Unable to add user %s to %s: %s",
5068                           user_name, exchange_acl, error_message(rc));
5069                 }
5070             } 
5071           else 
5072             {
5073               alt_recipient_v[0] = alt_recipient;
5074               ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_ADD);
5075             }
5076         }
5077       else
5078         {
5079           alt_recipient_v[0] = alt_recipient;
5080           ADD_ATTR("altRecipient", alt_recipient_v, LDAP_MOD_ADD);
5081           
5082           com_err(whoami, 0, "Unable to fetch pobox for %s", user_name);
5083         }
5084     }
5085   else
5086     {
5087       mail_v[0] = contact_mail;
5088       ADD_ATTR("mail", mail_v, LDAP_MOD_ADD);
5089
5090       if(!ActiveDirectory)
5091         {
5092           ADD_ATTR("mitMoiraMail", mail_v, LDAP_MOD_ADD);
5093         }
5094     }
5095
5096   if(strlen(av[U_FIRST])) {
5097     ADD_ATTR("givenName", givenName_v, LDAP_MOD_ADD);
5098   }
5099
5100   if(strlen(av[U_LAST]) || strlen(av[U_NAME])) {
5101     ADD_ATTR("sn", sn_v, LDAP_MOD_ADD);
5102   }
5103
5104   if(strlen(av[U_FIRST]) || strlen(av[U_MIDDLE]) || strlen(av[U_LAST])) {
5105     ADD_ATTR("displayName", displayName_v, LDAP_MOD_ADD);
5106
5107     if(!ActiveDirectory)
5108       {
5109         ADD_ATTR("eduPersonNickname", displayName_v, LDAP_MOD_ADD);      
5110       }
5111   } else {
5112     ADD_ATTR("displayName", name_v, LDAP_MOD_ADD);
5113
5114     if(!ActiveDirectory)
5115       {
5116         ADD_ATTR("eduPersonNickname", name_v, LDAP_MOD_ADD);            
5117       }
5118   }
5119
5120   if (strlen(av[U_MIDDLE]) == 1) {
5121     initials_v[0] = av[U_MIDDLE];
5122     ADD_ATTR("initials", initials_v, LDAP_MOD_ADD);
5123   }
5124
5125   if (strlen(call_args[2]) != 0)    
5126     {
5127       mitMoiraId_v[0] = call_args[2];
5128       ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_ADD); 
5129     }
5130
5131   ADD_ATTR("altSecurityIdentities", altSecurityIdentities_v, LDAP_MOD_ADD);
5132
5133   if(!ActiveDirectory)
5134     {
5135       loginshell_v[0] = av[U_SHELL];
5136       mitMoiraClass_v[0] = av[U_CLASS];
5137       mitMoiraStatus_v[0] = av[U_STATE];
5138       ADD_ATTR("loginShell", loginshell_v, LDAP_MOD_ADD);
5139       ADD_ATTR("uid", samAccountName_v, LDAP_MOD_ADD);
5140       ADD_ATTR("eduPersonPrincipalName", mail_v, LDAP_MOD_ADD);
5141       ADD_ATTR("o", o_v, LDAP_MOD_ADD);
5142       ADD_ATTR("mitMoiraClass", mitMoiraClass_v, LDAP_MOD_ADD);
5143       ADD_ATTR("mitMoiraStatus", mitMoiraStatus_v, LDAP_MOD_ADD);
5144     }
5145
5146   if (strlen(av[U_UID]) != 0)
5147     {
5148       uid_v[0] = av[U_UID];
5149
5150       if(ActiveDirectory) 
5151         {
5152           ADD_ATTR("uid", uid_v, LDAP_MOD_ADD);
5153         }
5154       else
5155         {
5156           gid_v[0] = "101";
5157           ADD_ATTR("uidNumber", uid_v, LDAP_MOD_ADD);
5158           ADD_ATTR("gidNumber", gid_v, LDAP_MOD_ADD);
5159         }
5160
5161       if(ActiveDirectory)
5162         {
5163           if (!UseSFU30)
5164             {
5165               ADD_ATTR("uidNumber", uid_v, LDAP_MOD_ADD);
5166             }
5167           else
5168             {
5169               ADD_ATTR("msSFU30UidNumber", uid_v, LDAP_MOD_ADD);
5170             }
5171         }
5172     }
5173
5174   if ((strlen(av[U_MITID]) != 0) && (av[U_MITID][0] == '9'))
5175       mitid_v[0] = av[U_MITID];
5176   else
5177       mitid_v[0] = "none";
5178
5179   ADD_ATTR("employeeID", mitid_v, LDAP_MOD_ADD);
5180
5181   n = SetHomeDirectory((LDAP *)call_args[0], user_name, new_dn, 
5182                        WinHomeDir, WinProfileDir, homedir_v, winProfile_v,
5183                        drives_v, mods, LDAP_MOD_ADD, n);
5184   
5185   if(ActiveDirectory) 
5186     {
5187       sprintf(filter_exp, "(sAMAccountName=%s)", "UserTemplate.u");
5188       sprintf(search_path, "%s,%s", security_template_ou, call_args[1]);
5189       attr_array[0] = "sAMAccountName";
5190       attr_array[1] = NULL;
5191       group_count = 0;
5192       group_base = NULL;
5193       
5194       if ((rc = linklist_build((LDAP *)call_args[0], search_path, filter_exp, 
5195                                attr_array, &group_base, &group_count, 
5196                                LDAP_SCOPE_SUBTREE) != 0))
5197         return(1);
5198       
5199       if (group_count != 1)
5200         {
5201           com_err(whoami, 0, "Unable to process user security template: %s - "
5202                   "security not set", "UserTemplate.u");
5203           return(1);
5204         }
5205       
5206       strcpy(TemplateDn, group_base->dn);
5207       strcpy(TemplateSamName, group_base->value);
5208       linklist_free(group_base);
5209       group_base = NULL;
5210       group_count = 0;
5211       
5212       rc = ldap_search_ext_s((LDAP *)call_args[0], search_path, 
5213                              LDAP_SCOPE_SUBTREE, filter_exp, NULL, 0, 
5214                              apsServerControls, NULL,
5215                              NULL, 0, &psMsg);
5216       
5217       if ((psMsg = ldap_first_entry((LDAP *)call_args[0], psMsg)) == NULL)
5218         {
5219           com_err(whoami, 0, "Unable to find user security template: %s - "
5220                   "security not set", "UserTemplate.u");
5221           return(1);
5222         }
5223       
5224       ppsValues = ldap_get_values_len((LDAP *)call_args[0], psMsg, 
5225                                       "ntSecurityDescriptor");
5226       if (ppsValues == NULL)
5227         {
5228           com_err(whoami, 0, "Unable to find user security template: %s - "
5229                   "security not set", "UserTemplate.u");
5230           return(1);
5231         }
5232       
5233       ADD_ATTR("ntSecurityDescriptor", (char **)ppsValues,
5234                LDAP_MOD_REPLACE | LDAP_MOD_BVALUES); 
5235     }
5236
5237   mods[n] = NULL;
5238
5239   rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
5240
5241   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
5242     {
5243       OldUseSFU30 = UseSFU30;
5244       SwitchSFU(mods, &UseSFU30, n);
5245       if (OldUseSFU30 != UseSFU30)
5246         rc = ldap_add_ext_s((LDAP *)call_args[0], new_dn, mods, NULL, NULL);
5247     }
5248
5249   for (i = 0; i < n; i++)
5250     free(mods[i]);
5251
5252   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
5253     {
5254       com_err(whoami, 0, "Unable to create user %s : %s",
5255               user_name, ldap_err2string(rc));
5256       callback_rc = rc;
5257       return(rc);
5258     }
5259
5260   if ((rc == LDAP_SUCCESS) && (SetPassword))
5261     {
5262       if ((rc = set_password(sam_name, "", ldap_domain)) != 0)
5263         {
5264           ad_kdc_disconnect();
5265           if (!ad_server_connect(default_server, ldap_domain))
5266             {
5267               com_err(whoami, 0, "Unable to set password for user %s : %s",
5268                       user_name, 
5269                       "cannot get changepw ticket from windows domain");
5270             }
5271           else
5272             {
5273               if ((rc = set_password(sam_name, "", ldap_domain)) != 0)
5274                 {
5275                   com_err(whoami, 0, "Unable to set password for user %s "
5276                           ": %ld", user_name, rc);
5277                 }
5278             }
5279         }
5280     }
5281
5282   if(!ActiveDirectory) 
5283     {
5284       if (rc = moira_connect())
5285         {
5286           critical_alert("Ldap incremental", 
5287                          "Error contacting Moira server : %s",
5288                          error_message(rc));
5289           return;
5290         }
5291   
5292       argv[0] = user_name;
5293       
5294       if (!(rc = mr_query("get_pobox", 1, argv, save_query_info, save_argv)))
5295         {
5296           n = 0;
5297           ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_REPLACE);
5298           mods[n] = NULL;
5299           rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5300            
5301           if (rc == LDAP_ALREADY_EXISTS || rc == LDAP_TYPE_OR_VALUE_EXISTS)
5302             rc = LDAP_SUCCESS;
5303
5304           if(rc)
5305             com_err(whoami, 0,
5306                     "Unable to set the mailRoutingAddress for %s : %s",
5307                     user_name, ldap_err2string(rc));
5308
5309           p = strdup(save_argv[3]);
5310           
5311           if((c = strchr(p, ',')) != NULL) {
5312             q = strtok(p, ",");
5313             StringTrim(q);
5314
5315             if ((c = strchr(q, '@')) == NULL)
5316               sprintf(temp, "%s@mit.edu", q);
5317             else
5318               sprintf(temp, "%s", q);
5319
5320             if(email_isvalid(temp) && atoi(av[U_STATE]) != US_DELETED) 
5321               {
5322                 mail_routing_v[0]  = temp;
5323
5324                 n = 0;
5325                 ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
5326                 mods[n] = NULL;
5327                 rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5328                 
5329                 if (rc == LDAP_ALREADY_EXISTS || 
5330                     rc == LDAP_TYPE_OR_VALUE_EXISTS)
5331                   rc = LDAP_SUCCESS;
5332                 
5333                 if(rc)
5334                   com_err(whoami, 0, 
5335                           "Unable to set the mailRoutingAddress for %s : %s",
5336                           user_name, ldap_err2string(rc));
5337               }
5338
5339             while((q = strtok(NULL, ",")) != NULL) {
5340               StringTrim(q);
5341
5342               if((c = strchr(q, '@')) == NULL)
5343                 sprintf(temp, "%s@mit.edu", q);
5344               else
5345                 sprintf(temp, "%s", q);
5346
5347               if(email_isvalid(temp) && atoi(av[U_STATE]) != US_DELETED)
5348                 {
5349                   mail_routing_v[0]  = temp;
5350                   
5351                   n = 0;
5352                   ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
5353                   mods[n] = NULL;
5354                   rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5355                   
5356                   if (rc == LDAP_ALREADY_EXISTS || 
5357                       rc == LDAP_TYPE_OR_VALUE_EXISTS)
5358                     rc = LDAP_SUCCESS;
5359                   
5360                   if(rc)
5361                     com_err(whoami, 0, 
5362                             "Unable to set the mailRoutingAddress for %s : %s",
5363                             user_name, ldap_err2string(rc));
5364                 }
5365             }
5366           } else {
5367             StringTrim(p);
5368
5369             if((c = strchr(p, '@')) == NULL)
5370               sprintf(temp, "%s@mit.edu", p);
5371             else
5372               sprintf(temp, "%s", p);
5373
5374             if(email_isvalid(temp) && atoi(av[U_STATE]) != US_DELETED) 
5375               {
5376                 mail_routing_v[0]  = temp;
5377                 
5378                 n = 0;
5379                 ADD_ATTR("mailRoutingAddress", mail_routing_v, LDAP_MOD_ADD);
5380                 mods[n] = NULL;
5381                 rc = ldap_modify_s((LDAP *)call_args[0], new_dn, mods);
5382                 
5383                 if (rc == LDAP_ALREADY_EXISTS || 
5384                     rc == LDAP_TYPE_OR_VALUE_EXISTS)
5385                   rc = LDAP_SUCCESS;
5386                 
5387                 if(rc)
5388                   com_err(whoami, 0, 
5389                           "Unable to set the mailRoutingAddress for %s : %s",
5390                           user_name, ldap_err2string(rc));
5391               }
5392           }
5393         }
5394       moira_disconnect();
5395     }
5396
5397   return(0);
5398 }
5399
5400 int user_change_status(LDAP *ldap_handle, char *dn_path, 
5401                        char *user_name, char *MoiraId,
5402                        int operation)
5403 {
5404   char      filter[128];
5405   char      *attr_array[3];
5406   char      temp[256];
5407   char      distinguished_name[1024];
5408   char      **modvalues;
5409   char      *mitMoiraId_v[] = {NULL, NULL};
5410   LDAPMod   *mods[20];
5411   LK_ENTRY  *group_base;
5412   int       group_count;
5413   int       rc;
5414   int       i;
5415   int       n;
5416   ULONG     ulongValue;
5417
5418   if (!check_string(user_name))
5419     {
5420       com_err(whoami, 0, "Unable to process invalid LDAP user name %s", 
5421               user_name);
5422       return(AD_INVALID_NAME);
5423     }
5424
5425   group_count = 0;
5426   group_base = NULL;
5427
5428   if (strlen(MoiraId) != 0)
5429     {
5430       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
5431       attr_array[0] = "UserAccountControl";
5432       attr_array[1] = NULL;
5433       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
5434                                &group_base, &group_count, 
5435                                LDAP_SCOPE_SUBTREE)) != 0)
5436         {
5437           com_err(whoami, 0, "Unable to process user %s : %s",
5438                   user_name, ldap_err2string(rc));
5439           return(rc);
5440         }
5441     }
5442
5443   if (group_count != 1)
5444     {
5445       linklist_free(group_base);
5446       group_count = 0;
5447       group_base = NULL;
5448       sprintf(filter, "(sAMAccountName=%s)", user_name);
5449       attr_array[0] = "UserAccountControl";
5450       attr_array[1] = NULL;
5451       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
5452                                &group_base, &group_count, 
5453                                LDAP_SCOPE_SUBTREE)) != 0)
5454         {
5455           com_err(whoami, 0, "Unable to process user %s : %s",
5456                   user_name, ldap_err2string(rc));
5457           return(rc);
5458         }
5459     }
5460   
5461   if (group_count != 1)
5462     {
5463       linklist_free(group_base);
5464       com_err(whoami, 0, "Unable to find user %s in directory",
5465               user_name);
5466       return(LDAP_NO_SUCH_OBJECT);
5467     }
5468
5469   strcpy(distinguished_name, group_base->dn);
5470   ulongValue = atoi((*group_base).value);
5471
5472   if (operation == MEMBER_DEACTIVATE)
5473     ulongValue |= UF_ACCOUNTDISABLE;
5474   else    
5475     ulongValue &= ~UF_ACCOUNTDISABLE;
5476
5477   sprintf(temp, "%ld", ulongValue);
5478
5479   if ((rc = construct_newvalues(group_base, group_count, (*group_base).value, 
5480                                 temp, &modvalues, REPLACE)) == 1)
5481     goto cleanup;
5482
5483   linklist_free(group_base);
5484   group_base = NULL;
5485   group_count = 0;
5486   n = 0;
5487   ADD_ATTR("UserAccountControl", modvalues, LDAP_MOD_REPLACE);
5488
5489   if (strlen(MoiraId) != 0)
5490     {
5491     mitMoiraId_v[0] = MoiraId;
5492     ADD_ATTR("mitMoiraId", mitMoiraId_v, LDAP_MOD_REPLACE);
5493     }
5494
5495   mods[n] = NULL;
5496   rc = ldap_modify_s(ldap_handle, distinguished_name, mods);
5497
5498   for (i = 0; i < n; i++)
5499     free(mods[i]);
5500
5501   free_values(modvalues);
5502
5503   if (rc != LDAP_SUCCESS)
5504     {
5505       com_err(whoami, 0, "Unable to change status of user %s : %s",
5506               user_name, ldap_err2string(rc));
5507     }
5508   
5509  cleanup:
5510   return(rc);
5511 }
5512
5513 int user_delete(LDAP *ldap_handle, char *dn_path, 
5514                 char *u_name, char *MoiraId)
5515 {
5516   char      filter[128];
5517   char      *attr_array[3];
5518   char      distinguished_name[1024];
5519   char      user_name[512];
5520   LK_ENTRY  *group_base;
5521   int       group_count;
5522   int       rc;
5523   char      temp[256];
5524
5525   if (!check_string(u_name))
5526     return(AD_INVALID_NAME);
5527
5528   strcpy(user_name, u_name);
5529   group_count = 0;
5530   group_base = NULL;
5531
5532   if (strlen(MoiraId) != 0)
5533     {
5534       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
5535       attr_array[0] = "name";
5536       attr_array[1] = NULL;
5537       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
5538                                &group_base, &group_count, 
5539                                LDAP_SCOPE_SUBTREE)) != 0)
5540         {
5541           com_err(whoami, 0, "Unable to process user %s : %s",
5542                   user_name, ldap_err2string(rc));
5543           goto cleanup;
5544         }
5545     }
5546   
5547   if (group_count != 1)
5548     {
5549       linklist_free(group_base);
5550       group_count = 0;
5551       group_base = NULL;
5552       sprintf(filter, "(sAMAccountName=%s)", user_name);
5553       attr_array[0] = "name";
5554       attr_array[1] = NULL;
5555       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
5556                                &group_base, &group_count, 
5557                                LDAP_SCOPE_SUBTREE)) != 0)
5558         {
5559           com_err(whoami, 0, "Unable to process user %s : %s",
5560                   user_name, ldap_err2string(rc));
5561           goto cleanup;
5562         }
5563     }
5564
5565   if (group_count != 1)
5566     {
5567       com_err(whoami, 0, "Unable to find user %s in directory",
5568               user_name);
5569       goto cleanup;
5570     }
5571   
5572   strcpy(distinguished_name, group_base->dn);
5573
5574   if (rc = ldap_delete_s(ldap_handle, distinguished_name))
5575     {
5576       com_err(whoami, 0, "Unable to process user %s : %s",
5577               user_name, ldap_err2string(rc));
5578     }
5579
5580   /* Need to add code to delete mit.edu contact */
5581   
5582   if (Exchange)
5583     {
5584       sprintf(temp, "cn=%s@mit.edu,%s,%s", user_name, contact_ou, dn_path);
5585
5586       if(rc = ldap_delete_s(ldap_handle, temp))
5587         {
5588           com_err(whoami, 0, "Unable to delete user contact for %s",
5589                   user_name);
5590         }
5591     }
5592
5593  cleanup:
5594   linklist_free(group_base);
5595
5596   return(0);
5597 }
5598
5599 void linklist_free(LK_ENTRY *linklist_base)
5600 {
5601   LK_ENTRY *linklist_previous;
5602
5603   while (linklist_base != NULL)
5604     {
5605       if (linklist_base->dn != NULL)
5606         free(linklist_base->dn);
5607
5608       if (linklist_base->attribute != NULL)
5609         free(linklist_base->attribute);
5610
5611       if (linklist_base->value != NULL)
5612         free(linklist_base->value);
5613
5614       if (linklist_base->member != NULL)
5615         free(linklist_base->member);
5616
5617       if (linklist_base->type != NULL)
5618         free(linklist_base->type);
5619
5620       if (linklist_base->list != NULL)
5621         free(linklist_base->list);
5622
5623       linklist_previous = linklist_base;
5624       linklist_base = linklist_previous->next;
5625       free(linklist_previous);
5626     }
5627 }
5628
5629 void free_values(char **modvalues)
5630 {
5631   int i;
5632
5633   i = 0;
5634
5635   if (modvalues != NULL)
5636     {
5637     while (modvalues[i] != NULL)
5638       {
5639         free(modvalues[i]);
5640         modvalues[i] = NULL;
5641         ++i;
5642       }
5643     free(modvalues);
5644   }
5645 }
5646
5647 static int illegalchars[] = {
5648   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
5649   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
5650   1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, /* SPACE - / */
5651   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, /* 0 - ? */
5652   0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
5653   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, /* P - _ */
5654   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
5655   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
5656   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5657   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5658   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5659   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5660   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5661   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5662   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5663   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5664 };
5665
5666 static int illegalchars_ldap[] = {
5667   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^@ - ^O */
5668   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* ^P - ^_ */
5669   0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, /* SPACE - / */
5670   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, /* 0 - ? */
5671   0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* @ - O */
5672   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 0, /* P - _ */
5673   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* ` - o */
5674   0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, /* p - ^? */
5675   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5676   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5677   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5678   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5679   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5680   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5681   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5682   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
5683 };
5684
5685 int check_string(char *s)
5686 {
5687   char  character;
5688
5689   for (; *s; s++)
5690     {
5691       character = *s;
5692
5693       if (isupper(character))
5694         character = tolower(character);
5695
5696       if(ActiveDirectory)
5697         {
5698           if (illegalchars[(unsigned) character])
5699             {
5700               com_err(whoami, 0, "Found illegal char '%c' (%d) in string %s",
5701                       character, (unsigned) character, s);
5702               return 0;
5703             }
5704         }
5705       else
5706         {
5707           if (illegalchars_ldap[(unsigned) character])
5708             {
5709               com_err(whoami, 0, "Found illegal char '%c' (%d) in string %s",
5710                       character, (unsigned) character, s);
5711               return 0;
5712             }
5713         }
5714     }
5715
5716   return(1);
5717 }
5718
5719 int check_container_name(char *s)
5720 {
5721   char  character;
5722
5723   for (; *s; s++)
5724     {
5725       character = *s;
5726
5727       if (isupper(character))
5728         character = tolower(character);
5729
5730       if (character == ' ')
5731         continue;
5732
5733       if (illegalchars[(unsigned) character])
5734         return 0;
5735     }
5736
5737   return(1);
5738 }
5739
5740 int mr_connect_cl(char *server, char *client, int version, int auth)
5741 {
5742   int   status;
5743   char  *motd;
5744   char  temp[128];
5745
5746   status = mr_connect(server);
5747
5748   if (status)
5749     {
5750       com_err(whoami, status, "while connecting to Moira");
5751       return status;
5752     }
5753
5754   status = mr_motd(&motd);
5755
5756   if (status)
5757     {
5758       mr_disconnect();
5759       com_err(whoami, status, "while checking server status");
5760       return status;
5761     }
5762
5763   if (motd)
5764     {
5765       sprintf(temp, "The Moira server is currently unavailable: %s", motd);
5766       com_err(whoami, status, temp);
5767       mr_disconnect();
5768       return status;
5769     }
5770
5771   status = mr_version(version);
5772
5773   if (status)
5774     {
5775       if (status == MR_UNKNOWN_PROC)
5776         {
5777           if (version > 2)
5778             status = MR_VERSION_HIGH;
5779           else
5780             status = MR_SUCCESS;
5781         }
5782
5783       if (status == MR_VERSION_HIGH)
5784         {
5785           com_err(whoami, 0, "Warning: This client is running newer code "
5786                   "than the server.");
5787                   com_err(whoami, 0, "Some operations may not work.");
5788         }
5789       else if (status && status != MR_VERSION_LOW)
5790         {
5791           com_err(whoami, status, "while setting query version number.");
5792           mr_disconnect();
5793           return status;
5794         }
5795     }
5796
5797   if (auth)
5798     {
5799       status = mr_krb5_auth(client);
5800       if (status)
5801         {
5802           com_err(whoami, status, "while authenticating to Moira.");
5803           mr_disconnect();
5804           return status;
5805         }
5806     }
5807   
5808   return MR_SUCCESS;
5809 }
5810
5811 void AfsToWinAfs(char* path, char* winPath)
5812 {
5813   char* pathPtr;
5814   char* winPathPtr;
5815   strcpy(winPath, WINAFS);
5816   pathPtr = path + strlen(AFS);
5817   winPathPtr = winPath + strlen(WINAFS);
5818   
5819   while (*pathPtr)
5820     {
5821       if (*pathPtr == '/')
5822         *winPathPtr = '\\';
5823       else
5824         *winPathPtr = *pathPtr;
5825       
5826       pathPtr++;
5827       winPathPtr++;
5828     }
5829 }
5830
5831 int GetAceInfo(int ac, char **av, void *ptr)
5832 {
5833   char **call_args;
5834   int   security_flag;
5835
5836   call_args = ptr;
5837   
5838   strcpy(call_args[0], av[L_ACE_TYPE]);
5839   strcpy(call_args[1], av[L_ACE_NAME]);
5840   security_flag = 0;
5841   get_group_membership(call_args[2], call_args[3], &security_flag, av);
5842   return(LDAP_SUCCESS);  
5843 }
5844
5845 int checkADname(LDAP *ldap_handle, char *dn_path, char *Name)
5846 {
5847   char filter[128];
5848   char *attr_array[3];
5849   int  group_count;
5850   int  rc;
5851   LK_ENTRY  *group_base;
5852   
5853   group_count = 0;
5854   group_base = NULL;
5855   
5856   sprintf(filter, "(sAMAccountName=%s)", Name);
5857   attr_array[0] = "sAMAccountName";
5858   attr_array[1] = NULL;
5859
5860   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
5861                            &group_base, &group_count, 
5862                            LDAP_SCOPE_SUBTREE)) != 0)
5863     {
5864       com_err(whoami, 0, "Unable to process ACE name %s : %s",
5865               Name, ldap_err2string(rc));
5866       return(1);
5867     }
5868
5869   linklist_free(group_base);
5870   group_base = NULL;
5871
5872   if (group_count == 0)
5873     return(0);
5874   
5875   return(1);
5876 }
5877
5878 #define MAX_ACE 7
5879
5880 int ProcessAce(LDAP *ldap_handle, char *dn_path, char *Name, char *Type, 
5881                int UpdateGroup, int *ProcessGroup, char *maillist)
5882 {
5883   char  *av[2];
5884   char  GroupName[256];
5885   char  *call_args[7];
5886   int   rc;
5887   char  *AceInfo[4];
5888   char  AceType[32];
5889   char  AceName[128];
5890   char  AceMembership[2];
5891   char  AceOu[256];
5892   char  temp[128];
5893   char  *save_argv[U_END];
5894
5895   if (!SetGroupAce)
5896     {
5897       com_err(whoami, 0, "ProcessAce disabled, skipping");
5898       return(0);
5899     }
5900
5901   strcpy(GroupName, Name);
5902   
5903   if (strcasecmp(Type, "LIST"))
5904     return(1);
5905
5906   while (1)
5907     {
5908       av[0] = GroupName;
5909       AceInfo[0] = AceType;
5910       AceInfo[1] = AceName;
5911       AceInfo[2] = AceMembership;
5912       AceInfo[3] = AceOu;
5913       memset(AceType, '\0', sizeof(AceType));
5914       memset(AceName, '\0', sizeof(AceName));
5915       memset(AceMembership, '\0', sizeof(AceMembership));
5916       memset(AceOu, '\0', sizeof(AceOu));
5917       callback_rc = 0;
5918     
5919       if (rc = mr_query("get_list_info", 1, av, GetAceInfo, AceInfo))
5920         { 
5921           if(rc != MR_NO_MATCH)
5922             com_err(whoami, 0, "Unable to get ACE info for list %s : %s", 
5923                     GroupName, error_message(rc));
5924
5925           return(1);
5926         }
5927
5928       if (callback_rc)
5929         {
5930           com_err(whoami, 0, "Unable to get ACE info for list %s", GroupName);
5931           return(1);
5932         }
5933
5934       if ((strcasecmp(AceType, "USER")) && (strcasecmp(AceType, "LIST")))
5935         return(0);
5936
5937       strcpy(temp, AceName);
5938
5939       if (!strcasecmp(AceType, "LIST"))
5940         sprintf(temp, "%s%s", AceName, group_suffix);
5941
5942       if (!UpdateGroup)
5943         {
5944           if (checkADname(ldap_handle, dn_path, temp))
5945               return(0);
5946
5947           (*ProcessGroup) = 1;
5948         }
5949
5950       if (!strcasecmp(AceInfo[0], "LIST"))
5951         {
5952           if (make_new_group(ldap_handle, dn_path, "", AceName, AceOu, 
5953                              AceMembership, 0, UpdateGroup, maillist))
5954             return(1);
5955
5956           populate_group(ldap_handle, dn_path, AceName, AceOu, AceMembership,
5957                          0, "");
5958         }
5959       else if (!strcasecmp(AceInfo[0], "USER"))
5960         {
5961           av[0] = AceName;
5962           call_args[0] = (char *)ldap_handle;
5963           call_args[1] = dn_path;
5964           call_args[2] = "";
5965           call_args[3] = NULL;
5966           callback_rc = 0;
5967
5968           if(!strcasecmp(AceName, PRODUCTION_PRINCIPAL) ||
5969              !strcasecmp(AceName, TEST_PRINCIPAL))
5970             {
5971               return(1);
5972             }
5973
5974           if (rc = mr_query("get_user_account_by_login", 1, av, 
5975                             save_query_info, save_argv))
5976             {
5977               com_err(whoami, 0, "Unable to process user ACE %s for group %s.",
5978                       AceName, Name);
5979               return(1);
5980             }
5981
5982           if (rc = user_create(U_END, save_argv, call_args)) 
5983             {
5984               com_err(whoami, 0, "Unable to process user ACE %s for group %s.",
5985                       AceName, Name);
5986               return(1);
5987             }
5988           
5989           if (callback_rc)
5990             {
5991               com_err(whoami, 0, "Unable to process user Ace %s for group %s",
5992                       AceName, Name);
5993               return(1);
5994             }
5995
5996           return(0);
5997         }
5998       else
5999         return(1);
6000
6001       if (!strcasecmp(AceType, "LIST"))
6002         {
6003           if (!strcasecmp(GroupName, AceName))
6004             return(0);
6005         }
6006
6007       strcpy(GroupName, AceName);
6008     }
6009   
6010   return(1);
6011 }
6012
6013 int make_new_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
6014                    char *group_name, char *group_ou, char *group_membership, 
6015                    int group_security_flag, int updateGroup, char *maillist)
6016 {
6017   char  *av[3];
6018   char  *call_args[8];
6019   int   rc;
6020   LK_ENTRY  *group_base;
6021   int  group_count;
6022   char filter[128];
6023   char *attr_array[3];
6024
6025   av[0] = group_name;
6026   call_args[0] = (char *)ldap_handle;
6027   call_args[1] = dn_path;
6028   call_args[2] = group_name;
6029   call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS);
6030   call_args[4] = (char *)updateGroup;
6031   call_args[5] = MoiraId;
6032   call_args[6] = "0";
6033   call_args[7] = NULL;
6034   callback_rc = 0;
6035
6036   group_count = 0;
6037   group_base = NULL;
6038
6039   if (rc = mr_query("get_list_info", 1, av, group_create, call_args))
6040     {
6041       moira_disconnect();
6042       com_err(whoami, 0, "Unable to create list %s : %s", group_name, 
6043               error_message(rc));
6044       return(rc);
6045     }
6046
6047   if (callback_rc)
6048     {
6049       moira_disconnect();
6050       com_err(whoami, 0, "Unable to create list %s", group_name);
6051       return(callback_rc);
6052     }
6053
6054   return(0);
6055 }
6056
6057 int populate_group(LDAP *ldap_handle, char *dn_path, char *group_name, 
6058                    char *group_ou, char *group_membership, 
6059                    int group_security_flag, char *MoiraId)
6060 {
6061   char      *av[3];
6062   char      *call_args[7];
6063   char      *pUserOu;
6064   LK_ENTRY  *ptr;
6065   int       rc;
6066   char      member[512];
6067   char      *s;
6068   char      **members;
6069   int       i = 0;
6070   int       j = 0;
6071   int       n = 0;
6072   char      group_dn[512];
6073   LDAPMod   *mods[20];
6074   char      *member_v[] = {NULL, NULL};
6075   char      *save_argv[U_END];
6076   char      machine_ou[256];
6077   char      NewMachineName[1024];
6078
6079   com_err(whoami, 0, "Populating group %s", group_name);
6080   av[0] = group_name;
6081   call_args[0] = (char *)ldap_handle;
6082   call_args[1] = dn_path;
6083   call_args[2] = group_name;
6084   call_args[3] = (char *)(MOIRA_USERS | MOIRA_KERBEROS | MOIRA_STRINGS | 
6085                           MOIRA_MACHINE);
6086   call_args[4] = NULL;
6087   member_base = NULL;
6088
6089   if (rc = mr_query("get_end_members_of_list", 1, av,
6090                     member_list_build, call_args))
6091     {
6092       if(rc == MR_LIST)
6093         return(0);
6094       
6095       com_err(whoami, 0, "Unable to populate list %s : %s", 
6096               group_name, error_message(rc));
6097       return(3);
6098     }
6099
6100   members = (char **)malloc(sizeof(char *) * 2);
6101
6102   if (member_base != NULL)
6103     {
6104       ptr = member_base;
6105
6106       while (ptr != NULL)
6107         {
6108           if (!strcasecmp(ptr->type, "LIST"))
6109             {
6110               ptr = ptr->next;
6111               continue;
6112             }
6113           
6114           if (!strcasecmp(ptr->type, "MACHINE") && !ProcessMachineContainer)
6115             {
6116               ptr = ptr->next;
6117               continue;
6118             }
6119             
6120           if(!strcasecmp(ptr->type, "USER"))
6121             {
6122               if(!strcasecmp(ptr->member, PRODUCTION_PRINCIPAL) ||
6123                  !strcasecmp(ptr->member, TEST_PRINCIPAL))
6124                 {
6125                   ptr = ptr->next;
6126                   continue;
6127                 }
6128
6129               if ((rc = check_user(ldap_handle, dn_path, ptr->member,
6130                                    "")) == AD_NO_USER_FOUND)
6131                 {
6132                   com_err(whoami, 0, "creating user %s", ptr->member);
6133
6134                   av[0] = ptr->member;
6135                   call_args[0] = (char *)ldap_handle;
6136                   call_args[1] = dn_path;
6137                   call_args[2] = "";
6138                   call_args[3] = NULL;
6139                   callback_rc = 0;
6140                   
6141                   if (rc = mr_query("get_user_account_by_login", 1, av, 
6142                                     save_query_info, save_argv))
6143                     {
6144                       com_err(whoami, 0, "Unable to create user %s " 
6145                               "while populating group %s.", ptr->member,
6146                               group_name);
6147
6148                       return(3);
6149                     }
6150
6151                   if (rc = user_create(U_END, save_argv, call_args)) 
6152                     {
6153                       com_err(whoami, 0, "Unable to create user %s "
6154                               "while populating group %s.", ptr->member,
6155                               group_name);
6156                       
6157                       return(3);
6158                     }
6159           
6160                   if (callback_rc)
6161                     {
6162                       com_err(whoami, 0, "Unable to create user %s "
6163                               "while populating group %s", ptr->member, 
6164                               group_name);
6165
6166                       return(3);
6167                     }
6168                 }
6169
6170               pUserOu = user_ou;
6171                   
6172               if(ActiveDirectory) 
6173                 {
6174                   sprintf(member, "cn=%s,%s,%s", ptr->member, pUserOu, 
6175                           dn_path);
6176                 }
6177               else 
6178                 {
6179                   sprintf(member, "uid=%s,%s,%s", ptr->member, pUserOu, 
6180                           dn_path);
6181                 }
6182             }
6183           else if (!strcasecmp(ptr->type, "STRING"))
6184             {
6185               if (contact_create(ldap_handle, dn_path, ptr->member,
6186                                  contact_ou))
6187                 return(3);
6188
6189               pUserOu = contact_ou;
6190               sprintf(member, "cn=%s,%s,%s", escape_string(ptr->member), 
6191                       pUserOu, dn_path);
6192             }
6193           else if (!strcasecmp(ptr->type, "KERBEROS"))
6194             {
6195               if (contact_create(ldap_handle, dn_path, ptr->member, 
6196                                  kerberos_ou))
6197                 return(3);
6198
6199               pUserOu = kerberos_ou;
6200               sprintf(member, "cn=%s,%s,%s", escape_string(ptr->member), 
6201                       pUserOu, dn_path);
6202             }
6203           else if (!strcasecmp(ptr->type, "MACHINE"))
6204             {
6205               memset(machine_ou, '\0', sizeof(machine_ou));
6206               memset(NewMachineName, '\0', sizeof(NewMachineName));
6207
6208               if (!get_machine_ou(ldap_handle, dn_path, ptr->member,
6209                                  machine_ou, NewMachineName))
6210                 {
6211                   pUserOu = machine_ou;
6212                   sprintf(member, "cn=%s,%s,%s", NewMachineName, pUserOu,
6213                           dn_path);
6214                 }
6215               else
6216                 {
6217                   ptr = ptr->next;                  
6218                   continue;
6219                 }
6220             }
6221
6222           if(i > 1) 
6223             members = (char **)realloc(members, ((i + 2) * sizeof(char *)));
6224           members[i++] = strdup(member);
6225
6226           ptr = ptr->next;
6227         }
6228     
6229       linklist_free(member_base);
6230       member_base = NULL;
6231     }
6232
6233   members[i] = NULL;
6234
6235   sprintf(group_dn, "cn=%s,%s,%s", group_name, group_ou, dn_path);
6236
6237   if(GroupPopulateDelete)
6238     {
6239       n = 0;
6240       ADD_ATTR("member", member_v, LDAP_MOD_REPLACE);
6241       mods[n] = NULL;
6242       
6243       if ((rc = ldap_modify_s(ldap_handle, group_dn, 
6244                               mods)) != LDAP_SUCCESS)
6245         {
6246           com_err(whoami, 0,
6247                   "Unable to populate group membership for %s: %s",
6248                   group_dn, ldap_err2string(rc));
6249         }
6250   
6251       for (i = 0; i < n; i++)
6252         free(mods[i]);
6253     }
6254
6255   n = 0;
6256   ADD_ATTR("member", members, LDAP_MOD_REPLACE);
6257   mods[n] = NULL;
6258
6259   if ((rc = ldap_modify_s(ldap_handle, group_dn, 
6260                           mods)) != LDAP_SUCCESS)
6261     {
6262       com_err(whoami, 0,
6263               "Unable to populate group membership for %s: %s",
6264               group_dn, ldap_err2string(rc));
6265     }
6266   
6267   for (i = 0; i < n; i++)
6268     free(mods[i]);
6269     
6270   free(members);
6271
6272   return(0);
6273 }
6274
6275 int process_group(LDAP *ldap_handle, char *dn_path, char *MoiraId, 
6276                   char *group_name, char *group_ou, char *group_membership, 
6277                   int group_security_flag, int type, char *maillist)
6278 {
6279   char      before_desc[512];
6280   char      before_name[256];
6281   char      before_group_ou[256];
6282   char      before_group_membership[2];
6283   char      distinguishedName[256];
6284   char      ad_distinguishedName[256];
6285   char      filter[128];
6286   char      *attr_array[3];
6287   int       before_security_flag;
6288   int       group_count;
6289   int       rc;
6290   LK_ENTRY  *group_base;
6291   LK_ENTRY  *ptr;
6292   char      ou_both[512];
6293   char      ou_security[512];
6294   char      ou_distribution[512];
6295   char      ou_neither[512];
6296   char      group_dn[512];
6297
6298   memset(ad_distinguishedName, '\0', sizeof(ad_distinguishedName));
6299   sprintf(distinguishedName, "CN=%s,%s,%s", group_name, group_ou, dn_path);
6300
6301   memset(filter, '\0', sizeof(filter));
6302   group_base = NULL;
6303   group_count = 0;
6304
6305   if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
6306                         "*", MoiraId, 
6307                         "samAccountName", &group_base, 
6308                         &group_count, filter))
6309     return(rc);
6310
6311   if (type == CHECK_GROUPS)
6312     {
6313       if (group_count == 1)
6314         {
6315           strcpy(group_dn, group_base->dn);
6316
6317           if (!strcasecmp(group_dn, distinguishedName))
6318             {
6319               linklist_free(group_base);
6320               return(0);
6321             }
6322         }
6323
6324       linklist_free(group_base);
6325
6326       if (group_count == 0)
6327         return(AD_NO_GROUPS_FOUND);
6328
6329       if (group_count == 1)
6330         return(AD_WRONG_GROUP_DN_FOUND);
6331
6332       return(AD_MULTIPLE_GROUPS_FOUND);
6333     }
6334
6335   if (group_count == 0)
6336     {
6337       return(AD_NO_GROUPS_FOUND);
6338     }
6339
6340   if (group_count > 1)
6341     {
6342       ptr = group_base;
6343
6344       strcpy(group_dn, ptr->dn);
6345
6346       while (ptr != NULL)
6347         {
6348           if (!strcasecmp(group_dn, ptr->value))
6349             break;
6350
6351           ptr = ptr->next;
6352         }
6353
6354       if (ptr == NULL)
6355         {
6356           com_err(whoami, 0, "%d groups with moira id = %s", group_count, 
6357                   MoiraId);
6358           ptr = group_base;
6359
6360           while (ptr != NULL)
6361             {
6362               com_err(whoami, 0, "%s with moira id = %s", ptr->value, MoiraId);
6363               ptr = ptr->next;
6364             }
6365
6366           linklist_free(group_base);
6367           return(AD_MULTIPLE_GROUPS_FOUND);
6368         }
6369
6370       ptr = group_base;
6371
6372       while (ptr != NULL)
6373         {
6374           strcpy(group_dn, ptr->dn);
6375
6376           if (strcasecmp(group_dn, ptr->value))
6377             rc = ldap_delete_s(ldap_handle, ptr->value);
6378
6379           ptr = ptr->next;
6380         }
6381
6382       linklist_free(group_base);
6383       memset(filter, '\0', sizeof(filter));
6384       group_base = NULL;
6385       group_count = 0;
6386
6387       if (rc = ad_get_group(ldap_handle, dn_path, group_name, 
6388                             "*", MoiraId, 
6389                             "samAccountName", &group_base, 
6390                             &group_count, filter))
6391         return(rc);
6392
6393       if (group_count == 0)
6394         return(AD_NO_GROUPS_FOUND);
6395
6396       if (group_count > 1)
6397         return(AD_MULTIPLE_GROUPS_FOUND);
6398     }
6399
6400   strcpy(ad_distinguishedName, group_base->dn);
6401   linklist_free(group_base);
6402   group_base = NULL;
6403   group_count = 0;
6404
6405   attr_array[0] = "sAMAccountName";
6406   attr_array[1] = NULL;
6407   
6408   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6409                            &group_base, &group_count, 
6410                            LDAP_SCOPE_SUBTREE)) != 0)
6411     {
6412       com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6413               MoiraId, ldap_err2string(rc));
6414       return(rc);
6415     }
6416   
6417   sprintf(filter, "(sAMAccountName=%s)", group_base->value);
6418
6419   if (!strcasecmp(ad_distinguishedName, distinguishedName))
6420     {
6421       linklist_free(group_base);
6422       group_base = NULL;
6423       group_count = 0;
6424       return(0);
6425     }
6426
6427   linklist_free(group_base);
6428   group_base = NULL;
6429   group_count = 0;
6430   memset(ou_both, '\0', sizeof(ou_both));
6431   memset(ou_security, '\0', sizeof(ou_security));
6432   memset(ou_distribution, '\0', sizeof(ou_distribution));
6433   memset(ou_neither, '\0', sizeof(ou_neither));
6434   memset(before_name, '\0', sizeof(before_name));
6435   memset(before_desc, '\0', sizeof(before_desc));
6436   memset(before_group_membership, '\0', sizeof(before_group_membership));
6437   
6438   attr_array[0] = "name";
6439   attr_array[1] = NULL;
6440
6441   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6442                            &group_base, &group_count, 
6443                            LDAP_SCOPE_SUBTREE)) != 0)
6444     {
6445       com_err(whoami, 0, "Unable to get list name with MoiraId = %s: %s",
6446               MoiraId, ldap_err2string(rc));
6447       return(rc);
6448     }
6449
6450   strcpy(before_name, group_base->value);
6451   linklist_free(group_base);
6452   group_base = NULL;
6453   group_count = 0;
6454
6455   attr_array[0] = "description";
6456   attr_array[1] = NULL;
6457   
6458   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6459                            &group_base, &group_count, 
6460                            LDAP_SCOPE_SUBTREE)) != 0)
6461     {
6462       com_err(whoami, 0, 
6463               "Unable to get list description with MoiraId = %s: %s",
6464               MoiraId, ldap_err2string(rc));
6465       return(rc);
6466     }
6467
6468   if (group_count != 0)
6469     {
6470       strcpy(before_desc, group_base->value);
6471       linklist_free(group_base);
6472       group_base = NULL;
6473       group_count = 0;
6474     }
6475  
6476   change_to_lower_case(ad_distinguishedName);  
6477   strcpy(ou_both, group_ou_both);
6478   change_to_lower_case(ou_both);
6479   strcpy(ou_security, group_ou_security);
6480   change_to_lower_case(ou_security);
6481   strcpy(ou_distribution, group_ou_distribution);
6482   change_to_lower_case(ou_distribution);
6483   strcpy(ou_neither, group_ou_neither);
6484   change_to_lower_case(ou_neither);
6485
6486   if (strstr(ad_distinguishedName, ou_both))
6487     {
6488       strcpy(before_group_ou, group_ou_both);
6489       before_group_membership[0] = 'B';
6490       before_security_flag = 1;
6491     }
6492   else if (strstr(ad_distinguishedName, ou_security))
6493     {
6494       strcpy(before_group_ou, group_ou_security);
6495       before_group_membership[0] = 'S';
6496       before_security_flag = 1;
6497     }
6498   else if (strstr(ad_distinguishedName, ou_distribution))
6499     {
6500       strcpy(before_group_ou, group_ou_distribution);
6501       before_group_membership[0] = 'D';
6502       before_security_flag = 0;
6503     }
6504   else if (strstr(ad_distinguishedName, ou_neither))
6505     {
6506       strcpy(before_group_ou, group_ou_neither);
6507       before_group_membership[0] = 'N';
6508       before_security_flag = 0;
6509     }
6510   else
6511     return(AD_NO_OU_FOUND);
6512
6513   rc = group_rename(ldap_handle, dn_path, before_name, 
6514                     before_group_membership, 
6515                     before_group_ou, before_security_flag, before_desc,
6516                     group_name, group_membership, group_ou, 
6517                     group_security_flag,
6518                     before_desc, MoiraId, filter, maillist);
6519
6520   return(rc);
6521 }
6522
6523 void change_to_lower_case(char *ptr)
6524 {
6525   int i;
6526
6527   for (i = 0; i < (int)strlen(ptr); i++)
6528     {
6529       ptr[i] = tolower(ptr[i]);
6530     }
6531 }
6532
6533 int ad_get_group(LDAP *ldap_handle, char *dn_path, 
6534                  char *group_name, char *group_membership, 
6535                  char *MoiraId, char *attribute,
6536                  LK_ENTRY **linklist_base, int *linklist_count,
6537                  char *rFilter)
6538 {
6539   LK_ENTRY  *pPtr;
6540   char  filter[128];
6541   char  *attr_array[3];
6542   char  *dn;
6543   int   rc;
6544
6545   (*linklist_base) = NULL;
6546   (*linklist_count) = 0;
6547
6548   if (strlen(rFilter) != 0)
6549     {
6550       strcpy(filter, rFilter);
6551       attr_array[0] = attribute;
6552       attr_array[1] = NULL;
6553       
6554       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6555                                linklist_base, linklist_count, 
6556                                LDAP_SCOPE_SUBTREE)) != 0)
6557         {
6558           com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6559                   MoiraId, ldap_err2string(rc));
6560          return(rc);
6561        }
6562
6563     if ((*linklist_count) == 1)
6564       {
6565         strcpy(rFilter, filter);
6566         return(0);
6567       }
6568     }
6569
6570   linklist_free((*linklist_base));
6571   (*linklist_base) = NULL;
6572   (*linklist_count) = 0;
6573
6574   if (strlen(MoiraId) != 0)
6575     {
6576       sprintf(filter, "(&(objectClass=group)(mitMoiraId=%s))", MoiraId);
6577
6578       attr_array[0] = attribute;
6579       attr_array[1] = NULL;
6580
6581       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6582                                linklist_base, linklist_count, 
6583                                LDAP_SCOPE_SUBTREE)) != 0)
6584         {
6585           com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6586                   MoiraId, ldap_err2string(rc));
6587          return(rc);
6588        }
6589     }
6590
6591   if ((*linklist_count) > 1)
6592     {
6593       com_err(whoami, 0, "multiple groups with mitMoiraId = %s", MoiraId);
6594       pPtr = (*linklist_base);
6595
6596       while (pPtr)
6597         {
6598           com_err(whoami, 0, "groups %s has mitMoiraId = %s", pPtr->value, 
6599                   MoiraId);
6600           pPtr = pPtr->next;
6601         }
6602
6603       linklist_free((*linklist_base));
6604       (*linklist_base) = NULL;
6605       (*linklist_count) = 0;
6606     }
6607
6608   if ((*linklist_count) == 1)
6609     {
6610
6611       pPtr = (*linklist_base);
6612       dn = strdup(pPtr->dn);
6613       dn += 3;
6614
6615       if (!memcmp(dn, group_name, strlen(group_name)))
6616         {
6617           strcpy(rFilter, filter);
6618           return(0);
6619         }
6620     }
6621
6622   linklist_free((*linklist_base));
6623   (*linklist_base) = NULL;
6624   (*linklist_count) = 0;
6625   sprintf(filter, "(sAMAccountName=%s%s)", group_name, group_suffix);
6626
6627   attr_array[0] = attribute;
6628   attr_array[1] = NULL;
6629
6630   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6631                            linklist_base, linklist_count, 
6632                            LDAP_SCOPE_SUBTREE)) != 0)
6633     {
6634       com_err(whoami, 0, "Unable to get list info with MoiraId = %s: %s",
6635               MoiraId, ldap_err2string(rc));
6636       return(rc);
6637     }
6638
6639   if ((*linklist_count) == 1)
6640     {
6641       strcpy(rFilter, filter);
6642       return(0);
6643     }
6644
6645   return(0);
6646 }
6647
6648 int check_user(LDAP *ldap_handle, char *dn_path, char *UserName, char *MoiraId)
6649 {
6650   char filter[128];
6651   char *attr_array[3];
6652   char SamAccountName[64];
6653   int  group_count;
6654   int  rc;
6655   LK_ENTRY  *group_base;
6656   LK_ENTRY  *gPtr;
6657
6658   group_count = 0;
6659   group_base = NULL;
6660
6661   if (strlen(MoiraId) != 0)
6662     {
6663       sprintf(filter, "(&(objectClass=user)(mitMoiraId=%s))", MoiraId);
6664
6665       attr_array[0] = "sAMAccountName";
6666       attr_array[1] = NULL;
6667       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6668                                &group_base, &group_count, 
6669                                LDAP_SCOPE_SUBTREE)) != 0)
6670         {
6671           com_err(whoami, 0, "Unable to process user %s : %s",
6672                   UserName, ldap_err2string(rc));
6673           return(rc);
6674         }
6675
6676       if (group_count > 1)
6677         {
6678           com_err(whoami, 0, "multiple users exist with MoiraId = %s",
6679                   MoiraId);
6680           gPtr = group_base;
6681
6682           while (gPtr)
6683             {
6684               com_err(whoami, 0, "user %s exist with MoiraId = %s",
6685                       gPtr->value, MoiraId);
6686               gPtr = gPtr->next;
6687             }
6688         }
6689     }
6690
6691   if (group_count != 1)
6692     {
6693       linklist_free(group_base);
6694       group_count = 0;
6695       group_base = NULL;
6696       sprintf(filter, "(sAMAccountName=%s)", UserName);
6697       attr_array[0] = "sAMAccountName";
6698       attr_array[1] = NULL;
6699
6700       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
6701                                &group_base, &group_count, 
6702                                LDAP_SCOPE_SUBTREE)) != 0)
6703         {
6704           com_err(whoami, 0, "Unable to process user %s : %s",
6705                   UserName, ldap_err2string(rc));
6706           return(rc);
6707         }
6708     }
6709
6710   if (group_count != 1)
6711     {
6712       linklist_free(group_base);
6713       return(AD_NO_USER_FOUND);
6714     }
6715
6716   strcpy(SamAccountName, group_base->value);
6717   linklist_free(group_base);
6718   group_count = 0;
6719   rc = 0;
6720
6721   if (strcmp(SamAccountName, UserName))
6722     {
6723       com_err(whoami, 0, 
6724               "User object %s with MoiraId %s has mismatched usernames " 
6725               "(LDAP username %s, Moira username %s)", SamAccountName,
6726               MoiraId, SamAccountName, UserName);
6727     }
6728
6729   return(0);
6730 }
6731
6732 void container_get_dn(char *src, char *dest)
6733 {
6734   char *sPtr;
6735   char *array[20];
6736   char name[256];
6737   int  n;
6738
6739   memset(array, '\0', 20 * sizeof(array[0]));
6740
6741   if (strlen(src) == 0)
6742     return;
6743
6744   strcpy(name, src);
6745   sPtr = name;
6746   n = 0;
6747   array[n] = name;
6748   ++n;
6749
6750   while (*sPtr)
6751     {
6752       if ((*sPtr) == '/')
6753         {
6754           (*sPtr) = '\0';
6755           ++sPtr;
6756           array[n] = sPtr;
6757           ++n;
6758         }
6759       else
6760         ++sPtr;
6761     }
6762
6763   strcpy(dest, "OU=");
6764
6765   while (n != 0)
6766     {
6767       strcat(dest, array[n-1]);
6768       --n;
6769       if (n > 0)
6770         {
6771           strcat(dest, ",OU=");
6772         }
6773     }
6774
6775   return;
6776 }
6777
6778 void container_get_name(char *src, char *dest)
6779 {
6780   char *sPtr;
6781   char *dPtr;
6782
6783   if (strlen(src) == 0)
6784     return;
6785
6786   sPtr = src;
6787   dPtr = src;
6788
6789   while (*sPtr)
6790     {
6791       if ((*sPtr) == '/')
6792         {
6793           dPtr = sPtr;
6794           ++dPtr;
6795         }
6796       ++sPtr;
6797     }
6798
6799   strcpy(dest, dPtr);
6800   return;
6801 }
6802
6803 void container_check(LDAP *ldap_handle, char *dn_path, char *name)
6804 {
6805   char cName[256];
6806   char *av[7];
6807   int  i;
6808   int  rc;
6809
6810   strcpy(cName, name);
6811
6812   for (i = 0; i < (int)strlen(cName); i++)
6813     {
6814       if (cName[i] == '/')
6815         {
6816           cName[i] = '\0';
6817           av[CONTAINER_NAME] = cName;
6818           av[CONTAINER_DESC] = "";
6819           av[CONTAINER_LOCATION] = "";
6820           av[CONTAINER_CONTACT] = "";
6821           av[CONTAINER_TYPE] = "";
6822           av[CONTAINER_ID] = "";
6823           av[CONTAINER_ROWID] = "";
6824           rc = container_create(ldap_handle, dn_path, 7, av);
6825
6826           if (rc == LDAP_SUCCESS)
6827             {
6828               com_err(whoami, 0, "container %s created without a mitMoiraId", 
6829                       cName);
6830             }
6831
6832           cName[i] = '/';
6833         }
6834     }
6835 }
6836
6837 int container_rename(LDAP *ldap_handle, char *dn_path, int beforec, 
6838                      char **before, int afterc, char **after)
6839 {
6840   char      dName[256];
6841   char      cName[256];
6842   char      new_cn[128];
6843   char      new_dn_path[256];
6844   char      temp[256];
6845   char      distinguishedName[256];
6846   char      *pPtr;
6847   int       rc;
6848   int       i;
6849
6850   memset(cName, '\0', sizeof(cName));
6851   container_get_name(after[CONTAINER_NAME], cName);
6852
6853   if (!check_container_name(cName))
6854     {
6855       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", 
6856               cName);
6857       return(AD_INVALID_NAME);
6858     }
6859
6860   memset(distinguishedName, '\0', sizeof(distinguishedName));
6861
6862   if (rc = container_get_distinguishedName(ldap_handle, dn_path, 
6863                                            distinguishedName, beforec, before))
6864     return(rc);
6865
6866   if (strlen(distinguishedName) == 0)
6867     {
6868       rc = container_create(ldap_handle, dn_path, afterc, after);
6869       return(rc);
6870     }
6871
6872   strcpy(temp, after[CONTAINER_NAME]);
6873   pPtr = temp;
6874
6875   for (i = 0; i < (int)strlen(temp); i++)
6876     {
6877       if (temp[i] == '/')
6878         {
6879           pPtr = &temp[i];
6880         }
6881     }
6882
6883   (*pPtr) = '\0';
6884
6885   container_get_dn(temp, dName);
6886
6887   if (strlen(temp) != 0)
6888     sprintf(new_dn_path, "%s,%s", dName, dn_path);
6889   else
6890     sprintf(new_dn_path, "%s", dn_path);
6891
6892   sprintf(new_cn, "OU=%s", cName);
6893
6894   container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
6895
6896   if ((rc = ldap_rename_s(ldap_handle, distinguishedName, new_cn, new_dn_path,
6897                           TRUE, NULL, NULL)) != LDAP_SUCCESS)
6898     {
6899       com_err(whoami, 0, "Unable to rename container from %s to %s : %s",
6900               before[CONTAINER_NAME], after[CONTAINER_NAME], 
6901               ldap_err2string(rc));
6902       return(rc);
6903     }
6904
6905   memset(dName, '\0', sizeof(dName));
6906   container_get_dn(after[CONTAINER_NAME], dName);
6907   rc = container_adupdate(ldap_handle, dn_path, dName, "", afterc, after);
6908
6909   return(rc);
6910 }
6911
6912 int container_delete(LDAP *ldap_handle, char *dn_path, int count, char **av)
6913 {
6914   char      distinguishedName[256];
6915   int       rc;
6916
6917   memset(distinguishedName, '\0', sizeof(distinguishedName));
6918
6919   if (rc = container_get_distinguishedName(ldap_handle, dn_path, 
6920                                            distinguishedName, count, av))
6921     return(rc);
6922
6923   if (strlen(distinguishedName) == 0)
6924     return(0);
6925
6926   if ((rc = ldap_delete_s(ldap_handle, distinguishedName)) != LDAP_SUCCESS)
6927     {
6928       if (rc == LDAP_NOT_ALLOWED_ON_NONLEAF)
6929         container_move_objects(ldap_handle, dn_path, distinguishedName);
6930       else
6931         com_err(whoami, 0, "Unable to delete container %s from directory : %s",
6932                 av[CONTAINER_NAME], ldap_err2string(rc));
6933     }
6934
6935   return(rc);
6936 }
6937
6938 int container_create(LDAP *ldap_handle, char *dn_path, int count, char **av)
6939 {
6940   char      *attr_array[3];
6941   LK_ENTRY  *group_base;
6942   int       group_count;
6943   LDAPMod   *mods[20];
6944   char      *objectClass_v[] = {"top", 
6945                            "organizationalUnit", 
6946                            NULL};
6947
6948   char *ou_v[] = {NULL, NULL};
6949   char *name_v[] = {NULL, NULL};
6950   char *moiraId_v[] = {NULL, NULL};
6951   char *desc_v[] = {NULL, NULL};
6952   char *managedBy_v[] = {NULL, NULL};
6953   char dName[256];
6954   char cName[256];
6955   char managedByDN[256];
6956   char filter[256];
6957   char temp[256];
6958   int  n;
6959   int  i;
6960   int  rc;
6961     
6962   memset(filter, '\0', sizeof(filter));
6963   memset(dName, '\0', sizeof(dName));
6964   memset(cName, '\0', sizeof(cName));
6965   memset(managedByDN, '\0', sizeof(managedByDN));
6966   container_get_dn(av[CONTAINER_NAME], dName);
6967   container_get_name(av[CONTAINER_NAME], cName);
6968
6969   if ((strlen(cName) == 0) || (strlen(dName) == 0))
6970     {
6971       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", 
6972               cName);
6973       return(AD_INVALID_NAME);
6974     }
6975
6976   if (!check_container_name(cName))
6977     {
6978       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", 
6979               cName);
6980       return(AD_INVALID_NAME);
6981     }
6982
6983   n = 0;
6984   ADD_ATTR("objectClass", objectClass_v, LDAP_MOD_ADD);
6985   name_v[0] = cName;
6986   ADD_ATTR("name", name_v, LDAP_MOD_ADD);
6987   ou_v[0] = cName;
6988   ADD_ATTR("ou", ou_v, LDAP_MOD_ADD);
6989
6990   if (strlen(av[CONTAINER_ROWID]) != 0)
6991     {
6992       moiraId_v[0] = av[CONTAINER_ROWID];
6993       ADD_ATTR("mitMoiraId", moiraId_v, LDAP_MOD_ADD);
6994     }
6995
6996   if (strlen(av[CONTAINER_DESC]) != 0)
6997     {
6998       desc_v[0] = av[CONTAINER_DESC];
6999       ADD_ATTR("description", desc_v, LDAP_MOD_ADD);
7000     }
7001
7002   if ((strlen(av[CONTAINER_TYPE]) != 0) && (strlen(av[CONTAINER_ID]) != 0))
7003     {
7004       if (!strcasecmp(av[CONTAINER_TYPE], "KERBEROS"))
7005         {
7006           if (!contact_create(ldap_handle, dn_path, av[CONTAINER_ID], 
7007                               kerberos_ou))
7008             {
7009               sprintf(managedByDN, "CN=%s,%s,%s", av[CONTAINER_ID], 
7010                       kerberos_ou, dn_path);
7011               managedBy_v[0] = managedByDN;
7012               ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_ADD);
7013             }
7014         }
7015       else
7016         {
7017           if (!strcasecmp(av[CONTAINER_TYPE], "USER"))
7018             {
7019               sprintf(filter, "(&(cn=%s)(&(objectCategory=person)"
7020                       "(objectClass=user)))", av[CONTAINER_ID]);
7021             }
7022
7023           if (!strcasecmp(av[CONTAINER_TYPE], "LIST"))
7024             {
7025               sprintf(filter, "(&(objectClass=group)(cn=%s))", 
7026                       av[CONTAINER_ID]);
7027             }
7028
7029           if (strlen(filter) != 0)
7030             {
7031               attr_array[0] = "distinguishedName";
7032               attr_array[1] = NULL;
7033               group_count = 0;
7034               group_base = NULL;
7035               if ((rc = linklist_build(ldap_handle, dn_path, filter, 
7036                                        attr_array, 
7037                                        &group_base, &group_count, 
7038                                        LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7039                 {
7040                   if (group_count == 1)
7041                     {
7042                       strcpy(managedByDN, group_base->value);
7043                       managedBy_v[0] = managedByDN;
7044                       ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_ADD);
7045                     }
7046                   linklist_free(group_base);
7047                   group_base = NULL;
7048                   group_count = 0;
7049                 }
7050             }
7051         }
7052     }
7053   
7054   mods[n] = NULL;
7055
7056   sprintf(temp, "%s,%s", dName, dn_path);
7057   rc = ldap_add_ext_s(ldap_handle, temp, mods, NULL, NULL);
7058   
7059   for (i = 0; i < n; i++)
7060     free(mods[i]);
7061   
7062   if ((rc != LDAP_SUCCESS) && (rc != LDAP_ALREADY_EXISTS))
7063     {
7064       com_err(whoami, 0, "Unable to create container %s : %s",
7065               cName, ldap_err2string(rc));
7066       return(rc);
7067     }
7068
7069   if (rc == LDAP_ALREADY_EXISTS)
7070     {
7071       if (strlen(av[CONTAINER_ROWID]) != 0)
7072         rc = container_adupdate(ldap_handle, dn_path, dName, "", count, av);
7073     }
7074
7075   return(rc);
7076 }
7077
7078 int container_update(LDAP *ldap_handle, char *dn_path, int beforec, 
7079                      char **before, int afterc, char **after)
7080 {
7081   char distinguishedName[256];
7082   int  rc;
7083
7084   memset(distinguishedName, '\0', sizeof(distinguishedName));
7085
7086   if (rc = container_get_distinguishedName(ldap_handle, dn_path, 
7087                                            distinguishedName, afterc, after))
7088     return(rc);
7089
7090   if (strlen(distinguishedName) == 0)
7091     {
7092       rc = container_create(ldap_handle, dn_path, afterc, after);
7093       return(rc);
7094     }
7095   
7096   container_check(ldap_handle, dn_path, after[CONTAINER_NAME]);
7097   rc = container_adupdate(ldap_handle, dn_path, "", distinguishedName, afterc,
7098                           after);
7099
7100   return(rc);
7101 }
7102
7103 int container_get_distinguishedName(LDAP *ldap_handle, char *dn_path, 
7104                                     char *distinguishedName, int count, 
7105                                     char **av)
7106 {
7107   char      *attr_array[3];
7108   LK_ENTRY  *group_base;
7109   int       group_count;
7110   char      dName[256];
7111   char      cName[256];
7112   char      filter[512];
7113   int       rc;
7114
7115   memset(filter, '\0', sizeof(filter));
7116   memset(dName, '\0', sizeof(dName));
7117   memset(cName, '\0', sizeof(cName));
7118   container_get_dn(av[CONTAINER_NAME], dName);
7119   container_get_name(av[CONTAINER_NAME], cName);
7120
7121   if (strlen(dName) == 0)
7122     {
7123       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", 
7124               av[CONTAINER_NAME]);
7125       return(AD_INVALID_NAME);
7126     }
7127
7128   if (!check_container_name(cName))
7129     {
7130       com_err(whoami, 0, "Unable to process invalid LDAP container name %s", 
7131               cName);
7132       return(AD_INVALID_NAME);
7133     }
7134   
7135   sprintf(filter, "(&(objectClass=organizationalUnit)(mitMoiraId=%s))", 
7136           av[CONTAINER_ROWID]);
7137   attr_array[0] = "distinguishedName";
7138   attr_array[1] = NULL;
7139   group_count = 0;
7140   group_base = NULL;
7141
7142   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
7143                            &group_base, &group_count, 
7144                            LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7145     {
7146       if (group_count == 1)
7147         {
7148           strcpy(distinguishedName, group_base->value);
7149         }
7150
7151       linklist_free(group_base);
7152       group_base = NULL;
7153       group_count = 0;
7154     }
7155
7156   if (strlen(distinguishedName) == 0)
7157     {
7158       sprintf(filter, "(&(objectClass=organizationalUnit)"
7159               "(distinguishedName=%s,%s))", dName, dn_path);
7160       attr_array[0] = "distinguishedName";
7161       attr_array[1] = NULL;
7162       group_count = 0;
7163       group_base = NULL;
7164
7165       if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
7166                                &group_base, &group_count, 
7167                                LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7168         {
7169           if (group_count == 1)
7170             {
7171               strcpy(distinguishedName, group_base->value);
7172             }
7173
7174           linklist_free(group_base);
7175           group_base = NULL;
7176           group_count = 0;
7177         }
7178     }
7179
7180   return(0);
7181 }
7182
7183 int container_adupdate(LDAP *ldap_handle, char *dn_path, char *dName, 
7184                        char *distinguishedName, int count, char **av)
7185 {
7186   char      *attr_array[5];
7187   LK_ENTRY  *group_base;
7188   LK_ENTRY  *pPtr;
7189   LDAPMod   *mods[20];
7190   int       group_count;
7191   char      filter[512];
7192   char      *moiraId_v[] = {NULL, NULL};
7193   char      *desc_v[] = {NULL, NULL};
7194   char      *managedBy_v[] = {NULL, NULL};
7195   char      managedByDN[256];
7196   char      moiraId[64];
7197   char      desc[256];
7198   char      ad_path[512];
7199   int       rc;
7200   int       i;
7201   int       n;
7202
7203
7204   strcpy(ad_path, distinguishedName);
7205
7206   if (strlen(dName) != 0)
7207     sprintf(ad_path, "%s,%s", dName, dn_path);
7208
7209   sprintf(filter, "(&(objectClass=organizationalUnit)(distinguishedName=%s))",
7210           ad_path);
7211
7212   if (strlen(av[CONTAINER_ID]) != 0)
7213     sprintf(filter, "(&(objectClass=organizationalUnit)(mitMoiraId=%s))", 
7214             av[CONTAINER_ROWID]);
7215
7216   attr_array[0] = "mitMoiraId";
7217   attr_array[1] = "description";
7218   attr_array[2] = "managedBy";
7219   attr_array[3] = NULL;
7220   group_count = 0;
7221   group_base = NULL;
7222
7223   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
7224                            &group_base, &group_count, 
7225                            LDAP_SCOPE_SUBTREE)) != LDAP_SUCCESS)
7226     {
7227       com_err(whoami, 0, "Unable to retreive container info for %s : %s",
7228               av[CONTAINER_NAME], ldap_err2string(rc));
7229       return(rc);
7230     }
7231
7232   memset(managedByDN, '\0', sizeof(managedByDN));
7233   memset(moiraId, '\0', sizeof(moiraId));
7234   memset(desc, '\0', sizeof(desc));
7235   pPtr = group_base;
7236
7237   while (pPtr)
7238     {
7239       if (!strcasecmp(pPtr->attribute, "description"))
7240         strcpy(desc, pPtr->value);
7241       else if (!strcasecmp(pPtr->attribute, "managedBy"))
7242         strcpy(managedByDN, pPtr->value);
7243       else if (!strcasecmp(pPtr->attribute, "mitMoiraId"))
7244         strcpy(moiraId, pPtr->value);
7245       pPtr = pPtr->next;
7246     }
7247
7248   linklist_free(group_base);
7249   group_base = NULL;
7250   group_count = 0;
7251
7252   n = 0;
7253   if (strlen(av[CONTAINER_ROWID]) != 0)
7254     {
7255       moiraId_v[0] = av[CONTAINER_ROWID];
7256       ADD_ATTR("mitMoiraId", moiraId_v, LDAP_MOD_REPLACE);
7257     }
7258
7259   if (strlen(av[CONTAINER_DESC]) != 0)
7260     {
7261       attribute_update(ldap_handle, ad_path, av[CONTAINER_DESC], "description",
7262                        dName);
7263     }
7264   else
7265     {
7266       if (strlen(desc) != 0)
7267         {
7268           attribute_update(ldap_handle, ad_path, "", "description", dName);
7269         }
7270     }
7271
7272   if ((strlen(av[CONTAINER_TYPE]) != 0) && (strlen(av[CONTAINER_ID]) != 0))
7273     {
7274       if (!strcasecmp(av[CONTAINER_TYPE], "KERBEROS"))
7275         {
7276           if (!contact_create(ldap_handle, dn_path, av[CONTAINER_ID], 
7277                               kerberos_ou))
7278             {
7279               sprintf(managedByDN, "CN=%s,%s,%s", av[CONTAINER_ID], 
7280                       kerberos_ou, dn_path);
7281               managedBy_v[0] = managedByDN;
7282               ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_REPLACE);
7283             }
7284           else
7285             {
7286               if (strlen(managedByDN) != 0)
7287                 {
7288                   attribute_update(ldap_handle, ad_path, "", "managedBy", 
7289                                    dName);
7290                 }
7291             }
7292         }
7293       else
7294         {
7295           memset(filter, '\0', sizeof(filter));
7296
7297           if (!strcasecmp(av[CONTAINER_TYPE], "USER"))
7298             {
7299               sprintf(filter, "(&(cn=%s)(&(objectCategory=person)"
7300                       "(objectClass=user)))", av[CONTAINER_ID]);
7301             }
7302
7303           if (!strcasecmp(av[CONTAINER_TYPE], "LIST"))
7304             {
7305               sprintf(filter, "(&(objectClass=group)(cn=%s))", 
7306                       av[CONTAINER_ID]);
7307             }
7308
7309           if (strlen(filter) != 0)
7310             {
7311               attr_array[0] = "distinguishedName";
7312               attr_array[1] = NULL;
7313               group_count = 0;
7314               group_base = NULL;
7315               if ((rc = linklist_build(ldap_handle, dn_path, filter, 
7316                                        attr_array, &group_base, &group_count, 
7317                                        LDAP_SCOPE_SUBTREE)) == LDAP_SUCCESS)
7318                 {
7319                   if (group_count == 1)
7320                     {
7321                       strcpy(managedByDN, group_base->value);
7322                       managedBy_v[0] = managedByDN;
7323                       ADD_ATTR("managedBy", managedBy_v, LDAP_MOD_REPLACE);
7324                     }
7325                   else
7326                     {
7327                       if (strlen(managedByDN) != 0)
7328                         {
7329                           attribute_update(ldap_handle, ad_path, "", 
7330                                            "managedBy", dName);
7331                         }
7332                     }
7333
7334                   linklist_free(group_base);
7335                   group_base = NULL;
7336                   group_count = 0;
7337                 }
7338             }
7339           else
7340             {
7341               if (strlen(managedByDN) != 0)
7342                 {
7343                   attribute_update(ldap_handle, ad_path, "", "managedBy", 
7344                                    dName);
7345                 }
7346             }
7347         }
7348     }
7349
7350   mods[n] = NULL;
7351
7352   if (n == 0)
7353     return(LDAP_SUCCESS);
7354
7355   rc = ldap_modify_s(ldap_handle, ad_path, mods);
7356
7357   for (i = 0; i < n; i++)
7358     free(mods[i]);
7359
7360   if (rc != LDAP_SUCCESS)
7361     {
7362       com_err(whoami, 0, "Unable to modify container info for %s : %s",
7363               av[CONTAINER_NAME], ldap_err2string(rc));
7364       return(rc);
7365     }
7366   
7367   return(rc);
7368 }
7369
7370 int container_move_objects(LDAP *ldap_handle, char *dn_path, char *dName)
7371 {
7372   char      *attr_array[3];
7373   LK_ENTRY  *group_base;
7374   LK_ENTRY  *pPtr;
7375   int       group_count;
7376   char      filter[512];
7377   char      new_cn[128];
7378   char      temp[256];
7379   int       rc;
7380   int       NumberOfEntries = 10;
7381   int       i;
7382   int       count;
7383
7384   rc = ldap_set_option(ldap_handle, LDAP_OPT_SIZELIMIT, &NumberOfEntries);
7385
7386   for (i = 0; i < 3; i++)
7387     {
7388       memset(filter, '\0', sizeof(filter));
7389
7390       if (i == 0)
7391         {
7392           strcpy(filter, "(!(|(objectClass=computer)"
7393                  "(objectClass=organizationalUnit)))");
7394           attr_array[0] = "cn";
7395           attr_array[1] = NULL;
7396         }
7397       else if (i == 1)
7398         {
7399           strcpy(filter, "(objectClass=computer)");
7400           attr_array[0] = "cn";
7401           attr_array[1] = NULL;
7402         }
7403       else
7404         {
7405           strcpy(filter, "(objectClass=organizationalUnit)");
7406           attr_array[0] = "ou";
7407           attr_array[1] = NULL;
7408         }
7409
7410       while (1)
7411         {
7412           if ((rc = linklist_build(ldap_handle, dName, filter, attr_array, 
7413                                    &group_base, &group_count, 
7414                                    LDAP_SCOPE_SUBTREE)) != LDAP_SUCCESS)
7415             {
7416               break;
7417             }
7418
7419           if (group_count == 0)
7420             break;
7421
7422           pPtr = group_base;
7423
7424           while(pPtr)
7425             {
7426               if (!strcasecmp(pPtr->attribute, "cn"))
7427                 {
7428                   sprintf(new_cn, "cn=%s", pPtr->value);
7429                   if (i == 0)
7430                     sprintf(temp, "%s,%s", orphans_other_ou, dn_path);
7431                   if (i == 1)
7432                     sprintf(temp, "%s,%s", orphans_machines_ou, dn_path);
7433                   count = 1;
7434
7435                   while (1)
7436                     {
7437                       rc = ldap_rename_s(ldap_handle, pPtr->dn, new_cn, temp,
7438                                          TRUE, NULL, NULL);
7439                       if (rc == LDAP_ALREADY_EXISTS)
7440                         {
7441                           sprintf(new_cn, "cn=%s_%d", pPtr->value, count);
7442                           ++count;
7443                         }
7444                       else
7445                         break;
7446                     }
7447                 }
7448               else if (!strcasecmp(pPtr->attribute, "ou"))
7449                 {
7450                   rc = ldap_delete_s(ldap_handle, pPtr->dn);
7451                 }
7452
7453               pPtr = pPtr->next;
7454             }
7455
7456           linklist_free(group_base);
7457           group_base = NULL;
7458           group_count = 0;
7459         }
7460     }
7461
7462   return(0);
7463 }
7464
7465 int get_machine_ou(LDAP *ldap_handle, char *dn_path, char *member, 
7466                    char *machine_ou, char *NewMachineName)
7467 {
7468   LK_ENTRY  *group_base;
7469   int  group_count;
7470   int  i;
7471   char filter[128];
7472   char *attr_array[3];
7473   char cn[256];
7474   char dn[256];
7475   char temp[256];
7476   char *pPtr;
7477   int   rc;
7478
7479   strcpy(NewMachineName, member);
7480   rc = moira_connect();
7481   rc = GetMachineName(NewMachineName);
7482   moira_disconnect();
7483
7484   if (strlen(NewMachineName) == 0)
7485     {
7486       com_err(whoami, 0, "Unable to find alais for machine %s in Moira", 
7487               member);
7488       return(1);
7489     }
7490
7491   pPtr = NULL;
7492   pPtr = strchr(NewMachineName, '.');
7493
7494   if (pPtr != NULL)
7495     (*pPtr) = '\0';
7496
7497   group_base = NULL;
7498   group_count = 0;
7499   sprintf(filter, "(sAMAccountName=%s$)", NewMachineName);
7500   attr_array[0] = "cn";
7501   attr_array[1] = NULL;
7502   sprintf(temp, "%s", dn_path);
7503
7504   if ((rc = linklist_build(ldap_handle, temp, filter, attr_array, 
7505                            &group_base, &group_count, 
7506                            LDAP_SCOPE_SUBTREE)) != 0)
7507     {
7508       com_err(whoami, 0, "Unable to process machine %s : %s",
7509               member, ldap_err2string(rc));
7510       return(1);
7511     }
7512
7513   if (group_count != 1)
7514     {
7515       return(1);
7516     }
7517
7518   strcpy(dn, group_base->dn);
7519   strcpy(cn, group_base->value);
7520
7521   for (i = 0; i < (int)strlen(dn); i++)
7522     dn[i] = tolower(dn[i]);
7523
7524   for (i = 0; i < (int)strlen(cn); i++)
7525     cn[i] = tolower(cn[i]);
7526
7527   linklist_free(group_base);
7528   pPtr = NULL;
7529   pPtr = strstr(dn, cn);
7530
7531   if (pPtr == NULL)
7532     {
7533       com_err(whoami, 0, "Unable to process machine %s",
7534               member);
7535       return(1);
7536     }
7537
7538   pPtr += strlen(cn) + 1;
7539   strcpy(machine_ou, pPtr);
7540   pPtr = NULL;
7541   pPtr = strstr(machine_ou, "dc=");
7542
7543   if (pPtr == NULL)
7544     {
7545       com_err(whoami, 0, "Unable to process machine %s",
7546               member);
7547       return(1);
7548     }
7549
7550   --pPtr;
7551   (*pPtr) = '\0';
7552
7553   return(0);
7554 }
7555
7556 int machine_move_to_ou(LDAP *ldap_handle, char * dn_path, 
7557                        char *MoiraMachineName, char *DestinationOu)
7558 {
7559   char        NewCn[128];
7560   char        OldDn[512];
7561   char        MachineName[128];
7562   char        filter[128];
7563   char        *attr_array[3];
7564   char        NewOu[256];
7565   char        *cPtr = NULL;
7566   int         group_count;
7567   long        rc;
7568   LK_ENTRY    *group_base;
7569
7570   group_count = 0;
7571   group_base = NULL;
7572   
7573   strcpy(MachineName, MoiraMachineName);
7574   rc = GetMachineName(MachineName);
7575
7576   if (strlen(MachineName) == 0)
7577     {
7578       com_err(whoami, 0, "Unable to find alais for machine %s in Moira", 
7579               MoiraMachineName);
7580       return(1);
7581     }
7582   
7583   cPtr = strchr(MachineName, '.');
7584
7585   if (cPtr != NULL)
7586     (*cPtr) = '\0';
7587
7588   sprintf(filter, "(sAMAccountName=%s$)", MachineName);
7589   attr_array[0] = "sAMAccountName";
7590   attr_array[1] = NULL;
7591
7592   if ((rc = linklist_build(ldap_handle, dn_path, filter, attr_array, 
7593                            &group_base, 
7594                            &group_count, LDAP_SCOPE_SUBTREE)) != 0)
7595     {
7596       com_err(whoami, 0, "Unable to process machine %s : %s",
7597               MoiraMachineName, ldap_err2string(rc));
7598       return(1);
7599     }
7600   
7601   if (group_count == 1)
7602     strcpy(OldDn, group_base->dn);
7603
7604   linklist_free(group_base);
7605   group_base = NULL;
7606
7607   if (group_count != 1)
7608     {
7609       com_err(whoami, 0, "Unable to find machine %s in directory: %s", 
7610               MoiraMachineName);
7611       return(1);
7612     }
7613
7614   sprintf(NewOu, "%s,%s", DestinationOu, dn_path);
7615   cPtr = strchr(OldDn, ',');
7616
7617   if (cPtr != NULL)
7618     {
7619       ++cPtr;
7620       if (!strcasecmp(cPtr, NewOu))
7621         return(0);
7622     }
7623
7624   sprintf(NewCn, "CN=%s", MachineName);
7625   rc = ldap_rename_s(ldap_handle, OldDn, NewCn, NewOu, TRUE, NULL, NULL);
7626
7627   return(rc);
7628 }
7629
7630 int machine_check(LDAP *ldap_handle, char *dn_path, char *machine_name)
7631 {
7632   char    Name[128];
7633   char    *pPtr;
7634   int     rc;
7635   
7636   memset(Name, '\0', sizeof(Name));
7637   strcpy(Name, machine_name);
7638   pPtr = NULL;
7639   pPtr = strchr(Name, '.');
7640
7641   if (pPtr != NULL)
7642     (*pPtr) = '\0';
7643
7644   strcat(Name, "$");
7645   return(!(rc = checkADname(ldap_handle, dn_path, Name)));
7646 }
7647
7648 int machine_get_moira_container(LDAP *ldap_handle, char *dn_path, 
7649                                 char *machine_name, char *container_name)
7650 {
7651   int     rc;
7652   char    *av[2];
7653   char    *call_args[2];
7654   
7655   av[0] = machine_name;
7656   call_args[0] = (char *)container_name;
7657   rc = mr_query("get_machine_to_container_map", 1, av, 
7658                 machine_GetMoiraContainer, call_args);
7659   return(rc);
7660 }
7661
7662 int machine_GetMoiraContainer(int ac, char **av, void *ptr)
7663 {
7664   char **call_args;
7665   
7666   call_args = ptr;
7667   strcpy(call_args[0], av[1]);
7668   return(0);
7669 }
7670
7671 int Moira_container_group_create(char **after)
7672 {
7673   long rc;
7674   char GroupName[64];
7675   char *argv[20];
7676   
7677   memset(GroupName, '\0', sizeof(GroupName));
7678   rc = Moira_groupname_create(GroupName, after[CONTAINER_NAME], 
7679                               after[CONTAINER_ROWID]);
7680   if (rc)
7681     return rc;
7682   
7683   argv[L_NAME] = GroupName;
7684   argv[L_ACTIVE] = "1";
7685   argv[L_PUBLIC] = "0";
7686   argv[L_HIDDEN] = "0";
7687   argv[L_MAILLIST] = "0";
7688   argv[L_GROUP] = "1";
7689   argv[L_GID] = UNIQUE_GID;
7690   argv[L_NFSGROUP] = "0";
7691   argv[L_MAILMAN] = "0";
7692   argv[L_MAILMAN_SERVER] = "[NONE]";
7693   argv[L_DESC] = "auto created container group";
7694   argv[L_ACE_TYPE] = "USER";
7695   argv[L_MEMACE_TYPE] = "USER";
7696   argv[L_ACE_NAME] = "sms";
7697   argv[L_MEMACE_NAME] = "sms";
7698
7699   if (rc = mr_query("add_list", 15, argv, NULL, NULL))
7700     {
7701       com_err(whoami, 0, 
7702               "Unable to create container group %s for container %s: %s",
7703               GroupName, after[CONTAINER_NAME], error_message(rc));
7704     }
7705
7706   Moira_setContainerGroup(after[CONTAINER_NAME], GroupName);
7707   Moira_addGroupToParent(after[CONTAINER_NAME], GroupName);
7708   
7709   return(rc);
7710 }
7711
7712 int Moira_container_group_update(char **before, char **after)
7713 {
7714   long rc;
7715   char BeforeGroupName[64];
7716   char AfterGroupName[64];
7717   char *argv[20];
7718   
7719   if (!strcasecmp(after[CONTAINER_NAME], before[CONTAINER_NAME]))
7720     return(0);
7721
7722   memset(BeforeGroupName, '\0', sizeof(BeforeGroupName));
7723   Moira_getGroupName(after[CONTAINER_NAME], BeforeGroupName, 0);
7724   if (strlen(BeforeGroupName) == 0)
7725     return(0);
7726
7727   memset(AfterGroupName, '\0', sizeof(AfterGroupName));
7728   rc = Moira_groupname_create(AfterGroupName, after[CONTAINER_NAME], 
7729                               after[CONTAINER_ROWID]);
7730   if (rc)
7731     return rc;
7732
7733   if (strcasecmp(BeforeGroupName, AfterGroupName))
7734     {
7735       argv[L_NAME] = BeforeGroupName;
7736       argv[L_NAME + 1] = AfterGroupName;
7737       argv[L_ACTIVE + 1] = "1";
7738       argv[L_PUBLIC + 1] = "0";
7739       argv[L_HIDDEN + 1] = "0";
7740       argv[L_MAILLIST + 1] = "0";
7741       argv[L_GROUP + 1] = "1";
7742       argv[L_GID + 1] = UNIQUE_GID;
7743       argv[L_NFSGROUP + 1] = "0";
7744       argv[L_MAILMAN + 1] = "0";
7745       argv[L_MAILMAN_SERVER + 1] = "[NONE]";
7746       argv[L_DESC + 1] = "auto created container group";
7747       argv[L_ACE_TYPE + 1] = "USER";
7748       argv[L_MEMACE_TYPE + 1] = "USER";
7749       argv[L_ACE_NAME + 1] = "sms";
7750       argv[L_MEMACE_NAME + 1] = "sms";
7751       
7752       if (rc = mr_query("update_list", 16, argv, NULL, NULL))
7753         {
7754           com_err(whoami, 0, 
7755                   "Unable to rename container group from %s to %s: %s",
7756                   BeforeGroupName, AfterGroupName, error_message(rc));
7757         }
7758     }
7759   
7760   return(rc);
7761 }
7762
7763 int Moira_container_group_delete(char **before)
7764 {
7765   long rc = 0;
7766   char *argv[13];
7767   char GroupName[64];
7768   char ParentGroupName[64];
7769   
7770   memset(ParentGroupName, '\0', sizeof(ParentGroupName));
7771   Moira_getGroupName(before[CONTAINER_NAME], ParentGroupName, 1);
7772
7773   memset(GroupName, '\0', sizeof(GroupName));
7774
7775   if (strcmp(before[CONTAINER_GROUP_NAME], "[none]"))
7776     strcpy(GroupName, before[CONTAINER_GROUP_NAME]);
7777   
7778   if ((strlen(ParentGroupName) != 0) && (strlen(GroupName) != 0))
7779     {
7780       argv[0] = ParentGroupName;
7781       argv[1] = "LIST";
7782       argv[2] = GroupName;
7783
7784       if (rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL))
7785         {
7786           com_err(whoami, 0, 
7787                   "Unable to delete container group %s from list: %s",
7788                   GroupName, ParentGroupName, error_message(rc));
7789         }
7790     }
7791   
7792   if (strlen(GroupName) != 0)
7793     {
7794       argv[0] = GroupName;
7795
7796       if (rc = mr_query("delete_list", 1, argv, NULL, NULL))
7797         {
7798           com_err(whoami, 0, "Unable to delete container group %s : %s",
7799                   GroupName, error_message(rc));
7800         }
7801     }
7802   
7803   return(rc);
7804 }
7805
7806 int Moira_groupname_create(char *GroupName, char *ContainerName,
7807                            char *ContainerRowID)
7808 {
7809   char *ptr;
7810   char *ptr1;
7811   char temp[64];
7812   char newGroupName[64];
7813   char tempGroupName[64];
7814   char tempgname[64];
7815   char *argv[1];
7816   int  i;
7817   long rc;
7818
7819   strcpy(temp, ContainerName);
7820   
7821   ptr1 = strrchr(temp, '/');
7822
7823   if (ptr1 != NULL)
7824   {
7825     *ptr1 = '\0';
7826     ptr = ++ptr1;
7827     ptr1 = strrchr(temp, '/');
7828
7829     if (ptr1 != NULL)
7830     {
7831         sprintf(tempgname, "%s-%s", ++ptr1, ptr);
7832     }
7833     else
7834         strcpy(tempgname, ptr);
7835   }
7836   else
7837     strcpy(tempgname, temp);
7838
7839   if (strlen(tempgname) > 25)
7840     tempgname[25] ='\0';
7841
7842   sprintf(newGroupName, "cnt-%s", tempgname);
7843
7844   /* change everything to lower case */
7845   ptr = newGroupName;
7846
7847   while (*ptr)
7848     {
7849       if (isupper(*ptr))
7850         *ptr = tolower(*ptr);
7851
7852       if (*ptr == ' ')
7853         *ptr = '-';
7854
7855       ptr++;
7856     }
7857
7858   strcpy(tempGroupName, newGroupName);
7859   i = (int)'0';
7860
7861   /* append 0-9 then a-z if a duplicate is found */
7862   while(1)
7863     {
7864       argv[0] = newGroupName;
7865
7866       if (rc = mr_query("get_list_info", 1, argv, NULL, NULL))
7867         {
7868           if (rc == MR_NO_MATCH)
7869             break;
7870           com_err(whoami, 0, "Moira error while creating group name for "
7871                   "container %s : %s", ContainerName, error_message(rc));
7872           return rc;
7873         }
7874
7875       sprintf(newGroupName, "%s-%c", tempGroupName, i);
7876
7877       if (i == (int)'z')
7878         {
7879           com_err(whoami, 0, "Unable to find a unique group name for "
7880                   "container %s: too many duplicate container names",
7881                   ContainerName);
7882           return 1;
7883         }
7884
7885       if (i == '9')
7886         i = 'a';
7887       else
7888         i++;
7889     }
7890
7891   strcpy(GroupName, newGroupName);
7892   return(0);
7893 }
7894
7895 int Moira_setContainerGroup(char *origContainerName, char *GroupName)
7896 {
7897   long rc;
7898   char *argv[3];
7899   
7900   argv[0] = origContainerName;
7901   argv[1] = GroupName;
7902   
7903   if ((rc = mr_query("set_container_list", 2, argv, NULL, NULL)))
7904     {
7905       com_err(whoami, 0, 
7906               "Unable to set container group %s in container %s: %s",
7907               GroupName, origContainerName, error_message(rc));
7908     }
7909   
7910   return(0);
7911 }
7912
7913 int Moira_addGroupToParent(char *origContainerName, char *GroupName)
7914  {
7915    char ContainerName[64];
7916    char ParentGroupName[64];
7917    char *argv[3];
7918    long rc;
7919
7920    strcpy(ContainerName, origContainerName);
7921    
7922    Moira_getGroupName(ContainerName, ParentGroupName, 1);
7923
7924    /* top-level container */
7925    if (strlen(ParentGroupName) == 0)
7926      return(0);
7927    
7928    argv[0] = ParentGroupName;
7929    argv[1] = "LIST";
7930    argv[2] = GroupName;
7931
7932    if ((rc = mr_query("add_member_to_list", 3, argv, NULL, NULL)))
7933      {
7934        com_err(whoami, 0, 
7935                "Unable to add container group %s to parent group %s: %s",
7936                GroupName, ParentGroupName, error_message(rc));
7937      }
7938    
7939    return(0);
7940  }
7941
7942 int Moira_getContainerGroup(int ac, char **av, void *ptr)
7943 {
7944   char **call_args;
7945   
7946   call_args = ptr;
7947   strcpy(call_args[0], av[1]);
7948
7949   return(0);
7950 }
7951
7952 int Moira_getGroupName(char *origContainerName, char *GroupName,
7953                        int ParentFlag)
7954 {
7955   char ContainerName[64];
7956   char *argv[3];
7957   char *call_args[3];
7958   char *ptr;
7959   long rc;
7960
7961   strcpy(ContainerName, origContainerName);
7962
7963   if (ParentFlag)
7964     {
7965       ptr = strrchr(ContainerName, '/');
7966
7967       if (ptr != NULL)
7968         (*ptr) = '\0';
7969       else
7970         return(0);
7971     }
7972
7973   argv[0] = ContainerName;
7974   argv[1] = NULL;
7975   call_args[0] = GroupName;
7976   call_args[1] = NULL;
7977
7978   if (!(rc = mr_query("get_container_list", 1, argv, Moira_getContainerGroup,
7979                       call_args)))
7980     {
7981       if (strlen(GroupName) != 0)
7982         return(0);
7983     }
7984
7985   if (rc)
7986     com_err(whoami, 0, "Unable to get container group from container %s: %s",
7987             ContainerName, error_message(rc));
7988   else
7989     com_err(whoami, 0, "Unable to get container group from container %s",
7990             ContainerName);
7991   
7992   return(0);
7993 }
7994
7995 int Moira_process_machine_container_group(char *MachineName, char* GroupName, 
7996                                           int DeleteMachine)
7997 {
7998   char *argv[3];
7999   long rc;
8000   
8001   if (strcmp(GroupName, "[none]") == 0)
8002     return 0;
8003
8004   argv[0] = GroupName;
8005   argv[1] = "MACHINE";
8006   argv[2] = MachineName;
8007
8008   if (!DeleteMachine)
8009     rc = mr_query("add_member_to_list", 3, argv, NULL, NULL);
8010   else
8011     rc = mr_query("delete_member_from_list", 3, argv, NULL, NULL);
8012
8013   if (rc)
8014     {
8015       com_err(whoami, 0, "Unable to add machine %s to container group%s: %s",
8016               MachineName, GroupName, error_message(rc));
8017     }
8018
8019   return(0);
8020 }
8021
8022 int GetMachineName(char *MachineName)
8023 {
8024   char    *args[2];
8025   char    NewMachineName[1024];
8026   char    *szDot;
8027   int     rc = 0;
8028   int     i;
8029   DWORD   dwLen = 0;
8030   char    *call_args[2];
8031   
8032   // If the address happens to be in the top-level MIT domain, great!
8033   strcpy(NewMachineName, MachineName);
8034
8035   for (i = 0; i < (int)strlen(NewMachineName); i++)
8036     NewMachineName[i] = toupper(NewMachineName[i]);
8037
8038   szDot = strchr(NewMachineName,'.');
8039
8040   if ((szDot) && (!strcasecmp(szDot+1, DOMAIN_SUFFIX)))
8041     {
8042       return(0);
8043     }
8044   
8045   // If not, see if it has a Moira alias in the top-level MIT domain.
8046   memset(NewMachineName, '\0', sizeof(NewMachineName));
8047   args[0] = "*";
8048   args[1] = MachineName;
8049   call_args[0] = NewMachineName;
8050   call_args[1] = NULL;
8051
8052   if (rc = mr_query("get_hostalias", 2, args, ProcessMachineName, call_args))
8053     {
8054       com_err(whoami, 0, "Unable to resolve machine name %s : %s",
8055               MachineName, error_message(rc));
8056       strcpy(MachineName, "");
8057       return(0);
8058     }
8059   
8060   if (strlen(NewMachineName) != 0)
8061     strcpy(MachineName, NewMachineName);
8062   else
8063     strcpy(MachineName, "");
8064
8065   return(0);
8066 }
8067
8068 int ProcessMachineName(int ac, char **av, void *ptr)
8069 {
8070   char    **call_args;
8071   char    MachineName[1024];
8072   char    *szDot;
8073   int     i;
8074   
8075   call_args = ptr;
8076
8077   if (strlen(call_args[0]) == 0)
8078     {
8079       strcpy(MachineName, av[0]);
8080
8081       for (i = 0; i < (int)strlen(MachineName); i++)
8082         MachineName[i] = toupper(MachineName[i]);
8083
8084       szDot = strchr(MachineName,'.');
8085
8086         if ((szDot) && (!strcasecmp(szDot+1,DOMAIN_SUFFIX)))
8087           {
8088             strcpy(call_args[0], MachineName);
8089           }
8090     }
8091
8092   return(0);
8093 }
8094
8095 void SwitchSFU(LDAPMod **mods, int *UseSFU30, int n)
8096 {
8097   int i;
8098   
8099   if (*UseSFU30)
8100     {
8101       for (i = 0; i < n; i++)
8102         {
8103           if (!strcmp(mods[i]->mod_type, "msSFU30UidNumber"))
8104             mods[i]->mod_type = "uidNumber";
8105         }
8106
8107       (*UseSFU30) = 0;
8108     }
8109   else
8110     {
8111       for (i = 0; i < n; i++)
8112         {
8113           if (!strcmp(mods[i]->mod_type, "uidNumber"))
8114             mods[i]->mod_type = "msSFU30UidNumber";
8115         }
8116
8117       (*UseSFU30) = 1;
8118     }
8119 }
8120
8121 int SetHomeDirectory(LDAP *ldap_handle, char *user_name, 
8122                      char *DistinguishedName,
8123                      char *WinHomeDir, char *WinProfileDir,
8124                      char **homedir_v, char **winProfile_v,
8125                      char **drives_v, LDAPMod **mods, 
8126                      int OpType, int n)
8127 {
8128   char cWeight[3];
8129   char cPath[1024];
8130   char path[1024];
8131   char winPath[1024];
8132   char winProfile[1024];
8133   char homeDrive[8];
8134   char homedir[1024];
8135   char apple_homedir[1024];
8136   char *apple_homedir_v[] = {NULL, NULL};
8137   int  last_weight;
8138   int  i;
8139   int  rc;
8140   LDAPMod *DelMods[20];
8141   char *argv[3];
8142   char *save_argv[FS_END];
8143   char *fsgroup_save_argv[2];
8144
8145   memset(homeDrive, '\0', sizeof(homeDrive));
8146   memset(path, '\0', sizeof(path));
8147   memset(winPath, '\0', sizeof(winPath));
8148   memset(winProfile, '\0', sizeof(winProfile));
8149
8150   if(!ActiveDirectory) 
8151     {
8152       if (rc = moira_connect())
8153         {
8154           critical_alert("Ldap incremental",
8155                          "Error contacting Moira server : %s",
8156                          error_message(rc));
8157           return;
8158         }
8159       
8160       argv[0] = user_name;
8161
8162       if (!(rc = mr_query("get_filesys_by_label", 1, argv, save_query_info, 
8163                           save_argv)))
8164         {
8165           if(!strcmp(save_argv[FS_TYPE], "FSGROUP") ||
8166              !strcmp(save_argv[FS_TYPE], "MUL"))
8167             {
8168         
8169               argv[0] = save_argv[FS_NAME];
8170               fsgCount = 0;
8171               
8172               if (!(rc = mr_query("get_fsgroup_members", 1, argv, 
8173                                   save_fsgroup_info, fsgroup_save_argv)))
8174                 {
8175                   if(fsgCount)
8176                     {
8177                       argv[0] = fsgroup_save_argv[0];
8178                       
8179                       if (!(rc = mr_query("get_filesys_by_label", 1, argv, 
8180                                           save_query_info, save_argv)))
8181                         {
8182                           strcpy(path, save_argv[FS_PACK]);
8183                         }
8184                     }
8185                 }
8186             }
8187           else
8188             {
8189               strcpy(path, save_argv[FS_PACK]);
8190             }
8191         }
8192       
8193       moira_disconnect();
8194
8195       if (strlen(path))
8196         {
8197           if (!strnicmp(path, AFS, strlen(AFS)))
8198             {
8199               sprintf(homedir, "%s", path);
8200               sprintf(apple_homedir, "%s/MacData", path);
8201               homedir_v[0] = homedir;
8202               apple_homedir_v[0] = apple_homedir;
8203               ADD_ATTR("homeDirectory", homedir_v, OpType);
8204               ADD_ATTR("apple-user-homeDirectory", apple_homedir_v, 
8205                        OpType);
8206             }
8207         }
8208       else
8209         {
8210           homedir_v[0] = "NONE";
8211           apple_homedir_v[0] = "NONE";
8212           ADD_ATTR("homeDirectory", homedir_v, OpType);
8213           ADD_ATTR("apple-user-homeDirectory", apple_homedir_v, 
8214                    OpType);
8215         }
8216
8217       return(n);
8218     }
8219  
8220   if ((!strcasecmp(WinHomeDir, "[afs]")) || 
8221       (!strcasecmp(WinProfileDir, "[afs]")))
8222     {
8223       if (rc = moira_connect())
8224         {
8225           critical_alert("Ldap incremental",
8226                          "Error contacting Moira server : %s",
8227                          error_message(rc));
8228           return;
8229         }
8230       
8231       argv[0] = user_name;
8232
8233       if (!(rc = mr_query("get_filesys_by_label", 1, argv, save_query_info, 
8234                           save_argv)))
8235         {
8236           if(!strcmp(save_argv[FS_TYPE], "FSGROUP") ||
8237              !strcmp(save_argv[FS_TYPE], "MUL"))
8238             {
8239         
8240               argv[0] = save_argv[FS_NAME];
8241               fsgCount = 0;
8242               
8243               if (!(rc = mr_query("get_fsgroup_members", 1, argv, 
8244                                   save_fsgroup_info, fsgroup_save_argv)))
8245                 {
8246                   if(fsgCount)
8247                     {
8248                       argv[0] = fsgroup_save_argv[0];
8249                       
8250                       if (!(rc = mr_query("get_filesys_by_label", 1, argv, 
8251                                           save_query_info, save_argv)))
8252                         {
8253                           strcpy(path, save_argv[FS_PACK]);
8254                         }
8255                     }
8256                 }
8257             }
8258           else
8259             {
8260               strcpy(path, save_argv[FS_PACK]);
8261             }
8262         }
8263      
8264       moira_disconnect();
8265
8266       if (strlen(path))
8267         {
8268           if (!strnicmp(path, AFS, strlen(AFS)))
8269             {
8270               AfsToWinAfs(path, winPath);
8271               strcpy(winProfile, winPath);
8272               strcat(winProfile, "\\.winprofile");
8273             }
8274         }
8275       else
8276         return(n);
8277     }
8278
8279     if ((!strcasecmp(WinHomeDir, "[dfs]")) || 
8280         (!strcasecmp(WinProfileDir, "[dfs]")))
8281     {
8282       sprintf(path, "\\\\%s\\dfs\\profiles\\%c\\%s", ldap_domain, 
8283               user_name[0], user_name);
8284
8285       if (!strcasecmp(WinProfileDir, "[dfs]"))
8286         {
8287           strcpy(winProfile, path);
8288           strcat(winProfile, "\\.winprofile");
8289         }
8290
8291       if (!strcasecmp(WinHomeDir, "[dfs]"))
8292         strcpy(winPath, path);
8293     }
8294     
8295     if (!strcasecmp(WinHomeDir, "[local]"))
8296       memset(winPath, '\0', sizeof(winPath));
8297     else if (!strcasecmp(WinHomeDir, "[afs]") || 
8298              !strcasecmp(WinHomeDir, "[dfs]"))
8299       {
8300         strcpy(homeDrive, "H:");
8301       }
8302     else
8303       {
8304         strcpy(winPath, WinHomeDir);
8305         if (!strncmp(WinHomeDir, "\\\\", 2))
8306           {
8307             strcpy(homeDrive, "H:");
8308           }        
8309       }
8310     
8311     // nothing needs to be done if WinProfileDir is [afs].
8312     if (!strcasecmp(WinProfileDir, "[local]"))
8313       memset(winProfile, '\0', sizeof(winProfile));
8314     else if (strcasecmp(WinProfileDir, "[afs]") && 
8315              strcasecmp(WinProfileDir, "[dfs]"))
8316       {
8317         strcpy(winProfile, WinProfileDir);
8318       }
8319     
8320     if (strlen(winProfile) != 0)
8321       {
8322         if (winProfile[strlen(winProfile) - 1] == '\\')
8323           winProfile[strlen(winProfile) - 1] = '\0';
8324       }
8325
8326     if (strlen(winPath) != 0)
8327       {
8328         if (winPath[strlen(winPath) - 1] == '\\')
8329           winPath[strlen(winPath) - 1] = '\0';
8330       }
8331     
8332     if ((winProfile[1] == ':') && (strlen(winProfile) == 2))
8333       strcat(winProfile, "\\");
8334
8335     if ((winPath[1] == ':') && (strlen(winPath) == 2))
8336       strcat(winPath, "\\");
8337     
8338     if (strlen(winPath) == 0)
8339       {
8340         if (OpType == LDAP_MOD_REPLACE)
8341           {
8342             i = 0;
8343             DEL_ATTR("homeDirectory", LDAP_MOD_DELETE);
8344             DelMods[i] = NULL;
8345             //unset homeDirectory attribute for user.
8346             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
8347             free(DelMods[0]);
8348           }
8349       }
8350     else
8351       {
8352         homedir_v[0] = strdup(winPath);
8353         ADD_ATTR("homeDirectory", homedir_v, OpType);
8354       }
8355     
8356     if (strlen(winProfile) == 0)
8357       {
8358         if (OpType == LDAP_MOD_REPLACE)
8359           {
8360             i = 0;
8361             DEL_ATTR("profilePath", LDAP_MOD_DELETE);
8362             DelMods[i] = NULL;
8363             //unset profilePate attribute for user.
8364             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
8365             free(DelMods[0]);
8366           }
8367       }
8368     else
8369       {
8370         winProfile_v[0] = strdup(winProfile);
8371         ADD_ATTR("profilePath", winProfile_v, OpType);
8372       }
8373     
8374     if (strlen(homeDrive) == 0)
8375       {
8376         if (OpType == LDAP_MOD_REPLACE)
8377           {
8378             i = 0;
8379             DEL_ATTR("homeDrive", LDAP_MOD_DELETE);
8380             DelMods[i] = NULL;
8381             //unset homeDrive attribute for user
8382             rc = ldap_modify_s(ldap_handle, DistinguishedName, DelMods);
8383             free(DelMods[0]);
8384           }
8385       }
8386     else
8387       {
8388         drives_v[0] = strdup(homeDrive);
8389         ADD_ATTR("homeDrive", drives_v, OpType);
8390       }
8391
8392     return(n);
8393 }
8394
8395 int attribute_update(LDAP *ldap_handle, char *distinguished_name, 
8396                      char *attribute_value, char *attribute, char *user_name)
8397 {
8398   char      *mod_v[] = {NULL, NULL};
8399   LDAPMod   *DelMods[20];
8400   LDAPMod   *mods[20];
8401   int       n;
8402   int       i;
8403   int       rc;
8404   
8405   if (strlen(attribute_value) == 0)
8406     {
8407       i = 0;
8408       DEL_ATTR(attribute, LDAP_MOD_DELETE);
8409       DelMods[i] = NULL;
8410       rc = ldap_modify_s(ldap_handle, distinguished_name, DelMods);
8411       free(DelMods[0]);
8412     }
8413   else
8414     {
8415       n = 0;
8416       mod_v[0] = attribute_value;
8417       ADD_ATTR(attribute, mod_v, LDAP_MOD_REPLACE);
8418       mods[n] = NULL;
8419
8420       if ((rc = ldap_modify_s(ldap_handle, distinguished_name, 
8421                               mods)) != LDAP_SUCCESS)
8422         {
8423           free(mods[0]);
8424           n = 0;
8425           mod_v[0] = attribute_value;
8426           ADD_ATTR(attribute, mod_v, LDAP_MOD_ADD);
8427           mods[n] = NULL;
8428
8429           if ((rc = ldap_modify_s(ldap_handle, distinguished_name, 
8430                                   mods)) != LDAP_SUCCESS)
8431             {
8432               com_err(whoami, 0, "Unable to change the %s attribute for %s "
8433                       "in the directory : %s",
8434                       attribute, user_name, ldap_err2string(rc));
8435             }
8436         }
8437
8438       free(mods[0]);
8439     }
8440   
8441   return(rc);
8442 }
8443
8444 void StringTrim(char *StringToTrim)
8445 {
8446   char *t, *s;
8447   char *save;
8448
8449   save = strdup(StringToTrim);
8450
8451   s = save;
8452
8453   while (isspace(*s))
8454     s++;
8455
8456   /* skip to end of string */
8457   if (*s == '\0')
8458     {
8459       if (*save)
8460         *save = '\0';
8461       strcpy(StringToTrim, save);
8462       return;
8463     }
8464   
8465   for (t = s; *t; t++)
8466     continue;
8467
8468   while (t > s)
8469     {
8470       --t;
8471       if (!isspace(*t))
8472         {
8473           t++;
8474           break;
8475         }
8476     }
8477
8478   if (*t)
8479     *t = '\0';
8480   
8481   strcpy(StringToTrim, s);
8482   return;
8483 }
8484
8485 int ReadConfigFile(char *DomainName)
8486 {
8487     int     Count;
8488     int     i;
8489     int     k;
8490     char    temp[256];
8491     char    temp1[256];
8492     FILE    *fptr;
8493
8494     Count = 0;
8495
8496     sprintf(temp, "%s%s.cfg", CFG_PATH, DomainName);
8497
8498     if ((fptr = fopen(temp, "r")) != NULL)
8499       {
8500         while (fgets(temp, sizeof(temp), fptr) != 0)
8501           {
8502             for (i = 0; i < (int)strlen(temp); i++)
8503               temp[i] = toupper(temp[i]);
8504
8505             if (temp[strlen(temp) - 1] == '\n')
8506               temp[strlen(temp) - 1] = '\0';
8507
8508             StringTrim(temp);
8509
8510             if (strlen(temp) == 0)
8511               continue;
8512
8513             if (!strncmp(temp, DOMAIN, strlen(DOMAIN)))
8514               {
8515                 if (strlen(temp) > (strlen(DOMAIN)))
8516                   {
8517                     strcpy(ldap_domain, &temp[strlen(DOMAIN)]);
8518                     StringTrim(ldap_domain);
8519                   }
8520               }
8521             else if (!strncmp(temp, REALM, strlen(REALM)))
8522               {
8523                 if (strlen(temp) > (strlen(REALM)))
8524                   {
8525                     strcpy(ldap_realm, &temp[strlen(REALM)]);
8526                     StringTrim(ldap_realm);
8527                   }
8528               }
8529             else if (!strncmp(temp, PORT, strlen(PORT)))
8530               {
8531                 if (strlen(temp) > (strlen(PORT)))
8532                   {
8533                     strcpy(ldap_port, &temp[strlen(PORT)]);
8534                     StringTrim(ldap_port);
8535                   }
8536               }
8537             else if (!strncmp(temp, PRINCIPALNAME, strlen(PRINCIPALNAME)))
8538               {
8539                 if (strlen(temp) > (strlen(PRINCIPALNAME)))
8540                   {
8541                     strcpy(PrincipalName, &temp[strlen(PRINCIPALNAME)]);
8542                     StringTrim(PrincipalName);
8543                   }
8544               }
8545             else if (!strncmp(temp, SERVER, strlen(SERVER)))
8546               {
8547                 if (strlen(temp) > (strlen(SERVER)))
8548                   {
8549                     ServerList[Count] = calloc(1, 256);
8550                     strcpy(ServerList[Count], &temp[strlen(SERVER)]);
8551                     StringTrim(ServerList[Count]);
8552                     ++Count;
8553                   }
8554               }
8555             else if (!strncmp(temp, MSSFU, strlen(MSSFU)))
8556               {
8557                 if (strlen(temp) > (strlen(MSSFU)))
8558                   {
8559                     strcpy(temp1, &temp[strlen(MSSFU)]);
8560                     StringTrim(temp1);
8561                     if (!strcmp(temp1, SFUTYPE))
8562                       UseSFU30 = 1;
8563                   }
8564               }
8565             else if (!strncmp(temp, GROUP_SUFFIX, strlen(GROUP_SUFFIX)))
8566               {
8567                 if (strlen(temp) > (strlen(GROUP_SUFFIX)))
8568                   {
8569                     strcpy(temp1, &temp[strlen(GROUP_SUFFIX)]);
8570                     StringTrim(temp1);
8571                     if (!strcasecmp(temp1, "NO")) 
8572                       {
8573                         UseGroupSuffix = 0;
8574                         memset(group_suffix, '\0', sizeof(group_suffix));
8575                       }
8576                   }
8577               }
8578             else if (!strncmp(temp, GROUP_TYPE, strlen(GROUP_TYPE)))
8579               {
8580                 if (strlen(temp) > (strlen(GROUP_TYPE)))
8581                   {
8582                     strcpy(temp1, &temp[strlen(GROUP_TYPE)]);
8583                     StringTrim(temp1);
8584                     if (!strcasecmp(temp1, "UNIVERSAL")) 
8585                       UseGroupUniversal = 1;
8586                   }
8587               }
8588             else if (!strncmp(temp, SET_GROUP_ACE, strlen(SET_GROUP_ACE)))
8589               {
8590                 if (strlen(temp) > (strlen(SET_GROUP_ACE)))
8591                   {
8592                     strcpy(temp1, &temp[strlen(SET_GROUP_ACE)]);
8593                     StringTrim(temp1);
8594                     if (!strcasecmp(temp1, "NO"))
8595                       SetGroupAce = 0;
8596                   }
8597               }
8598             else if (!strncmp(temp, SET_PASSWORD, strlen(SET_PASSWORD)))
8599               {
8600                 if (strlen(temp) > (strlen(SET_PASSWORD)))
8601                   {
8602                     strcpy(temp1, &temp[strlen(SET_PASSWORD)]);
8603                     StringTrim(temp1);
8604                     if (!strcasecmp(temp1, "NO"))
8605                       SetPassword = 0;
8606                   }
8607               }
8608             else if (!strncmp(temp, EXCHANGE, strlen(EXCHANGE)))
8609               {
8610                 if (strlen(temp) > (strlen(EXCHANGE)))
8611                   {
8612                     strcpy(temp1, &temp[strlen(EXCHANGE)]);
8613                     StringTrim(temp1);
8614                     if (!strcasecmp(temp1, "YES"))
8615                       Exchange = 1;
8616                   }
8617               }
8618             else if (!strncmp(temp, PROCESS_MACHINE_CONTAINER, 
8619                               strlen(PROCESS_MACHINE_CONTAINER)))
8620               {
8621                 if (strlen(temp) > (strlen(PROCESS_MACHINE_CONTAINER)))
8622                   {
8623                     strcpy(temp1, &temp[strlen(PROCESS_MACHINE_CONTAINER)]);
8624                     StringTrim(temp1);
8625                     if (!strcasecmp(temp1, "NO"))
8626                       ProcessMachineContainer = 0;
8627                   }
8628               }
8629             else if (!strncmp(temp, ACTIVE_DIRECTORY, 
8630                               strlen(ACTIVE_DIRECTORY)))
8631               {
8632                 if (strlen(temp) > (strlen(ACTIVE_DIRECTORY)))
8633                   {
8634                     strcpy(temp1, &temp[strlen(ACTIVE_DIRECTORY)]);
8635                     StringTrim(temp1);
8636                     if (!strcasecmp(temp1, "NO"))
8637                       ActiveDirectory = 0;
8638                   }
8639               }
8640             else if (!strncmp(temp, GROUP_POPULATE_MEMBERS, 
8641                               strlen(GROUP_POPULATE_MEMBERS)))
8642               {
8643                 if (strlen(temp) > (strlen(GROUP_POPULATE_MEMBERS)))
8644                   {
8645                     strcpy(temp1, &temp[strlen(GROUP_POPULATE_MEMBERS)]);
8646                     StringTrim(temp1);
8647                     if (!strcasecmp(temp1, "DELETE")) 
8648                       {
8649                         GroupPopulateDelete = 1;
8650                       }
8651                   }
8652               }
8653             else
8654               {
8655                 if (strlen(ldap_domain) != 0)
8656                   {
8657                     memset(ldap_domain, '\0', sizeof(ldap_domain));
8658                     break;
8659                   }
8660
8661                 if (strlen(temp) != 0)
8662                   strcpy(ldap_domain, temp);
8663               }
8664           }
8665         fclose(fptr);
8666       }
8667     
8668     if (strlen(ldap_domain) == 0)
8669       {
8670       strcpy(ldap_domain, DomainName);
8671       }
8672
8673     if (Count == 0)
8674         return(0);
8675
8676     for (i = 0; i < Count; i++)
8677       {
8678         if (ServerList[i] != 0)
8679           {
8680             for (k = 0; k < (int)strlen(ServerList[i]); k++)
8681               ServerList[i][k] = toupper(ServerList[i][k]);
8682           }
8683       }
8684     
8685     return(0);
8686 }
8687
8688 int ReadDomainList()
8689 {
8690   int     Count;
8691   int     i;
8692   char    temp[128];
8693   char    temp1[128];
8694   FILE    *fptr;
8695   unsigned char c[11];
8696   unsigned char stuff[256];
8697   int     rc;
8698   int     ok;
8699
8700   Count = 0;
8701   sprintf(temp, "%s%s", CFG_PATH, WINADCFG);
8702
8703   if ((fptr = fopen(temp, "r")) != NULL)
8704     {
8705       while (fgets(temp, sizeof(temp), fptr) != 0)
8706         {
8707           for (i = 0; i < (int)strlen(temp); i++)
8708             temp[i] = toupper(temp[i]);
8709
8710           if (temp[strlen(temp) - 1] == '\n')
8711             temp[strlen(temp) - 1] = '\0';
8712
8713           StringTrim(temp);
8714
8715           if (strlen(temp) == 0)
8716             continue;
8717
8718           if (!strncmp(temp, DOMAIN, strlen(DOMAIN)))
8719             {
8720               if (strlen(temp) > (strlen(DOMAIN)))
8721                 {
8722                   strcpy(temp1, &temp[strlen(DOMAIN)]);
8723                   StringTrim(temp1);
8724                   strcpy(temp, temp1);
8725                 }
8726             }
8727           
8728           strcpy(DomainNames[Count], temp);
8729           StringTrim(DomainNames[Count]);
8730           ++Count;
8731         }
8732
8733       fclose(fptr);
8734     }
8735
8736   if (Count == 0)
8737     {
8738       critical_alert("incremental", "%s", "ldap.incr cannot run due to a "
8739                      "configuration error in ldap.cfg");
8740       return(1);
8741     }
8742   
8743   return(0);
8744 }
8745
8746 int email_isvalid(const char *address) {
8747   int        count = 0;
8748   const char *c, *domain;
8749   static char *rfc822_specials = "()<>@,;:\\\"[]";
8750
8751   if(address[strlen(address) - 1] == '.') 
8752     return 0;
8753     
8754   /* first we validate the name portion (name@domain) */
8755   for (c = address;  *c;  c++) {
8756     if (*c == '\"' && (c == address || *(c - 1) == '.' || *(c - 1) == 
8757                        '\"')) {
8758       while (*++c) {
8759         if (*c == '\"') 
8760           break;
8761         if (*c == '\\' && (*++c == ' ')) 
8762           continue;
8763         if (*c <= ' ' || *c >= 127) 
8764           return 0;
8765       }
8766
8767       if (!*c++) 
8768         return 0;
8769       if (*c == '@') 
8770         break;
8771       if (*c != '.') 
8772         return 0;
8773       continue;
8774     }
8775
8776     if (*c == '@') 
8777       break;
8778     if (*c <= ' ' || *c >= 127) 
8779       return 0;
8780     if (strchr(rfc822_specials, *c)) 
8781       return 0;
8782   }
8783
8784   if (c == address || *(c - 1) == '.') 
8785     return 0;
8786
8787   /* next we validate the domain portion (name@domain) */
8788   if (!*(domain = ++c)) return 0;
8789   do {
8790     if (*c == '.') {
8791       if (c == domain || *(c - 1) == '.') 
8792         return 0;
8793       count++;
8794     }
8795     if (*c <= ' ' || *c >= 127) 
8796       return 0;
8797     if (strchr(rfc822_specials, *c)) 
8798       return 0;
8799   } while (*++c);
8800
8801   return (count >= 1);
8802 }
8803
8804 int find_homeMDB(LDAP *ldap_handle, char *dn_path, char **homeMDB, 
8805              char **homeServerName) 
8806 {
8807   LK_ENTRY *group_base;
8808   LK_ENTRY *sub_group_base;
8809   LK_ENTRY *gPtr;
8810   LK_ENTRY *sub_gPtr;
8811   int      group_count;
8812   int      sub_group_count;
8813   char     filter[1024];
8814   char     sub_filter[1024];
8815   char     search_path[1024];
8816   char     range[1024];
8817   char     *attr_array[3];
8818   char     *s;
8819   int      homeMDB_count = -1;
8820   int      rc;
8821   int      i;
8822   int      mdbbl_count;
8823   int      rangeStep = 1500;
8824   int      rangeLow = 0;
8825   int      rangeHigh = rangeLow + (rangeStep - 1);
8826   int      isLast = 0;
8827
8828   /* Grumble..... microsoft not making it searchable from the root *grr* */
8829
8830   memset(filter, '\0', sizeof(filter));
8831   memset(search_path, '\0', sizeof(search_path));
8832   
8833   sprintf(filter, "(objectClass=msExchMDB)");
8834   sprintf(search_path, "CN=Configuration,%s", dn_path);
8835   attr_array[0] = "distinguishedName";
8836   attr_array[1] = NULL;
8837   
8838   group_base = NULL;
8839   group_count = 0;
8840   
8841   if ((rc = linklist_build(ldap_handle, search_path, filter, attr_array,
8842                            &group_base, &group_count, 
8843                            LDAP_SCOPE_SUBTREE)) != 0) 
8844     {
8845       com_err(whoami, 0, "Unable to find msExchMDB %s",
8846               ldap_err2string(rc));
8847       return(rc);
8848     }
8849   
8850   if (group_count) 
8851     {
8852       gPtr = group_base;
8853       
8854       while(gPtr) {
8855         if (((s = strstr(gPtr->dn, "Public")) != (char *) NULL) ||
8856             ((s = strstr(gPtr->dn, "Recover")) != (char *) NULL) || 
8857             ((s = strstr(gPtr->dn, "Reserve")) != (char *) NULL))
8858           {
8859             gPtr = gPtr->next;
8860             continue;
8861           }
8862
8863         /* 
8864          * Due to limits in active directory we need to use the LDAP
8865          * range semantics to query and return all the values in 
8866          * large lists, we will stop increasing the range when
8867          * the result count is 0.
8868          */
8869
8870         i = 0;  
8871         mdbbl_count = 0;
8872
8873         for(;;) 
8874           {
8875             memset(sub_filter, '\0', sizeof(sub_filter));
8876             memset(range, '\0', sizeof(range));
8877             sprintf(sub_filter, "(objectClass=msExchMDB)");
8878
8879             if(isLast)
8880               sprintf(range, "homeMDBBL;Range=%d-*", rangeLow);
8881             else 
8882               sprintf(range, "homeMDBBL;Range=%d-%d", rangeLow, rangeHigh);
8883
8884             attr_array[0] = range;
8885             attr_array[1] = NULL;
8886             
8887             sub_group_base = NULL;
8888             sub_group_count = 0;
8889             
8890             if ((rc = linklist_build(ldap_handle, gPtr->dn, sub_filter, 
8891                                      attr_array, &sub_group_base, 
8892                                      &sub_group_count, 
8893                                      LDAP_SCOPE_SUBTREE)) != 0) 
8894               {
8895                 com_err(whoami, 0, "Unable to find homeMDBBL %s",
8896                         ldap_err2string(rc));
8897                 return(rc);
8898               }
8899
8900             if(!sub_group_count)
8901               {
8902                 if(isLast) 
8903                   {
8904                     isLast = 0;
8905                     rangeLow = 0;
8906                     rangeHigh = rangeLow + (rangeStep - 1);
8907                     break;
8908                   }
8909                 else
8910                   isLast++;
8911               }
8912
8913             mdbbl_count += sub_group_count;
8914             rangeLow = rangeHigh + 1;
8915             rangeHigh = rangeLow + (rangeStep - 1);
8916           }
8917
8918         /* First time through, need to initialize or update the least used */
8919         
8920         com_err(whoami, 0, "Mail store %s, count %d", gPtr->dn, 
8921                 mdbbl_count);
8922
8923         if(mdbbl_count < homeMDB_count || homeMDB_count == -1) 
8924           {
8925             homeMDB_count = mdbbl_count; 
8926             *homeMDB = strdup(gPtr->dn);
8927           }
8928
8929         gPtr = gPtr->next;
8930         linklist_free(sub_group_base);
8931       }
8932     }
8933
8934   linklist_free(group_base);
8935   
8936   /* 
8937    * Ok found the server least allocated need to now query to get its
8938    * msExchHomeServerName so we can set it as a user attribute
8939    */
8940   
8941   attr_array[0] = "legacyExchangeDN";
8942   attr_array[1] = NULL; 
8943   
8944   group_count = 0;
8945   group_base = NULL;
8946   
8947   if ((rc = linklist_build(ldap_handle, *homeMDB, filter, 
8948                            attr_array, &group_base, 
8949                            &group_count, 
8950                            LDAP_SCOPE_SUBTREE)) != 0) 
8951     {
8952       com_err(whoami, 0, "Unable to find msExchHomeServerName %s",
8953               ldap_err2string(rc));
8954       return(rc);
8955     }  
8956   
8957   if(group_count) 
8958     {
8959       *homeServerName = strdup(group_base->value);
8960       if((s = strrchr(*homeServerName, '/')) != (char *) NULL) 
8961         {
8962           *s = '\0';
8963         }
8964     } 
8965
8966   linklist_free(group_base);
8967   
8968   return(rc);
8969 }
8970       
8971 char *lowercase(char *s)
8972 {
8973   char *p;
8974
8975   for (p = s; *p; p++)
8976     {
8977       if (isupper(*p))
8978         *p = tolower(*p);
8979     }
8980   return s;
8981 }
8982
8983 char *uppercase(char *s)
8984 {
8985   char *p;
8986
8987   for (p = s; *p; p++)
8988     {
8989       if (islower(*p))
8990         *p = toupper(*p);
8991     }
8992   return s;
8993 }
8994
8995 char *escape_string(char *s)
8996 {
8997   char *p, *q;
8998   char string[1024];
8999   char temp[1024];
9000   int i = 0;
9001   int spaces = 0;
9002
9003   memset(string, '\0', sizeof(string));
9004
9005   q = s;
9006
9007   /* Escape any special characters */
9008
9009   for(; *q != '\0'; q++) {
9010     if(*q == ',')
9011       string[i++] = '\\';
9012     if(*q == '+') 
9013       string[i++] = '\\';
9014     if(*q == '"') 
9015       string[i++] = '\\';
9016     if(*q == '\\') 
9017       string[i++] = '\\';
9018     if(*q == '<') 
9019       string[i++] = '\\';
9020     if(*q == '>') 
9021       string[i++] = '\\';
9022     if(*q == ';')
9023       string[i++] = '\\';
9024     if(*q == '#')
9025       string[i++] = '\\';
9026     if(*q == '=')
9027       string[i++] = '\\';
9028
9029     string[i++] = *q;
9030   }
9031
9032   return strdup(string);
9033 }
9034
9035 int save_query_info(int argc, char **argv, void *hint)
9036 {
9037   int i;
9038   char **nargv = hint;
9039
9040   for(i = 0; i < argc; i++)
9041     nargv[i] = strdup(argv[i]);
9042
9043   return MR_CONT;
9044 }
9045
9046 int save_fsgroup_info(int argc, char **argv, void *hint)
9047 {
9048   int i;
9049   char **nargv = hint;
9050
9051   if(!fsgCount) 
9052     {
9053       for(i = 0; i < argc; i++)
9054         nargv[i] = strdup(argv[i]);
9055
9056       fsgCount++;
9057     }
9058
9059   return MR_CONT;
9060 }
This page took 0.818989 seconds and 5 git commands to generate.