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