Commit | Line | Data |
---|---|---|
805e021f CE |
1 | /* |
2 | * Copyright 2000, International Business Machines Corporation and others. | |
3 | * All Rights Reserved. | |
4 | * | |
5 | * This software has been released under the terms of the IBM Public | |
6 | * License. For details, see the LICENSE file in the top-level source | |
7 | * directory or online at http://www.openafs.org/dl/license10.html | |
8 | */ | |
9 | ||
10 | /* This file implements configuration functions in the following categories: | |
11 | * cfg_Host*() - manipulate static server configuration information. | |
12 | */ | |
13 | ||
14 | #include <afsconfig.h> | |
15 | #include <afs/param.h> | |
16 | #include <afs/stds.h> | |
17 | ||
18 | #include <roken.h> | |
19 | ||
20 | #include <pthread.h> | |
21 | ||
22 | #ifdef AFS_NT40_ENV | |
23 | #include <WINNT/vptab.h> | |
24 | #include <WINNT/afsreg.h> | |
25 | #include <direct.h> | |
26 | #endif /* AFS_NT40_ENV */ | |
27 | ||
28 | #include <rx/rx.h> | |
29 | #include <rx/rxstat.h> | |
30 | ||
31 | #include <afs/afs_Admin.h> | |
32 | #include <afs/afs_AdminErrors.h> | |
33 | #include <afs/afs_utilAdmin.h> | |
34 | #include <afs/afs_bosAdmin.h> | |
35 | #include <afs/afs_clientAdmin.h> | |
36 | #include <afs/afs_kasAdmin.h> | |
37 | #include <afs/afs_ptsAdmin.h> | |
38 | ||
39 | #include <afs/kautils.h> | |
40 | #include <afs/bnode.h> | |
41 | #include <afs/prerror.h> | |
42 | #include <afs/keys.h> | |
43 | #include <afs/dirpath.h> | |
44 | #include <afs/cellconfig.h> | |
45 | ||
46 | #include "cfginternal.h" | |
47 | #include "afs_cfgAdmin.h" | |
48 | #include "../adminutil/afs_AdminInternal.h" | |
49 | ||
50 | ||
51 | ||
52 | /* Local declarations and definitions */ | |
53 | ||
54 | static int | |
55 | KasKeyIsZero(kas_encryptionKey_t * kasKey); | |
56 | ||
57 | static int | |
58 | KasKeyEmbeddedInString(const char *keyString, kas_encryptionKey_t * kasKey); | |
59 | ||
60 | ||
61 | ||
62 | ||
63 | /* ---------------- Exported Server Host functions ------------------ */ | |
64 | ||
65 | ||
66 | /* | |
67 | * cfg_HostQueryStatus() -- Query status of static server configuration | |
68 | * on host, i.e., status of required configuration files, etc. | |
69 | * Upon successful completion *configStP is set to the server | |
70 | * configuration status, with a value of zero (0) indicating that | |
71 | * the configuration is valid. | |
72 | * | |
73 | * If server configuration is not valid then *cellNameP is set to NULL; | |
74 | * otherwise, *cellNameP is an allocated buffer containing server cell. | |
75 | * | |
76 | * Warning: in determining if server configuration is valid, no check | |
77 | * is made for consistency with other servers in cell; also, the | |
78 | * internal consistency of configuration files may not be verified. | |
79 | */ | |
80 | int ADMINAPI | |
81 | cfg_HostQueryStatus(const char *hostName, /* name of host */ | |
82 | afs_status_p configStP, /* server config status */ | |
83 | char **cellNameP, /* server's cell */ | |
84 | afs_status_p st) | |
85 | { /* completion status */ | |
86 | int rc = 1; | |
87 | struct afsconf_keys keys; | |
88 | afs_status_t tst2, tst = 0; | |
89 | afs_status_t serverSt = 0; | |
90 | char *serverCellName = NULL; | |
91 | ||
92 | /* validate parameters */ | |
93 | ||
94 | if (hostName == NULL || *hostName == '\0') { | |
95 | tst = ADMCFGHOSTNAMENULL; | |
96 | } else if (strlen(hostName) > (MAXHOSTCHARS - 1)) { | |
97 | tst = ADMCFGHOSTNAMETOOLONG; | |
98 | } else if (configStP == NULL) { | |
99 | tst = ADMCFGCONFIGSTATUSPNULL; | |
100 | } else if (cellNameP == NULL) { | |
101 | tst = ADMCFGCELLNAMEPNULL; | |
102 | } | |
103 | ||
104 | /* remote configuration not yet supported; hostName must be local host */ | |
105 | ||
106 | if (tst == 0) { | |
107 | short isLocal; | |
108 | ||
109 | if (!cfgutil_HostNameIsLocal(hostName, &isLocal, &tst2)) { | |
110 | tst = tst2; | |
111 | } else if (!isLocal) { | |
112 | tst = ADMCFGNOTSUPPORTED; | |
113 | } | |
114 | } | |
115 | ||
116 | /* check for existence and readability of required server config files */ | |
117 | ||
118 | if (tst == 0) { | |
119 | int i; | |
120 | const char *cfgfile[4]; | |
121 | ||
122 | cfgfile[0] = AFSDIR_SERVER_THISCELL_FILEPATH; | |
123 | cfgfile[1] = AFSDIR_SERVER_CELLSERVDB_FILEPATH; | |
124 | cfgfile[2] = AFSDIR_SERVER_KEY_FILEPATH; | |
125 | cfgfile[3] = AFSDIR_SERVER_ULIST_FILEPATH; | |
126 | ||
127 | for (i = 0; i < 4; i++) { | |
128 | int fd; | |
129 | if ((fd = open(cfgfile[i], O_RDONLY)) < 0) { | |
130 | break; | |
131 | } | |
132 | (void)close(fd); | |
133 | } | |
134 | ||
135 | if (i < 4) { | |
136 | if (errno == EACCES) { | |
137 | tst = ADMNOPRIV; | |
138 | } else { | |
139 | serverSt = ADMCFGSERVERBASICINFOINVALID; | |
140 | } | |
141 | } | |
142 | } | |
143 | ||
144 | /* verify the required server config files to the degree possible */ | |
145 | ||
146 | if (tst == 0 && serverSt == 0) { | |
147 | struct afsconf_dir *confdir; | |
148 | ||
149 | if ((confdir = afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH)) == NULL) { | |
150 | /* one or more config files appears to be invalid */ | |
151 | serverSt = ADMCFGSERVERBASICINFOINVALID; | |
152 | } else { | |
153 | struct afsconf_entry *cellentry = NULL; | |
154 | ||
155 | if (confdir->cellName == NULL || *confdir->cellName == '\0') { | |
156 | /* no cell set for server */ | |
157 | serverSt = ADMCFGSERVERNOTINCELL; | |
158 | } else if ((afsconf_GetKeys(confdir, &keys) != 0) | |
159 | || (keys.nkeys == 0)) { | |
160 | /* no server keys */ | |
161 | serverSt = ADMCFGSERVERNOKEYS; | |
162 | } else { | |
163 | for (cellentry = confdir->entries; cellentry != NULL; | |
164 | cellentry = cellentry->next) { | |
165 | if (!strcasecmp | |
166 | (confdir->cellName, cellentry->cellInfo.name)) { | |
167 | break; | |
168 | } | |
169 | } | |
170 | ||
171 | if (cellentry == NULL) { | |
172 | serverSt = ADMCFGSERVERCELLNOTINDB; | |
173 | } else if (cellentry->cellInfo.numServers <= 0) { | |
174 | serverSt = ADMCFGSERVERCELLHASNODBENTRIES; | |
175 | } | |
176 | } | |
177 | ||
178 | if (tst == 0 && serverSt == 0) { | |
179 | /* everything looks good; malloc cell name buffer to return */ | |
180 | serverCellName = strdup(cellentry->cellInfo.name); | |
181 | if (serverCellName == NULL) | |
182 | tst = ADMNOMEM; | |
183 | } | |
184 | ||
185 | (void)afsconf_Close(confdir); | |
186 | } | |
187 | } | |
188 | ||
189 | if (tst == 0) { | |
190 | /* return server status and cell name */ | |
191 | *configStP = serverSt; | |
192 | ||
193 | if (serverSt == 0) { | |
194 | *cellNameP = serverCellName; | |
195 | } else { | |
196 | *cellNameP = NULL; | |
197 | } | |
198 | } else { | |
199 | /* indicate failure */ | |
200 | rc = 0; | |
201 | ||
202 | /* free cell name if allocated before failure */ | |
203 | if (serverCellName != NULL) { | |
204 | free(serverCellName); | |
205 | } | |
206 | } | |
207 | if (st != NULL) { | |
208 | *st = tst; | |
209 | } | |
210 | return rc; | |
211 | } | |
212 | ||
213 | ||
214 | /* | |
215 | * cfg_HostOpen() -- Obtain host configuration handle. | |
216 | */ | |
217 | int ADMINAPI | |
218 | cfg_HostOpen(void *cellHandle, /* cell handle */ | |
219 | const char *hostName, /* name of host to configure */ | |
220 | void **hostHandleP, /* host config handle */ | |
221 | afs_status_p st) | |
222 | { /* completion status */ | |
223 | int rc = 1; | |
224 | afs_status_t tst2, tst = 0; | |
225 | cfg_host_p cfg_host; | |
226 | char fullHostName[MAXHOSTCHARS]; | |
227 | ||
228 | /* validate parameters and resolve host name to fully qualified name */ | |
229 | ||
230 | if (!CellHandleIsValid(cellHandle, &tst2)) { | |
231 | tst = tst2; | |
232 | } else if (hostName == NULL || *hostName == '\0') { | |
233 | tst = ADMCFGHOSTNAMENULL; | |
234 | } else if (strlen(hostName) > (MAXHOSTCHARS - 1)) { | |
235 | tst = ADMCFGHOSTNAMETOOLONG; | |
236 | } else if (hostHandleP == NULL) { | |
237 | tst = ADMCFGHOSTHANDLEPNULL; | |
238 | } else if (!cfgutil_HostNameGetFull(hostName, fullHostName, &tst2)) { | |
239 | tst = tst2; | |
240 | } | |
241 | ||
242 | /* remote configuration not yet supported; hostName must be local host */ | |
243 | ||
244 | if (tst == 0) { | |
245 | short isLocal; | |
246 | ||
247 | if (!cfgutil_HostNameIsLocal(hostName, &isLocal, &tst2)) { | |
248 | tst = tst2; | |
249 | } else if (!isLocal) { | |
250 | tst = ADMCFGNOTSUPPORTED; | |
251 | } | |
252 | } | |
253 | ||
254 | /* allocate a host configuration handle */ | |
255 | ||
256 | if (tst == 0) { | |
257 | char *localHostName; | |
258 | ||
259 | if ((cfg_host = malloc(sizeof(cfg_host_t))) == NULL) { | |
260 | tst = ADMNOMEM; | |
261 | } else if ((localHostName = strdup(fullHostName)) == NULL) { | |
262 | free(cfg_host); | |
263 | tst = ADMNOMEM; | |
264 | } else { | |
265 | /* initialize handle */ | |
266 | cfg_host->begin_magic = BEGIN_MAGIC; | |
267 | cfg_host->is_valid = 1; | |
268 | cfg_host->hostName = localHostName; | |
269 | cfg_host->is_local = 1; /* not yet supporting remote config */ | |
270 | cfg_host->cellHandle = cellHandle; | |
271 | cfg_host->bosHandle = NULL; | |
272 | cfg_host->end_magic = END_MAGIC; | |
273 | ||
274 | if (!afsclient_CellNameGet | |
275 | (cfg_host->cellHandle, &cfg_host->cellName, &tst2)) { | |
276 | tst = tst2; | |
277 | } else if (pthread_mutex_init(&cfg_host->mutex, NULL)) { | |
278 | tst = ADMMUTEXINIT; | |
279 | } | |
280 | ||
281 | if (tst != 0) { | |
282 | /* cell name lookup or mutex initialization failed */ | |
283 | free(localHostName); | |
284 | free(cfg_host); | |
285 | } | |
286 | } | |
287 | } | |
288 | ||
289 | if (tst == 0) { | |
290 | /* success; return host config handle to user */ | |
291 | *hostHandleP = cfg_host; | |
292 | } else { | |
293 | /* indicate failure */ | |
294 | rc = 0; | |
295 | } | |
296 | if (st != NULL) { | |
297 | *st = tst; | |
298 | } | |
299 | return rc; | |
300 | } | |
301 | ||
302 | ||
303 | /* | |
304 | * cfg_HostClose() -- Release host configuration handle. | |
305 | */ | |
306 | int ADMINAPI | |
307 | cfg_HostClose(void *hostHandle, /* host config handle */ | |
308 | afs_status_p st) | |
309 | { /* completion status */ | |
310 | int rc = 1; | |
311 | afs_status_t tst2, tst = 0; | |
312 | cfg_host_p cfg_host = (cfg_host_p) hostHandle; | |
313 | ||
314 | /* validate parameters */ | |
315 | ||
316 | if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) { | |
317 | tst = tst2; | |
318 | } | |
319 | ||
320 | /* free handle; can assume no other thread using this handle */ | |
321 | ||
322 | if (tst == 0) { | |
323 | /* mark cfg handle invalid in case use after free (bug catcher) */ | |
324 | cfg_host->is_valid = 0; | |
325 | ||
326 | if (cfg_host->bosHandle != NULL) { | |
327 | if (!bos_ServerClose(cfg_host->bosHandle, &tst2)) { | |
328 | tst = tst2; | |
329 | } | |
330 | } | |
331 | free(cfg_host->hostName); | |
332 | (void)pthread_mutex_destroy(&cfg_host->mutex); | |
333 | free(cfg_host); | |
334 | } | |
335 | ||
336 | if (tst != 0) { | |
337 | rc = 0; | |
338 | } | |
339 | if (st != NULL) { | |
340 | *st = tst; | |
341 | } | |
342 | return rc; | |
343 | } | |
344 | ||
345 | ||
346 | /* | |
347 | * cfg_HostSetCell() -- Define server cell membership for host. | |
348 | * | |
349 | * The cellDbHosts argument is a multistring containing the names of | |
350 | * the existing database servers already configured in the cell; this | |
351 | * multistring list can be obtained via cfg_CellServDbEnumerate(). | |
352 | * If configuring the first server in a new cell then the cellDbHosts | |
353 | * list contains only the name of that host. | |
354 | * | |
355 | * Note: The names in cellDbHosts MUST exactly match those in the | |
356 | * cell-wide server CellServDB; using cfg_CellServDbEnumerate() | |
357 | * is highly recommended. | |
358 | */ | |
359 | int ADMINAPI | |
360 | cfg_HostSetCell(void *hostHandle, /* host config handle */ | |
361 | const char *cellName, /* cell name */ | |
362 | const char *cellDbHosts, /* cell database hosts */ | |
363 | afs_status_p st) | |
364 | { /* completion status */ | |
365 | int rc = 1; | |
366 | afs_status_t tst2, tst = 0; | |
367 | cfg_host_p cfg_host = (cfg_host_p) hostHandle; | |
368 | ||
369 | /* validate parameters */ | |
370 | ||
371 | if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) { | |
372 | tst = tst2; | |
373 | } else if (cellName == NULL || *cellName == '\0') { | |
374 | tst = ADMCFGCELLNAMENULL; | |
375 | } else if (strlen(cellName) > (MAXCELLCHARS - 1)) { | |
376 | tst = ADMCFGCELLNAMETOOLONG; | |
377 | } else if (!cfgutil_HostHandleCellNameCompatible(cfg_host, cellName)) { | |
378 | tst = ADMCFGCELLNAMECONFLICT; | |
379 | } else if (cellDbHosts == NULL || *cellDbHosts == '\0') { | |
380 | tst = ADMCFGCELLDBHOSTSNULL; | |
381 | } | |
382 | ||
383 | /* remote configuration not yet supported in this function */ | |
384 | ||
385 | if (tst == 0) { | |
386 | if (!cfg_host->is_local) { | |
387 | tst = ADMCFGNOTSUPPORTED; | |
388 | } | |
389 | } | |
390 | ||
391 | /* define server cell and cell database hosts */ | |
392 | ||
393 | if (tst == 0) { | |
394 | const char *dbHost = cellDbHosts; | |
395 | struct afsconf_cell hostCell; | |
396 | memset(&hostCell, 0, sizeof(hostCell)); | |
397 | ||
398 | strcpy(hostCell.name, cellName); | |
399 | hostCell.numServers = 0; | |
400 | ||
401 | while (*dbHost != '\0' && tst == 0) { | |
402 | /* fill in each database host */ | |
403 | size_t dbHostLen = strlen(dbHost); | |
404 | ||
405 | if (dbHostLen > (MAXHOSTCHARS - 1)) { | |
406 | tst = ADMCFGHOSTNAMETOOLONG; | |
407 | } else if (hostCell.numServers >= MAXHOSTSPERCELL) { | |
408 | tst = ADMCFGCELLDBHOSTCOUNTTOOLARGE; | |
409 | } else { | |
410 | strcpy(hostCell.hostName[hostCell.numServers++], dbHost); | |
411 | dbHost += dbHostLen + 1; | |
412 | } | |
413 | } | |
414 | ||
415 | if (tst == 0) { | |
416 | /* create server ThisCell/CellServDB dir if it does not exist */ | |
417 | #ifdef AFS_NT40_ENV | |
418 | (void)mkdir(AFSDIR_USR_DIRPATH); | |
419 | (void)mkdir(AFSDIR_SERVER_AFS_DIRPATH); | |
420 | (void)mkdir(AFSDIR_SERVER_ETC_DIRPATH); | |
421 | #else | |
422 | (void)mkdir(AFSDIR_USR_DIRPATH, 0755); | |
423 | (void)mkdir(AFSDIR_SERVER_AFS_DIRPATH, 0755); | |
424 | (void)mkdir(AFSDIR_SERVER_ETC_DIRPATH, 0755); | |
425 | #endif | |
426 | if (afsconf_SetCellInfo | |
427 | (NULL, AFSDIR_SERVER_ETC_DIRPATH, &hostCell)) { | |
428 | /* failed; most likely cause is bad host name */ | |
429 | tst = ADMCFGSERVERSETCELLFAILED; | |
430 | } | |
431 | } | |
432 | } | |
433 | ||
434 | if (tst != 0) { | |
435 | rc = 0; | |
436 | } | |
437 | if (st != NULL) { | |
438 | *st = tst; | |
439 | } | |
440 | return rc; | |
441 | } | |
442 | ||
443 | ||
444 | /* | |
445 | * cfg_HostSetAfsPrincipal() -- Put AFS server principal (afs) key in | |
446 | * host's KeyFile; principal is created if it does not exist. | |
447 | * | |
448 | * If first server host in cell, passwd must be initial password for | |
449 | * the afs principal; the afs principal is created. | |
450 | * | |
451 | * If additional server host, passwd can be specified or NULL; the | |
452 | * afs principal must already exist by definition. If passwd is NULL | |
453 | * then an attempt is made to fetch the afs key. If the key fetch fails | |
454 | * because pre 3.5 database servers are in use (which will only return a | |
455 | * key checksum) then the function fails with a return status of | |
456 | * ADMCFGAFSKEYNOTAVAILABLE; in this case the function should be called | |
457 | * again with passwd specified. If passwd is specified (not NULL) but the | |
458 | * password key fails a checksum comparison with the current afs key | |
459 | * then the function fails with a return status of ADMCFGAFSPASSWDINVALID. | |
460 | * | |
461 | * ASSUMPTIONS: Client configured and BOS server started; if first host in | |
462 | * cell then Authentication server must be started as well. | |
463 | */ | |
464 | int ADMINAPI | |
465 | cfg_HostSetAfsPrincipal(void *hostHandle, /* host config handle */ | |
466 | short isFirst, /* first server in cell flag */ | |
467 | const char *passwd, /* afs initial password */ | |
468 | afs_status_p st) | |
469 | { /* completion status */ | |
470 | int rc = 1; | |
471 | afs_status_t tst2, tst = 0; | |
472 | cfg_host_p cfg_host = (cfg_host_p) hostHandle; | |
473 | ||
474 | /* validate parameters */ | |
475 | ||
476 | if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) { | |
477 | tst = tst2; | |
478 | } else if ((isFirst && passwd == NULL) | |
479 | || (passwd != NULL && *passwd == '\0')) { | |
480 | tst = ADMCFGPASSWDNULL; | |
481 | } | |
482 | ||
483 | /* put afs key in host's KeyFile */ | |
484 | ||
485 | if (tst == 0) { | |
486 | kas_identity_t afsIdentity; | |
487 | kas_encryptionKey_t afsKey; | |
488 | int afsKvno = 0; | |
489 | ||
490 | strcpy(afsIdentity.principal, "afs"); | |
491 | afsIdentity.instance[0] = '\0'; | |
492 | ||
493 | if (isFirst) { | |
494 | /* create afs principal */ | |
495 | if (!kas_PrincipalCreate | |
496 | (cfg_host->cellHandle, NULL, &afsIdentity, passwd, &tst2) | |
497 | && tst2 != KAEXIST) { | |
498 | /* failed to create principal (and not because existed) */ | |
499 | tst = tst2; | |
500 | } | |
501 | } | |
502 | ||
503 | if (tst == 0) { | |
504 | /* retrive afs principal information to verify or obtain key */ | |
505 | kas_principalEntry_t afsEntry; | |
506 | ||
507 | if (!kas_PrincipalGet | |
508 | (cfg_host->cellHandle, NULL, &afsIdentity, &afsEntry, | |
509 | &tst2)) { | |
510 | tst = tst2; | |
511 | } else { | |
512 | if (passwd != NULL) { | |
513 | /* password given; form key and verify as most recent */ | |
514 | kas_encryptionKey_t passwdKey; | |
515 | unsigned int passwdKeyCksum; | |
516 | ||
517 | if (!kas_StringToKey | |
518 | (cfg_host->cellName, passwd, &passwdKey, &tst2) | |
519 | || !kas_KeyCheckSum(&passwdKey, &passwdKeyCksum, | |
520 | &tst2)) { | |
521 | /* failed to form key or key checksum */ | |
522 | tst = tst2; | |
523 | ||
524 | } else if (passwdKeyCksum != afsEntry.keyCheckSum) { | |
525 | /* passwd string does not generate most recent key; | |
526 | * check if passwd string embeds key directly. | |
527 | */ | |
528 | if (KasKeyEmbeddedInString(passwd, &passwdKey)) { | |
529 | /* passwd string embeds kas key */ | |
530 | if (!kas_KeyCheckSum | |
531 | (&passwdKey, &passwdKeyCksum, &tst2)) { | |
532 | tst = tst2; | |
533 | } else if (passwdKeyCksum != afsEntry.keyCheckSum) { | |
534 | /* passwd string does not embed valid key */ | |
535 | tst = ADMCFGAFSPASSWDINVALID; | |
536 | } | |
537 | } else { | |
538 | /* passwd string does NOT embed key */ | |
539 | tst = ADMCFGAFSPASSWDINVALID; | |
540 | } | |
541 | } | |
542 | ||
543 | if (tst == 0) { | |
544 | /* passwd seems to generate/embed most recent key */ | |
545 | afsKey = passwdKey; | |
546 | afsKvno = afsEntry.keyVersion; | |
547 | } | |
548 | ||
549 | } else { | |
550 | /* password NOT given; check if key retrieved since | |
551 | * pre 3.5 database servers only return key checksum | |
552 | */ | |
553 | if (KasKeyIsZero(&afsEntry.key)) { | |
554 | tst = ADMCFGAFSKEYNOTAVAILABLE; | |
555 | } else { | |
556 | afsKey = afsEntry.key; | |
557 | afsKvno = afsEntry.keyVersion; | |
558 | } | |
559 | } | |
560 | } | |
561 | } | |
562 | ||
563 | if (tst == 0) { | |
564 | /* add key to host's KeyFile; RPC must be unauthenticated; | |
565 | * bosserver is presumed to be in noauth mode. | |
566 | */ | |
567 | void *cellHandle, *bosHandle; | |
568 | ||
569 | if (!afsclient_NullCellOpen(&cellHandle, &tst2)) { | |
570 | tst = tst2; | |
571 | } else { | |
572 | if (!bos_ServerOpen | |
573 | (cellHandle, cfg_host->hostName, &bosHandle, &tst2)) { | |
574 | tst = tst2; | |
575 | } else { | |
576 | if (!bos_KeyCreate(bosHandle, afsKvno, &afsKey, &tst2) | |
577 | && tst2 != BZKEYINUSE) { | |
578 | /* failed to add key (and not because existed) */ | |
579 | tst = tst2; | |
580 | } | |
581 | ||
582 | if (!bos_ServerClose(bosHandle, &tst2)) { | |
583 | tst = tst2; | |
584 | } | |
585 | } | |
586 | ||
587 | if (!afsclient_CellClose(cellHandle, &tst2)) { | |
588 | tst = tst2; | |
589 | } | |
590 | } | |
591 | } | |
592 | } | |
593 | ||
594 | if (tst != 0) { | |
595 | rc = 0; | |
596 | } | |
597 | if (st != NULL) { | |
598 | *st = tst; | |
599 | } | |
600 | return rc; | |
601 | } | |
602 | ||
603 | ||
604 | /* | |
605 | * cfg_HostSetAdminPrincipal() -- Put generic administrator principal in | |
606 | * host's UserList; principal is created if it does not exist. | |
607 | * | |
608 | * If first server host in cell, passwd and afsUid must be the initial | |
609 | * password and the AFS UID for the admin principal; the admin principal | |
610 | * is created. | |
611 | * | |
612 | * If additional server host, passwd and afsUid are ignored; the admin | |
613 | * principal is assumed to exist. | |
614 | * | |
615 | * ASSUMPTIONS: Client configured and BOS server started; if first host in | |
616 | * cell then Authentication and Protection servers must be started as well. | |
617 | */ | |
618 | int ADMINAPI | |
619 | cfg_HostSetAdminPrincipal(void *hostHandle, /* host config handle */ | |
620 | short isFirst, /* first server in cell flag */ | |
621 | char *admin, /* admin principal name */ | |
622 | const char *passwd, /* admin initial password */ | |
623 | unsigned int afsUid, /* admin AFS UID */ | |
624 | afs_status_p st) | |
625 | { /* completion status */ | |
626 | int rc = 1; | |
627 | afs_status_t tst2, tst = 0; | |
628 | cfg_host_p cfg_host = (cfg_host_p) hostHandle; | |
629 | ||
630 | /* validate parameters and prepare host handle for bos functions */ | |
631 | ||
632 | if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) { | |
633 | tst = tst2; | |
634 | } else if (admin == NULL || *admin == '\0') { | |
635 | tst = ADMCFGADMINPRINCIPALNULL; | |
636 | } else if (strlen(admin) > (KAS_MAX_NAME_LEN - 1)) { | |
637 | tst = ADMCFGADMINPRINCIPALTOOLONG; | |
638 | } else if (isFirst && (passwd == NULL || *passwd == '\0')) { | |
639 | tst = ADMCFGPASSWDNULL; | |
640 | } else if (!cfgutil_HostHandleBosInit(cfg_host, &tst2)) { | |
641 | tst = tst2; | |
642 | } | |
643 | ||
644 | /* put admin in host's UserList */ | |
645 | ||
646 | if (tst == 0) { | |
647 | if (isFirst) { | |
648 | /* first server host in cell; create admin principal */ | |
649 | kas_identity_t adminIdentity; | |
650 | int adminUid = afsUid; | |
651 | kas_admin_t adminFlag = KAS_ADMIN; | |
652 | ||
653 | strcpy(adminIdentity.principal, admin); | |
654 | adminIdentity.instance[0] = '\0'; | |
655 | ||
656 | if (!kas_PrincipalCreate | |
657 | (cfg_host->cellHandle, NULL, &adminIdentity, passwd, &tst2) | |
658 | && tst2 != KAEXIST) { | |
659 | /* failed to create principal (and not because existed) */ | |
660 | tst = tst2; | |
661 | ||
662 | } else | |
663 | if (!kas_PrincipalFieldsSet | |
664 | (cfg_host->cellHandle, NULL, &adminIdentity, &adminFlag, | |
665 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | |
666 | &tst2)) { | |
667 | /* failed to set admin attributes */ | |
668 | tst = tst2; | |
669 | ||
670 | } else | |
671 | if (!pts_UserCreate | |
672 | (cfg_host->cellHandle, admin, &adminUid, &tst2) | |
673 | && tst2 != PREXIST) { | |
674 | /* failed to create user (and not because existed) */ | |
675 | tst = tst2; | |
676 | ||
677 | } else | |
678 | if (!pts_GroupMemberAdd | |
679 | (cfg_host->cellHandle, admin, "system:administrators", | |
680 | &tst2) && tst2 != PRIDEXIST) { | |
681 | /* failed to add to group (not because already there) */ | |
682 | tst = tst2; | |
683 | } | |
684 | } | |
685 | ||
686 | if (tst == 0) { | |
687 | /* add admin to host's UserList */ | |
688 | if (!bos_AdminCreate(cfg_host->bosHandle, admin, &tst2) | |
689 | && tst2 != EEXIST) { | |
690 | /* failed to add admin (and not because existed) */ | |
691 | /* DANGER: platform-specific errno values being returned */ | |
692 | tst = tst2; | |
693 | } | |
694 | } | |
695 | } | |
696 | ||
697 | if (tst != 0) { | |
698 | rc = 0; | |
699 | } | |
700 | if (st != NULL) { | |
701 | *st = tst; | |
702 | } | |
703 | return rc; | |
704 | } | |
705 | ||
706 | ||
707 | /* | |
708 | * cfg_HostInvalidate() -- Invalidate static server configuration on host. | |
709 | * | |
710 | * Server configuration invalidated only if BOS server is not running. | |
711 | */ | |
712 | int ADMINAPI | |
713 | cfg_HostInvalidate(void *hostHandle, /* host config handle */ | |
714 | afs_status_p st) | |
715 | { /* completion status */ | |
716 | int rc = 1; | |
717 | afs_status_t tst2, tst = 0; | |
718 | cfg_host_p cfg_host = (cfg_host_p) hostHandle; | |
719 | ||
720 | /* validate parameters */ | |
721 | ||
722 | if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) { | |
723 | tst = tst2; | |
724 | } | |
725 | ||
726 | /* remote configuration not yet supported in this function */ | |
727 | ||
728 | if (tst == 0) { | |
729 | if (!cfg_host->is_local) { | |
730 | tst = ADMCFGNOTSUPPORTED; | |
731 | } | |
732 | } | |
733 | ||
734 | /* make sure bosserver is not running on host */ | |
735 | ||
736 | #ifdef AFS_NT40_ENV | |
737 | /* Windows - bosserver is controlled via the BOS control service */ | |
738 | if (tst == 0) { | |
739 | DWORD svcState; | |
740 | ||
741 | if (!cfgutil_WindowsServiceQuery | |
742 | (AFSREG_SVR_SVC_NAME, &svcState, &tst2)) { | |
743 | tst = tst2; | |
744 | } else if (svcState != SERVICE_STOPPED) { | |
745 | tst = ADMCFGBOSSERVERACTIVE; | |
746 | } | |
747 | } | |
748 | #else | |
749 | if (tst == 0) { | |
750 | /* function not yet implemented for Unix */ | |
751 | tst = ADMCFGNOTSUPPORTED; | |
752 | } | |
753 | #endif /* AFS_NT40_ENV */ | |
754 | ||
755 | ||
756 | /* remove server state files */ | |
757 | ||
758 | if (tst == 0) { | |
759 | int i; | |
760 | const char *cfgdir[3]; | |
761 | ||
762 | cfgdir[0] = AFSDIR_SERVER_ETC_DIRPATH; | |
763 | cfgdir[1] = AFSDIR_SERVER_DB_DIRPATH; | |
764 | cfgdir[2] = AFSDIR_SERVER_LOCAL_DIRPATH; | |
765 | ||
766 | for (i = 0; i < 3 && tst == 0; i++) { | |
767 | if (!cfgutil_CleanDirectory(cfgdir[i], &tst2)) { | |
768 | tst = tst2; | |
769 | } | |
770 | } | |
771 | } | |
772 | ||
773 | /* remove all vice partition table entries */ | |
774 | ||
775 | #ifdef AFS_NT40_ENV | |
776 | if (tst == 0) { | |
777 | struct vpt_iter vpiter; | |
778 | struct vptab vpentry; | |
779 | ||
780 | /* note: ignore errors except from removal attempts */ | |
781 | ||
782 | if (!vpt_Start(&vpiter)) { | |
783 | while (!vpt_NextEntry(&vpiter, &vpentry)) { | |
784 | if (vpt_RemoveEntry(vpentry.vp_name)) { | |
785 | /* ENOENT implies entry does not exist; consider removed */ | |
786 | if (errno != ENOENT) { | |
787 | if (errno == EACCES) { | |
788 | tst = ADMNOPRIV; | |
789 | } else { | |
790 | tst = ADMCFGVPTABLEWRITEFAILED; | |
791 | } | |
792 | } | |
793 | } | |
794 | } | |
795 | (void)vpt_Finish(&vpiter); | |
796 | } | |
797 | } | |
798 | #else | |
799 | /* function not yet implemented for unix */ | |
800 | if (tst == 0) { | |
801 | tst = ADMCFGNOTSUPPORTED; | |
802 | } | |
803 | #endif /* AFS_NT40_ENV */ | |
804 | ||
805 | if (tst != 0) { | |
806 | rc = 0; | |
807 | } | |
808 | if (st != NULL) { | |
809 | *st = tst; | |
810 | } | |
811 | return rc; | |
812 | } | |
813 | ||
814 | ||
815 | ||
816 | /* | |
817 | * cfg_HostPartitionTableEnumerate() -- Enumerate AFS partition table entries. | |
818 | * | |
819 | * If the partition table is empty (or does not exist) then *tablePP | |
820 | * is set to NULL and *nEntriesP is set to zero (0). | |
821 | * | |
822 | * Partitions in table are not necessarily those being exported; a table | |
823 | * entry may have been added or removed since the fileserver last started. | |
824 | */ | |
825 | int ADMINAPI | |
826 | cfg_HostPartitionTableEnumerate(void *hostHandle, /* host config handle */ | |
827 | cfg_partitionEntry_t ** tablePP, /* table */ | |
828 | int *nEntriesP, /* table entry count */ | |
829 | afs_status_p st) | |
830 | { /* completion status */ | |
831 | int rc = 1; | |
832 | afs_status_t tst2, tst = 0; | |
833 | cfg_host_p cfg_host = (cfg_host_p) hostHandle; | |
834 | ||
835 | /* validate parameters */ | |
836 | ||
837 | if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) { | |
838 | tst = tst2; | |
839 | } else if (tablePP == NULL) { | |
840 | tst = ADMCFGVPTABLEPNULL; | |
841 | } else if (nEntriesP == NULL) { | |
842 | tst = ADMCFGVPTABLECOUNTPNULL; | |
843 | } | |
844 | ||
845 | /* remote configuration not yet supported in this function */ | |
846 | ||
847 | if (tst == 0) { | |
848 | if (!cfg_host->is_local) { | |
849 | tst = ADMCFGNOTSUPPORTED; | |
850 | } | |
851 | } | |
852 | ||
853 | /* enumerate the vice partition table */ | |
854 | ||
855 | #ifdef AFS_NT40_ENV | |
856 | if (tst == 0) { | |
857 | struct vpt_iter vpiter; | |
858 | struct vptab vpentry; | |
859 | int vpentryCountMax = 0; | |
860 | ||
861 | /* count table entries */ | |
862 | ||
863 | if (vpt_Start(&vpiter)) { | |
864 | /* ENOENT implies table does not exist (which is OK) */ | |
865 | if (errno != ENOENT) { | |
866 | if (errno == EACCES) { | |
867 | tst = ADMNOPRIV; | |
868 | } else { | |
869 | tst = ADMCFGVPTABLEREADFAILED; | |
870 | } | |
871 | } | |
872 | } else { | |
873 | while (!vpt_NextEntry(&vpiter, &vpentry)) { | |
874 | vpentryCountMax++; | |
875 | } | |
876 | if (errno != ENOENT) { | |
877 | tst = ADMCFGVPTABLEREADFAILED; | |
878 | } | |
879 | (void)vpt_Finish(&vpiter); | |
880 | } | |
881 | ||
882 | /* alloc storage for table entries; handle any entry count change */ | |
883 | ||
884 | if (tst == 0) { | |
885 | if (vpentryCountMax == 0) { | |
886 | *nEntriesP = 0; | |
887 | *tablePP = NULL; | |
888 | } else { | |
889 | /* return a two-part table; first points into second */ | |
890 | void *metaTablep; | |
891 | size_t metaTableSize; | |
892 | ||
893 | metaTableSize = | |
894 | vpentryCountMax * (sizeof(cfg_partitionEntry_t) + | |
895 | sizeof(struct vptab)); | |
896 | ||
897 | if ((metaTablep = malloc(metaTableSize)) == NULL) { | |
898 | tst = ADMNOMEM; | |
899 | } else { | |
900 | int i; | |
901 | cfg_partitionEntry_t *cpePart; | |
902 | struct vptab *vptPart; | |
903 | int vpentryCount = 0; | |
904 | ||
905 | cpePart = (cfg_partitionEntry_t *) metaTablep; | |
906 | vptPart = (struct vptab *)(&cpePart[vpentryCountMax]); | |
907 | ||
908 | for (i = 0; i < vpentryCountMax; i++) { | |
909 | cpePart[i].partitionName = vptPart[i].vp_name; | |
910 | cpePart[i].deviceName = vptPart[i].vp_dev; | |
911 | } | |
912 | ||
913 | if (vpt_Start(&vpiter)) { | |
914 | /* ENOENT implies table does not exist (which is OK) */ | |
915 | if (errno != ENOENT) { | |
916 | if (errno == EACCES) { | |
917 | tst = ADMNOPRIV; | |
918 | } else { | |
919 | tst = ADMCFGVPTABLEREADFAILED; | |
920 | } | |
921 | } | |
922 | } else { | |
923 | for (i = 0; i < vpentryCountMax; i++) { | |
924 | if (vpt_NextEntry(&vpiter, &vptPart[i])) { | |
925 | break; | |
926 | } | |
927 | } | |
928 | ||
929 | if (i < vpentryCountMax && errno != ENOENT) { | |
930 | tst = ADMCFGVPTABLEREADFAILED; | |
931 | } else { | |
932 | vpentryCount = i; | |
933 | } | |
934 | (void)vpt_Finish(&vpiter); | |
935 | } | |
936 | ||
937 | if (tst == 0) { | |
938 | *nEntriesP = vpentryCount; | |
939 | ||
940 | if (vpentryCount != 0) { | |
941 | *tablePP = (cfg_partitionEntry_t *) metaTablep; | |
942 | } else { | |
943 | *tablePP = NULL; | |
944 | free(metaTablep); | |
945 | } | |
946 | } else { | |
947 | free(metaTablep); | |
948 | } | |
949 | } | |
950 | } | |
951 | } | |
952 | } | |
953 | #else | |
954 | /* function not yet implemented for Unix */ | |
955 | if (tst == 0) { | |
956 | tst = ADMCFGNOTSUPPORTED; | |
957 | } | |
958 | #endif /* AFS_NT40_ENV */ | |
959 | ||
960 | if (tst != 0) { | |
961 | rc = 0; | |
962 | } | |
963 | if (st != NULL) { | |
964 | *st = tst; | |
965 | } | |
966 | return rc; | |
967 | } | |
968 | ||
969 | ||
970 | /* | |
971 | * cfg_HostPartitionTableAddEntry() -- Add or update AFS partition table entry. | |
972 | */ | |
973 | int ADMINAPI | |
974 | cfg_HostPartitionTableAddEntry(void *hostHandle, /* host config handle */ | |
975 | const char *partName, /* partition name */ | |
976 | const char *devName, /* device name */ | |
977 | afs_status_p st) | |
978 | { /* completion status */ | |
979 | int rc = 1; | |
980 | afs_status_t tst = 0; | |
981 | #ifdef AFS_NT40_ENV | |
982 | afs_status_t tst2; | |
983 | cfg_host_p cfg_host = (cfg_host_p) hostHandle; | |
984 | #endif | |
985 | ||
986 | #ifdef AFS_NT40_ENV | |
987 | /* validate parameters */ | |
988 | ||
989 | if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) { | |
990 | tst = tst2; | |
991 | } else if (partName == NULL) { | |
992 | tst = ADMCFGPARTITIONNAMENULL; | |
993 | } else if (!vpt_PartitionNameValid(partName)) { | |
994 | tst = ADMCFGPARTITIONNAMEBAD; | |
995 | } else if (devName == NULL) { | |
996 | tst = ADMCFGDEVICENAMENULL; | |
997 | } else if (!vpt_DeviceNameValid(devName)) { | |
998 | tst = ADMCFGDEVICENAMEBAD; | |
999 | } | |
1000 | ||
1001 | /* remote configuration not yet supported in this function */ | |
1002 | ||
1003 | if (tst == 0) { | |
1004 | if (!cfg_host->is_local) { | |
1005 | tst = ADMCFGNOTSUPPORTED; | |
1006 | } | |
1007 | } | |
1008 | ||
1009 | /* add entry to table */ | |
1010 | ||
1011 | if (tst == 0) { | |
1012 | struct vptab vpentry; | |
1013 | ||
1014 | strcpy(vpentry.vp_name, partName); | |
1015 | strcpy(vpentry.vp_dev, devName); | |
1016 | ||
1017 | if (vpt_AddEntry(&vpentry)) { | |
1018 | if (errno == EACCES) { | |
1019 | tst = ADMNOPRIV; | |
1020 | } else if (errno == EINVAL) { | |
1021 | /* shouldn't happen since checked partition/dev names */ | |
1022 | tst = ADMCFGVPTABLEENTRYBAD; | |
1023 | } else { | |
1024 | tst = ADMCFGVPTABLEWRITEFAILED; | |
1025 | } | |
1026 | } | |
1027 | } | |
1028 | #else | |
1029 | /* function not yet implemented for unix */ | |
1030 | if (tst == 0) { | |
1031 | tst = ADMCFGNOTSUPPORTED; | |
1032 | } | |
1033 | #endif /* AFS_NT40_ENV */ | |
1034 | ||
1035 | if (tst != 0) { | |
1036 | rc = 0; | |
1037 | } | |
1038 | if (st != NULL) { | |
1039 | *st = tst; | |
1040 | } | |
1041 | return rc; | |
1042 | } | |
1043 | ||
1044 | ||
1045 | /* | |
1046 | * cfg_HostPartitionTableRemoveEntry() -- Remove AFS partition table entry. | |
1047 | */ | |
1048 | int ADMINAPI | |
1049 | cfg_HostPartitionTableRemoveEntry(void *hostHandle, /* host config handle */ | |
1050 | const char *partName, /* partition name */ | |
1051 | afs_status_p st) | |
1052 | { /* completion status */ | |
1053 | int rc = 1; | |
1054 | afs_status_t tst = 0; | |
1055 | #ifdef AFS_NT40_ENV | |
1056 | afs_status_t tst2; | |
1057 | cfg_host_p cfg_host = (cfg_host_p) hostHandle; | |
1058 | #endif | |
1059 | ||
1060 | #ifdef AFS_NT40_ENV | |
1061 | /* validate parameters */ | |
1062 | ||
1063 | if (!cfgutil_HostHandleValidate(cfg_host, &tst2)) { | |
1064 | tst = tst2; | |
1065 | } else if (partName == NULL) { | |
1066 | tst = ADMCFGPARTITIONNAMENULL; | |
1067 | } else if (!vpt_PartitionNameValid(partName)) { | |
1068 | tst = ADMCFGPARTITIONNAMEBAD; | |
1069 | } | |
1070 | ||
1071 | /* remote configuration not yet supported in this function */ | |
1072 | ||
1073 | if (tst == 0) { | |
1074 | if (!cfg_host->is_local) { | |
1075 | tst = ADMCFGNOTSUPPORTED; | |
1076 | } | |
1077 | } | |
1078 | ||
1079 | /* remove entry from table */ | |
1080 | ||
1081 | if (tst == 0) { | |
1082 | if (vpt_RemoveEntry(partName)) { | |
1083 | /* ENOENT implies entry does not exist; consider to be removed */ | |
1084 | if (errno != ENOENT) { | |
1085 | if (errno == EACCES) { | |
1086 | tst = ADMNOPRIV; | |
1087 | } else if (errno == EINVAL) { | |
1088 | /* shouldn't happen since checked partition/dev names */ | |
1089 | tst = ADMCFGPARTITIONNAMEBAD; | |
1090 | } else { | |
1091 | tst = ADMCFGVPTABLEWRITEFAILED; | |
1092 | } | |
1093 | } | |
1094 | } | |
1095 | } | |
1096 | #else | |
1097 | /* function not yet implemented for unix */ | |
1098 | if (tst == 0) { | |
1099 | tst = ADMCFGNOTSUPPORTED; | |
1100 | } | |
1101 | #endif /* AFS_NT40_ENV */ | |
1102 | ||
1103 | if (tst != 0) { | |
1104 | rc = 0; | |
1105 | } | |
1106 | if (st != NULL) { | |
1107 | *st = tst; | |
1108 | } | |
1109 | return rc; | |
1110 | } | |
1111 | ||
1112 | ||
1113 | /* | |
1114 | * cfg_HostPartitionNameValid() -- check partition name syntax. | |
1115 | */ | |
1116 | int ADMINAPI | |
1117 | cfg_HostPartitionNameValid(const char *partName, /* partition name */ | |
1118 | short *isValidP, /* syntax is valid */ | |
1119 | afs_status_p st) | |
1120 | { /* completion status */ | |
1121 | int rc = 1; | |
1122 | afs_status_t tst = 0; | |
1123 | ||
1124 | /* validate parameters */ | |
1125 | ||
1126 | if (partName == NULL) { | |
1127 | tst = ADMCFGPARTITIONNAMENULL; | |
1128 | } else if (isValidP == NULL) { | |
1129 | tst = ADMCFGVALIDFLAGPNULL; | |
1130 | } | |
1131 | ||
1132 | /* check name syntax */ | |
1133 | ||
1134 | #ifdef AFS_NT40_ENV | |
1135 | if (tst == 0) { | |
1136 | *isValidP = vpt_PartitionNameValid(partName); | |
1137 | } | |
1138 | #else | |
1139 | /* function not yet implemented for Unix */ | |
1140 | if (tst == 0) { | |
1141 | tst = ADMCFGNOTSUPPORTED; | |
1142 | } | |
1143 | #endif | |
1144 | ||
1145 | if (tst != 0) { | |
1146 | rc = 0; | |
1147 | } | |
1148 | if (st != NULL) { | |
1149 | *st = tst; | |
1150 | } | |
1151 | return rc; | |
1152 | } | |
1153 | ||
1154 | ||
1155 | ||
1156 | /* | |
1157 | * cfg_HostDeviceNameValid() -- check device name syntax. | |
1158 | */ | |
1159 | int ADMINAPI | |
1160 | cfg_HostDeviceNameValid(const char *devName, /* device name */ | |
1161 | short *isValidP, /* syntax is valid */ | |
1162 | afs_status_p st) | |
1163 | { /* completion status */ | |
1164 | int rc = 1; | |
1165 | afs_status_t tst = 0; | |
1166 | ||
1167 | /* validate parameters */ | |
1168 | ||
1169 | if (devName == NULL) { | |
1170 | tst = ADMCFGDEVICENAMENULL; | |
1171 | } else if (isValidP == NULL) { | |
1172 | tst = ADMCFGVALIDFLAGPNULL; | |
1173 | } | |
1174 | ||
1175 | /* check name syntax */ | |
1176 | ||
1177 | #ifdef AFS_NT40_ENV | |
1178 | if (tst == 0) { | |
1179 | *isValidP = vpt_DeviceNameValid(devName); | |
1180 | } | |
1181 | #else | |
1182 | /* function not yet implemented for Unix */ | |
1183 | if (tst == 0) { | |
1184 | tst = ADMCFGNOTSUPPORTED; | |
1185 | } | |
1186 | #endif | |
1187 | ||
1188 | if (tst != 0) { | |
1189 | rc = 0; | |
1190 | } | |
1191 | if (st != NULL) { | |
1192 | *st = tst; | |
1193 | } | |
1194 | return rc; | |
1195 | } | |
1196 | ||
1197 | ||
1198 | ||
1199 | /* ---------------- Exported Utility functions ------------------ */ | |
1200 | ||
1201 | ||
1202 | /* | |
1203 | * cfg_StringDeallocate() -- Deallocate (multi)string returned by library. | |
1204 | */ | |
1205 | int ADMINAPI | |
1206 | cfg_StringDeallocate(char *stringDataP, /* (multi)string to deallocate */ | |
1207 | afs_status_p st) | |
1208 | { /* completion status */ | |
1209 | free(stringDataP); | |
1210 | if (st != NULL) { | |
1211 | *st = 0; | |
1212 | } | |
1213 | return 1; | |
1214 | } | |
1215 | ||
1216 | ||
1217 | /* | |
1218 | * cfg_PartitionListDeallocate() -- Deallocate partition table enumeration | |
1219 | * returned by library. | |
1220 | */ | |
1221 | int ADMINAPI | |
1222 | cfg_PartitionListDeallocate(cfg_partitionEntry_t * partitionListDataP, | |
1223 | afs_status_p st) | |
1224 | { | |
1225 | free(partitionListDataP); | |
1226 | if (st != NULL) { | |
1227 | *st = 0; | |
1228 | } | |
1229 | return 1; | |
1230 | } | |
1231 | ||
1232 | ||
1233 | ||
1234 | ||
1235 | /* ---------------- Local functions ------------------ */ | |
1236 | ||
1237 | ||
1238 | /* | |
1239 | * KasKeyIsZero() -- determine if kas key is zero | |
1240 | * | |
1241 | * RETURN CODES: 1 if zero, 0 otherwise | |
1242 | */ | |
1243 | static int | |
1244 | KasKeyIsZero(kas_encryptionKey_t * kasKey) | |
1245 | { | |
1246 | char *keyp = (char *)kasKey; | |
1247 | int i; | |
1248 | ||
1249 | for (i = 0; i < sizeof(*kasKey); i++) { | |
1250 | if (*keyp++ != 0) { | |
1251 | return 0; | |
1252 | } | |
1253 | } | |
1254 | return 1; | |
1255 | } | |
1256 | ||
1257 | ||
1258 | /* | |
1259 | * KasKeyEmbeddedInString() -- determine if kas key is embedded in string | |
1260 | * and return key if extant. | |
1261 | * | |
1262 | * RETURN CODES: 1 if embedded key found, 0 otherwise | |
1263 | */ | |
1264 | static int | |
1265 | KasKeyEmbeddedInString(const char *keyString, kas_encryptionKey_t * kasKey) | |
1266 | { | |
1267 | char *octalDigits = "01234567"; | |
1268 | ||
1269 | /* keyString format is exactly 24 octal digits if embeds kas key */ | |
1270 | if (strlen(keyString) == 24 && strspn(keyString, octalDigits) == 24) { | |
1271 | /* kas key is embedded in keyString; extract it */ | |
1272 | int i; | |
1273 | ||
1274 | for (i = 0; i < 24; i += 3) { | |
1275 | char keyPiece[4]; | |
1276 | unsigned char keyPieceVal; | |
1277 | ||
1278 | keyPiece[0] = keyString[i]; | |
1279 | keyPiece[1] = keyString[i + 1]; | |
1280 | keyPiece[2] = keyString[i + 2]; | |
1281 | keyPiece[3] = '\0'; | |
1282 | ||
1283 | keyPieceVal = (unsigned char)strtoul(keyPiece, NULL, 8); | |
1284 | ||
1285 | *((unsigned char *)kasKey + (i / 3)) = keyPieceVal; | |
1286 | } | |
1287 | return 1; | |
1288 | } else { | |
1289 | /* key NOT embedded in keyString */ | |
1290 | return 0; | |
1291 | } | |
1292 | } |