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