2 * Copyright 2000, International Business Machines Corporation and others.
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
10 /* This file implements configuration functions in the following categories:
11 * cfg_Host*() - manipulate static server configuration information.
14 #include <afsconfig.h>
15 #include <afs/param.h>
23 #include <WINNT/vptab.h>
24 #include <WINNT/afsreg.h>
26 #endif /* AFS_NT40_ENV */
29 #include <rx/rxstat.h>
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>
39 #include <afs/kautils.h>
40 #include <afs/bnode.h>
41 #include <afs/prerror.h>
43 #include <afs/dirpath.h>
44 #include <afs/cellconfig.h>
46 #include "cfginternal.h"
47 #include "afs_cfgAdmin.h"
48 #include "../adminutil/afs_AdminInternal.h"
52 /* Local declarations and definitions */
55 KasKeyIsZero(kas_encryptionKey_t
* kasKey
);
58 KasKeyEmbeddedInString(const char *keyString
, kas_encryptionKey_t
* kasKey
);
63 /* ---------------- Exported Server Host functions ------------------ */
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.
73 * If server configuration is not valid then *cellNameP is set to NULL;
74 * otherwise, *cellNameP is an allocated buffer containing server cell.
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.
81 cfg_HostQueryStatus(const char *hostName
, /* name of host */
82 afs_status_p configStP
, /* server config status */
83 char **cellNameP
, /* server's cell */
85 { /* completion status */
87 struct afsconf_keys keys
;
88 afs_status_t tst2
, tst
= 0;
89 afs_status_t serverSt
= 0;
90 char *serverCellName
= NULL
;
92 /* validate parameters */
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
;
104 /* remote configuration not yet supported; hostName must be local host */
109 if (!cfgutil_HostNameIsLocal(hostName
, &isLocal
, &tst2
)) {
111 } else if (!isLocal
) {
112 tst
= ADMCFGNOTSUPPORTED
;
116 /* check for existence and readability of required server config files */
120 const char *cfgfile
[4];
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
;
127 for (i
= 0; i
< 4; i
++) {
129 if ((fd
= open(cfgfile
[i
], O_RDONLY
)) < 0) {
136 if (errno
== EACCES
) {
139 serverSt
= ADMCFGSERVERBASICINFOINVALID
;
144 /* verify the required server config files to the degree possible */
146 if (tst
== 0 && serverSt
== 0) {
147 struct afsconf_dir
*confdir
;
149 if ((confdir
= afsconf_Open(AFSDIR_SERVER_ETC_DIRPATH
)) == NULL
) {
150 /* one or more config files appears to be invalid */
151 serverSt
= ADMCFGSERVERBASICINFOINVALID
;
153 struct afsconf_entry
*cellentry
= NULL
;
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)) {
161 serverSt
= ADMCFGSERVERNOKEYS
;
163 for (cellentry
= confdir
->entries
; cellentry
!= NULL
;
164 cellentry
= cellentry
->next
) {
166 (confdir
->cellName
, cellentry
->cellInfo
.name
)) {
171 if (cellentry
== NULL
) {
172 serverSt
= ADMCFGSERVERCELLNOTINDB
;
173 } else if (cellentry
->cellInfo
.numServers
<= 0) {
174 serverSt
= ADMCFGSERVERCELLHASNODBENTRIES
;
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
)
185 (void)afsconf_Close(confdir
);
190 /* return server status and cell name */
191 *configStP
= serverSt
;
194 *cellNameP
= serverCellName
;
199 /* indicate failure */
202 /* free cell name if allocated before failure */
203 if (serverCellName
!= NULL
) {
204 free(serverCellName
);
215 * cfg_HostOpen() -- Obtain host configuration handle.
218 cfg_HostOpen(void *cellHandle
, /* cell handle */
219 const char *hostName
, /* name of host to configure */
220 void **hostHandleP
, /* host config handle */
222 { /* completion status */
224 afs_status_t tst2
, tst
= 0;
226 char fullHostName
[MAXHOSTCHARS
];
228 /* validate parameters and resolve host name to fully qualified name */
230 if (!CellHandleIsValid(cellHandle
, &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
)) {
242 /* remote configuration not yet supported; hostName must be local host */
247 if (!cfgutil_HostNameIsLocal(hostName
, &isLocal
, &tst2
)) {
249 } else if (!isLocal
) {
250 tst
= ADMCFGNOTSUPPORTED
;
254 /* allocate a host configuration handle */
259 if ((cfg_host
= malloc(sizeof(cfg_host_t
))) == NULL
) {
261 } else if ((localHostName
= strdup(fullHostName
)) == NULL
) {
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
;
274 if (!afsclient_CellNameGet
275 (cfg_host
->cellHandle
, &cfg_host
->cellName
, &tst2
)) {
277 } else if (pthread_mutex_init(&cfg_host
->mutex
, NULL
)) {
282 /* cell name lookup or mutex initialization failed */
290 /* success; return host config handle to user */
291 *hostHandleP
= cfg_host
;
293 /* indicate failure */
304 * cfg_HostClose() -- Release host configuration handle.
307 cfg_HostClose(void *hostHandle
, /* host config handle */
309 { /* completion status */
311 afs_status_t tst2
, tst
= 0;
312 cfg_host_p cfg_host
= (cfg_host_p
) hostHandle
;
314 /* validate parameters */
316 if (!cfgutil_HostHandleValidate(cfg_host
, &tst2
)) {
320 /* free handle; can assume no other thread using this handle */
323 /* mark cfg handle invalid in case use after free (bug catcher) */
324 cfg_host
->is_valid
= 0;
326 if (cfg_host
->bosHandle
!= NULL
) {
327 if (!bos_ServerClose(cfg_host
->bosHandle
, &tst2
)) {
331 free(cfg_host
->hostName
);
332 (void)pthread_mutex_destroy(&cfg_host
->mutex
);
347 * cfg_HostSetCell() -- Define server cell membership for host.
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.
355 * Note: The names in cellDbHosts MUST exactly match those in the
356 * cell-wide server CellServDB; using cfg_CellServDbEnumerate()
357 * is highly recommended.
360 cfg_HostSetCell(void *hostHandle
, /* host config handle */
361 const char *cellName
, /* cell name */
362 const char *cellDbHosts
, /* cell database hosts */
364 { /* completion status */
366 afs_status_t tst2
, tst
= 0;
367 cfg_host_p cfg_host
= (cfg_host_p
) hostHandle
;
369 /* validate parameters */
371 if (!cfgutil_HostHandleValidate(cfg_host
, &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
;
383 /* remote configuration not yet supported in this function */
386 if (!cfg_host
->is_local
) {
387 tst
= ADMCFGNOTSUPPORTED
;
391 /* define server cell and cell database hosts */
394 const char *dbHost
= cellDbHosts
;
395 struct afsconf_cell hostCell
;
396 memset(&hostCell
, 0, sizeof(hostCell
));
398 strcpy(hostCell
.name
, cellName
);
399 hostCell
.numServers
= 0;
401 while (*dbHost
!= '\0' && tst
== 0) {
402 /* fill in each database host */
403 size_t dbHostLen
= strlen(dbHost
);
405 if (dbHostLen
> (MAXHOSTCHARS
- 1)) {
406 tst
= ADMCFGHOSTNAMETOOLONG
;
407 } else if (hostCell
.numServers
>= MAXHOSTSPERCELL
) {
408 tst
= ADMCFGCELLDBHOSTCOUNTTOOLARGE
;
410 strcpy(hostCell
.hostName
[hostCell
.numServers
++], dbHost
);
411 dbHost
+= dbHostLen
+ 1;
416 /* create server ThisCell/CellServDB dir if it does not exist */
418 (void)mkdir(AFSDIR_USR_DIRPATH
);
419 (void)mkdir(AFSDIR_SERVER_AFS_DIRPATH
);
420 (void)mkdir(AFSDIR_SERVER_ETC_DIRPATH
);
422 (void)mkdir(AFSDIR_USR_DIRPATH
, 0755);
423 (void)mkdir(AFSDIR_SERVER_AFS_DIRPATH
, 0755);
424 (void)mkdir(AFSDIR_SERVER_ETC_DIRPATH
, 0755);
426 if (afsconf_SetCellInfo
427 (NULL
, AFSDIR_SERVER_ETC_DIRPATH
, &hostCell
)) {
428 /* failed; most likely cause is bad host name */
429 tst
= ADMCFGSERVERSETCELLFAILED
;
445 * cfg_HostSetAfsPrincipal() -- Put AFS server principal (afs) key in
446 * host's KeyFile; principal is created if it does not exist.
448 * If first server host in cell, passwd must be initial password for
449 * the afs principal; the afs principal is created.
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.
461 * ASSUMPTIONS: Client configured and BOS server started; if first host in
462 * cell then Authentication server must be started as well.
465 cfg_HostSetAfsPrincipal(void *hostHandle
, /* host config handle */
466 short isFirst
, /* first server in cell flag */
467 const char *passwd
, /* afs initial password */
469 { /* completion status */
471 afs_status_t tst2
, tst
= 0;
472 cfg_host_p cfg_host
= (cfg_host_p
) hostHandle
;
474 /* validate parameters */
476 if (!cfgutil_HostHandleValidate(cfg_host
, &tst2
)) {
478 } else if ((isFirst
&& passwd
== NULL
)
479 || (passwd
!= NULL
&& *passwd
== '\0')) {
480 tst
= ADMCFGPASSWDNULL
;
483 /* put afs key in host's KeyFile */
486 kas_identity_t afsIdentity
;
487 kas_encryptionKey_t afsKey
;
490 strcpy(afsIdentity
.principal
, "afs");
491 afsIdentity
.instance
[0] = '\0';
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) */
504 /* retrive afs principal information to verify or obtain key */
505 kas_principalEntry_t afsEntry
;
507 if (!kas_PrincipalGet
508 (cfg_host
->cellHandle
, NULL
, &afsIdentity
, &afsEntry
,
512 if (passwd
!= NULL
) {
513 /* password given; form key and verify as most recent */
514 kas_encryptionKey_t passwdKey
;
515 unsigned int passwdKeyCksum
;
518 (cfg_host
->cellName
, passwd
, &passwdKey
, &tst2
)
519 || !kas_KeyCheckSum(&passwdKey
, &passwdKeyCksum
,
521 /* failed to form key or key checksum */
524 } else if (passwdKeyCksum
!= afsEntry
.keyCheckSum
) {
525 /* passwd string does not generate most recent key;
526 * check if passwd string embeds key directly.
528 if (KasKeyEmbeddedInString(passwd
, &passwdKey
)) {
529 /* passwd string embeds kas key */
531 (&passwdKey
, &passwdKeyCksum
, &tst2
)) {
533 } else if (passwdKeyCksum
!= afsEntry
.keyCheckSum
) {
534 /* passwd string does not embed valid key */
535 tst
= ADMCFGAFSPASSWDINVALID
;
538 /* passwd string does NOT embed key */
539 tst
= ADMCFGAFSPASSWDINVALID
;
544 /* passwd seems to generate/embed most recent key */
546 afsKvno
= afsEntry
.keyVersion
;
550 /* password NOT given; check if key retrieved since
551 * pre 3.5 database servers only return key checksum
553 if (KasKeyIsZero(&afsEntry
.key
)) {
554 tst
= ADMCFGAFSKEYNOTAVAILABLE
;
556 afsKey
= afsEntry
.key
;
557 afsKvno
= afsEntry
.keyVersion
;
564 /* add key to host's KeyFile; RPC must be unauthenticated;
565 * bosserver is presumed to be in noauth mode.
567 void *cellHandle
, *bosHandle
;
569 if (!afsclient_NullCellOpen(&cellHandle
, &tst2
)) {
573 (cellHandle
, cfg_host
->hostName
, &bosHandle
, &tst2
)) {
576 if (!bos_KeyCreate(bosHandle
, afsKvno
, &afsKey
, &tst2
)
577 && tst2
!= BZKEYINUSE
) {
578 /* failed to add key (and not because existed) */
582 if (!bos_ServerClose(bosHandle
, &tst2
)) {
587 if (!afsclient_CellClose(cellHandle
, &tst2
)) {
605 * cfg_HostSetAdminPrincipal() -- Put generic administrator principal in
606 * host's UserList; principal is created if it does not exist.
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
612 * If additional server host, passwd and afsUid are ignored; the admin
613 * principal is assumed to exist.
615 * ASSUMPTIONS: Client configured and BOS server started; if first host in
616 * cell then Authentication and Protection servers must be started as well.
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 */
625 { /* completion status */
627 afs_status_t tst2
, tst
= 0;
628 cfg_host_p cfg_host
= (cfg_host_p
) hostHandle
;
630 /* validate parameters and prepare host handle for bos functions */
632 if (!cfgutil_HostHandleValidate(cfg_host
, &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
)) {
644 /* put admin in host's UserList */
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
;
653 strcpy(adminIdentity
.principal
, admin
);
654 adminIdentity
.instance
[0] = '\0';
656 if (!kas_PrincipalCreate
657 (cfg_host
->cellHandle
, NULL
, &adminIdentity
, passwd
, &tst2
)
658 && tst2
!= KAEXIST
) {
659 /* failed to create principal (and not because existed) */
663 if (!kas_PrincipalFieldsSet
664 (cfg_host
->cellHandle
, NULL
, &adminIdentity
, &adminFlag
,
665 NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
, NULL
,
667 /* failed to set admin attributes */
672 (cfg_host
->cellHandle
, admin
, &adminUid
, &tst2
)
673 && tst2
!= PREXIST
) {
674 /* failed to create user (and not because existed) */
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) */
687 /* add admin to host's UserList */
688 if (!bos_AdminCreate(cfg_host
->bosHandle
, admin
, &tst2
)
690 /* failed to add admin (and not because existed) */
691 /* DANGER: platform-specific errno values being returned */
708 * cfg_HostInvalidate() -- Invalidate static server configuration on host.
710 * Server configuration invalidated only if BOS server is not running.
713 cfg_HostInvalidate(void *hostHandle
, /* host config handle */
715 { /* completion status */
717 afs_status_t tst2
, tst
= 0;
718 cfg_host_p cfg_host
= (cfg_host_p
) hostHandle
;
720 /* validate parameters */
722 if (!cfgutil_HostHandleValidate(cfg_host
, &tst2
)) {
726 /* remote configuration not yet supported in this function */
729 if (!cfg_host
->is_local
) {
730 tst
= ADMCFGNOTSUPPORTED
;
734 /* make sure bosserver is not running on host */
737 /* Windows - bosserver is controlled via the BOS control service */
741 if (!cfgutil_WindowsServiceQuery
742 (AFSREG_SVR_SVC_NAME
, &svcState
, &tst2
)) {
744 } else if (svcState
!= SERVICE_STOPPED
) {
745 tst
= ADMCFGBOSSERVERACTIVE
;
750 /* function not yet implemented for Unix */
751 tst
= ADMCFGNOTSUPPORTED
;
753 #endif /* AFS_NT40_ENV */
756 /* remove server state files */
760 const char *cfgdir
[3];
762 cfgdir
[0] = AFSDIR_SERVER_ETC_DIRPATH
;
763 cfgdir
[1] = AFSDIR_SERVER_DB_DIRPATH
;
764 cfgdir
[2] = AFSDIR_SERVER_LOCAL_DIRPATH
;
766 for (i
= 0; i
< 3 && tst
== 0; i
++) {
767 if (!cfgutil_CleanDirectory(cfgdir
[i
], &tst2
)) {
773 /* remove all vice partition table entries */
777 struct vpt_iter vpiter
;
778 struct vptab vpentry
;
780 /* note: ignore errors except from removal attempts */
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
) {
790 tst
= ADMCFGVPTABLEWRITEFAILED
;
795 (void)vpt_Finish(&vpiter
);
799 /* function not yet implemented for unix */
801 tst
= ADMCFGNOTSUPPORTED
;
803 #endif /* AFS_NT40_ENV */
817 * cfg_HostPartitionTableEnumerate() -- Enumerate AFS partition table entries.
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).
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.
826 cfg_HostPartitionTableEnumerate(void *hostHandle
, /* host config handle */
827 cfg_partitionEntry_t
** tablePP
, /* table */
828 int *nEntriesP
, /* table entry count */
830 { /* completion status */
832 afs_status_t tst2
, tst
= 0;
833 cfg_host_p cfg_host
= (cfg_host_p
) hostHandle
;
835 /* validate parameters */
837 if (!cfgutil_HostHandleValidate(cfg_host
, &tst2
)) {
839 } else if (tablePP
== NULL
) {
840 tst
= ADMCFGVPTABLEPNULL
;
841 } else if (nEntriesP
== NULL
) {
842 tst
= ADMCFGVPTABLECOUNTPNULL
;
845 /* remote configuration not yet supported in this function */
848 if (!cfg_host
->is_local
) {
849 tst
= ADMCFGNOTSUPPORTED
;
853 /* enumerate the vice partition table */
857 struct vpt_iter vpiter
;
858 struct vptab vpentry
;
859 int vpentryCountMax
= 0;
861 /* count table entries */
863 if (vpt_Start(&vpiter
)) {
864 /* ENOENT implies table does not exist (which is OK) */
865 if (errno
!= ENOENT
) {
866 if (errno
== EACCES
) {
869 tst
= ADMCFGVPTABLEREADFAILED
;
873 while (!vpt_NextEntry(&vpiter
, &vpentry
)) {
876 if (errno
!= ENOENT
) {
877 tst
= ADMCFGVPTABLEREADFAILED
;
879 (void)vpt_Finish(&vpiter
);
882 /* alloc storage for table entries; handle any entry count change */
885 if (vpentryCountMax
== 0) {
889 /* return a two-part table; first points into second */
891 size_t metaTableSize
;
894 vpentryCountMax
* (sizeof(cfg_partitionEntry_t
) +
895 sizeof(struct vptab
));
897 if ((metaTablep
= malloc(metaTableSize
)) == NULL
) {
901 cfg_partitionEntry_t
*cpePart
;
902 struct vptab
*vptPart
;
903 int vpentryCount
= 0;
905 cpePart
= (cfg_partitionEntry_t
*) metaTablep
;
906 vptPart
= (struct vptab
*)(&cpePart
[vpentryCountMax
]);
908 for (i
= 0; i
< vpentryCountMax
; i
++) {
909 cpePart
[i
].partitionName
= vptPart
[i
].vp_name
;
910 cpePart
[i
].deviceName
= vptPart
[i
].vp_dev
;
913 if (vpt_Start(&vpiter
)) {
914 /* ENOENT implies table does not exist (which is OK) */
915 if (errno
!= ENOENT
) {
916 if (errno
== EACCES
) {
919 tst
= ADMCFGVPTABLEREADFAILED
;
923 for (i
= 0; i
< vpentryCountMax
; i
++) {
924 if (vpt_NextEntry(&vpiter
, &vptPart
[i
])) {
929 if (i
< vpentryCountMax
&& errno
!= ENOENT
) {
930 tst
= ADMCFGVPTABLEREADFAILED
;
934 (void)vpt_Finish(&vpiter
);
938 *nEntriesP
= vpentryCount
;
940 if (vpentryCount
!= 0) {
941 *tablePP
= (cfg_partitionEntry_t
*) metaTablep
;
954 /* function not yet implemented for Unix */
956 tst
= ADMCFGNOTSUPPORTED
;
958 #endif /* AFS_NT40_ENV */
971 * cfg_HostPartitionTableAddEntry() -- Add or update AFS partition table entry.
974 cfg_HostPartitionTableAddEntry(void *hostHandle
, /* host config handle */
975 const char *partName
, /* partition name */
976 const char *devName
, /* device name */
978 { /* completion status */
980 afs_status_t tst
= 0;
983 cfg_host_p cfg_host
= (cfg_host_p
) hostHandle
;
987 /* validate parameters */
989 if (!cfgutil_HostHandleValidate(cfg_host
, &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
;
1001 /* remote configuration not yet supported in this function */
1004 if (!cfg_host
->is_local
) {
1005 tst
= ADMCFGNOTSUPPORTED
;
1009 /* add entry to table */
1012 struct vptab vpentry
;
1014 strcpy(vpentry
.vp_name
, partName
);
1015 strcpy(vpentry
.vp_dev
, devName
);
1017 if (vpt_AddEntry(&vpentry
)) {
1018 if (errno
== EACCES
) {
1020 } else if (errno
== EINVAL
) {
1021 /* shouldn't happen since checked partition/dev names */
1022 tst
= ADMCFGVPTABLEENTRYBAD
;
1024 tst
= ADMCFGVPTABLEWRITEFAILED
;
1029 /* function not yet implemented for unix */
1031 tst
= ADMCFGNOTSUPPORTED
;
1033 #endif /* AFS_NT40_ENV */
1046 * cfg_HostPartitionTableRemoveEntry() -- Remove AFS partition table entry.
1049 cfg_HostPartitionTableRemoveEntry(void *hostHandle
, /* host config handle */
1050 const char *partName
, /* partition name */
1052 { /* completion status */
1054 afs_status_t tst
= 0;
1057 cfg_host_p cfg_host
= (cfg_host_p
) hostHandle
;
1061 /* validate parameters */
1063 if (!cfgutil_HostHandleValidate(cfg_host
, &tst2
)) {
1065 } else if (partName
== NULL
) {
1066 tst
= ADMCFGPARTITIONNAMENULL
;
1067 } else if (!vpt_PartitionNameValid(partName
)) {
1068 tst
= ADMCFGPARTITIONNAMEBAD
;
1071 /* remote configuration not yet supported in this function */
1074 if (!cfg_host
->is_local
) {
1075 tst
= ADMCFGNOTSUPPORTED
;
1079 /* remove entry from table */
1082 if (vpt_RemoveEntry(partName
)) {
1083 /* ENOENT implies entry does not exist; consider to be removed */
1084 if (errno
!= ENOENT
) {
1085 if (errno
== EACCES
) {
1087 } else if (errno
== EINVAL
) {
1088 /* shouldn't happen since checked partition/dev names */
1089 tst
= ADMCFGPARTITIONNAMEBAD
;
1091 tst
= ADMCFGVPTABLEWRITEFAILED
;
1097 /* function not yet implemented for unix */
1099 tst
= ADMCFGNOTSUPPORTED
;
1101 #endif /* AFS_NT40_ENV */
1114 * cfg_HostPartitionNameValid() -- check partition name syntax.
1117 cfg_HostPartitionNameValid(const char *partName
, /* partition name */
1118 short *isValidP
, /* syntax is valid */
1120 { /* completion status */
1122 afs_status_t tst
= 0;
1124 /* validate parameters */
1126 if (partName
== NULL
) {
1127 tst
= ADMCFGPARTITIONNAMENULL
;
1128 } else if (isValidP
== NULL
) {
1129 tst
= ADMCFGVALIDFLAGPNULL
;
1132 /* check name syntax */
1136 *isValidP
= vpt_PartitionNameValid(partName
);
1139 /* function not yet implemented for Unix */
1141 tst
= ADMCFGNOTSUPPORTED
;
1157 * cfg_HostDeviceNameValid() -- check device name syntax.
1160 cfg_HostDeviceNameValid(const char *devName
, /* device name */
1161 short *isValidP
, /* syntax is valid */
1163 { /* completion status */
1165 afs_status_t tst
= 0;
1167 /* validate parameters */
1169 if (devName
== NULL
) {
1170 tst
= ADMCFGDEVICENAMENULL
;
1171 } else if (isValidP
== NULL
) {
1172 tst
= ADMCFGVALIDFLAGPNULL
;
1175 /* check name syntax */
1179 *isValidP
= vpt_DeviceNameValid(devName
);
1182 /* function not yet implemented for Unix */
1184 tst
= ADMCFGNOTSUPPORTED
;
1199 /* ---------------- Exported Utility functions ------------------ */
1203 * cfg_StringDeallocate() -- Deallocate (multi)string returned by library.
1206 cfg_StringDeallocate(char *stringDataP
, /* (multi)string to deallocate */
1208 { /* completion status */
1218 * cfg_PartitionListDeallocate() -- Deallocate partition table enumeration
1219 * returned by library.
1222 cfg_PartitionListDeallocate(cfg_partitionEntry_t
* partitionListDataP
,
1225 free(partitionListDataP
);
1235 /* ---------------- Local functions ------------------ */
1239 * KasKeyIsZero() -- determine if kas key is zero
1241 * RETURN CODES: 1 if zero, 0 otherwise
1244 KasKeyIsZero(kas_encryptionKey_t
* kasKey
)
1246 char *keyp
= (char *)kasKey
;
1249 for (i
= 0; i
< sizeof(*kasKey
); i
++) {
1259 * KasKeyEmbeddedInString() -- determine if kas key is embedded in string
1260 * and return key if extant.
1262 * RETURN CODES: 1 if embedded key found, 0 otherwise
1265 KasKeyEmbeddedInString(const char *keyString
, kas_encryptionKey_t
* kasKey
)
1267 char *octalDigits
= "01234567";
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 */
1274 for (i
= 0; i
< 24; i
+= 3) {
1276 unsigned char keyPieceVal
;
1278 keyPiece
[0] = keyString
[i
];
1279 keyPiece
[1] = keyString
[i
+ 1];
1280 keyPiece
[2] = keyString
[i
+ 2];
1283 keyPieceVal
= (unsigned char)strtoul(keyPiece
, NULL
, 8);
1285 *((unsigned char *)kasKey
+ (i
/ 3)) = keyPieceVal
;
1289 /* key NOT embedded in keyString */