source: trunk/third/moira/incremental/winad/winad.c @ 24319

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