4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
24 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
28 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
29 * Use is subject to license terms.
33 * nfs security related library routines.
35 * Some of the routines in this file are adopted from
36 * lib/libnsl/netselect/netselect.c and are modified to be
37 * used for accessing /etc/nfssec.conf.
49 #include <nfs/nfs_sec.h>
50 #include <rpc/rpcsec_gss.h>
59 * mapping for /etc/nfssec.conf
66 static struct sc_data sc_service
[] = {
67 "default", rpc_gss_svc_default
,
68 "-", rpc_gss_svc_none
,
69 "none", rpc_gss_svc_none
,
70 "integrity", rpc_gss_svc_integrity
,
71 "privacy", rpc_gss_svc_privacy
,
75 static mutex_t matching_lock
= DEFAULTMUTEX
;
76 static char *gettoken(char *, int);
77 extern int atoi(const char *str
);
79 extern bool_t
rpc_gss_get_principal_name(rpc_gss_principal_t
*, char *,
80 char *, char *, char *);
82 extern bool_t
rpc_gss_mech_to_oid(char *, rpc_gss_OID
*);
83 extern bool_t
rpc_gss_qop_to_num(char *, char *, uint_t
*);
86 * blank() returns true if the line is a blank line, 0 otherwise
92 while (*cp
&& isspace(*cp
)) {
99 * comment() returns true if the line is a comment, 0 otherwise.
105 while (*cp
&& isspace(*cp
)) {
113 * getvalue() searches for the given string in the given array,
114 * and returns the integer value associated with the string.
117 getvalue(cp
, sc_data
)
119 struct sc_data sc_data
[];
121 int i
; /* used to index through the given struct sc_data array */
123 for (i
= 0; sc_data
[i
].string
; i
++) {
124 if (strcmp(sc_data
[i
].string
, cp
) == 0) {
128 return (sc_data
[i
].value
);
132 * shift1left() moves all characters in the string over 1 to
145 * gettoken() behaves much like strtok(), except that
146 * it knows about escaped space characters (i.e., space characters
147 * preceeded by a '\' are taken literally).
149 * XXX We should make this MT-hot by making it more like strtok_r().
156 static char *savep
; /* the place where we left off */
157 register char *p
; /* the beginning of the new token */
158 register char *retp
; /* the token to be returned */
161 /* Determine if first or subsequent call */
162 p
= (cp
== NULL
)? savep
: cp
;
164 /* Return if no tokens remain. */
177 * Save the location of the token and then skip past it
191 * Only process the escape of the space separator;
192 * since the token may contain other separators,
193 * let the other routines handle the escape of
194 * specific characters in the token.
197 if (*p
== '\\' && *(p
+ 1) != '\n' && isspace(*(p
+ 1))) {
203 savep
= 0; /* indicate this is last token */
212 * matchname() parses a line of the /etc/nfssec.conf file
213 * and match the sc_name with the given name.
214 * If there is a match, it fills the information into the given
215 * pointer of the seconfig_t structure.
217 * Returns TRUE if a match is found.
220 matchname(char *line
, char *name
, seconfig_t
*secp
)
222 char *tok1
, *tok2
; /* holds a token from the line */
223 char *secname
, *gss_mech
, *gss_qop
; /* pointer to a secmode name */
225 if ((secname
= gettoken(line
, FALSE
)) == NULL
) {
230 if (strcmp(secname
, name
) != 0) {
235 if (((tok1
= gettoken(NULL
, FALSE
)) == NULL
) ||
236 ((gss_mech
= gettoken(NULL
, FALSE
)) == NULL
) ||
237 ((gss_qop
= gettoken(NULL
, FALSE
)) == NULL
) ||
238 ((tok2
= gettoken(NULL
, FALSE
)) == NULL
) ||
239 ((secp
->sc_service
= getvalue(tok2
, sc_service
))
243 secp
->sc_nfsnum
= atoi(tok1
);
244 (void) strcpy(secp
->sc_name
, secname
);
245 (void) strcpy(secp
->sc_gss_mech
, gss_mech
);
246 secp
->sc_gss_mech_type
= NULL
;
247 if (secp
->sc_gss_mech
[0] != '-') {
248 if (!rpc_gss_mech_to_oid(gss_mech
, &secp
->sc_gss_mech_type
) ||
249 !rpc_gss_qop_to_num(gss_qop
, gss_mech
, &secp
->sc_qop
)) {
258 * matchnum() parses a line of the /etc/nfssec.conf file
259 * and match the sc_nfsnum with the given number.
260 * If it is a match, it fills the information in the given pointer
261 * of the seconfig_t structure.
263 * Returns TRUE if a match is found.
266 matchnum(char *line
, int num
, seconfig_t
*secp
)
268 char *tok1
, *tok2
; /* holds a token from the line */
269 char *secname
, *gss_mech
, *gss_qop
; /* pointer to a secmode name */
271 if ((secname
= gettoken(line
, FALSE
)) == NULL
) {
277 if ((tok1
= gettoken(NULL
, FALSE
)) == NULL
) {
282 if ((secp
->sc_nfsnum
= atoi(tok1
)) != num
) {
286 if (((gss_mech
= gettoken(NULL
, FALSE
)) == NULL
) ||
287 ((gss_qop
= gettoken(NULL
, FALSE
)) == NULL
) ||
288 ((tok2
= gettoken(NULL
, FALSE
)) == NULL
) ||
289 ((secp
->sc_service
= getvalue(tok2
, sc_service
))
294 (void) strcpy(secp
->sc_name
, secname
);
295 (void) strcpy(secp
->sc_gss_mech
, gss_mech
);
296 if (secp
->sc_gss_mech
[0] != '-') {
297 if (!rpc_gss_mech_to_oid(gss_mech
, &secp
->sc_gss_mech_type
) ||
298 !rpc_gss_qop_to_num(gss_qop
, gss_mech
, &secp
->sc_qop
)) {
307 * Fill in the RPC Protocol security flavor number
308 * into the sc_rpcnum of seconfig_t structure.
310 * Mainly to map NFS secmod number to RPCSEC_GSS if
311 * a mechanism name is specified.
314 get_rpcnum(seconfig_t
*secp
)
316 if (secp
->sc_gss_mech
[0] != '-') {
317 secp
->sc_rpcnum
= RPCSEC_GSS
;
319 secp
->sc_rpcnum
= secp
->sc_nfsnum
;
324 * Parse a given hostname (nodename[.domain@realm]) to
325 * instant name (nodename[.domain]) and realm.
327 * Assuming user has allocated the space for inst and realm.
330 parsehostname(char *hostname
, char *inst
, char *realm
)
337 h
= (char *)strdup(hostname
);
339 syslog(LOG_ERR
, "parsehostname: no memory\n");
343 r
= (char *)strchr(h
, '@');
345 (void) strcpy(inst
, h
);
346 (void) strcpy(realm
, "");
349 (void) strcpy(inst
, h
);
350 (void) strcpy(realm
, r
);
357 * Get the name corresponding to a qop num.
360 nfs_get_qop_name(seconfig_t
*entryp
)
362 char *tok
; /* holds a token from the line */
363 char *secname
, *gss_qop
= NULL
; /* pointer to a secmode name */
364 char line
[BUFSIZ
]; /* holds each line of NFSSEC_CONF */
365 FILE *fp
; /* file stream for NFSSEC_CONF */
367 (void) mutex_lock(&matching_lock
);
368 if ((fp
= fopen(NFSSEC_CONF
, "r")) == NULL
) {
369 (void) mutex_unlock(&matching_lock
);
373 while (fgets(line
, BUFSIZ
, fp
)) {
374 if (!(blank(line
) || comment(line
))) {
375 if ((secname
= gettoken(line
, FALSE
)) == NULL
) {
379 if (strcmp(secname
, entryp
->sc_name
) == 0) {
381 if ((tok
= gettoken(NULL
, FALSE
)) == NULL
) {
386 if (atoi(tok
) != entryp
->sc_nfsnum
)
389 if ((gettoken(NULL
, FALSE
) == NULL
) ||
390 ((gss_qop
= gettoken(NULL
, FALSE
))
400 (void) mutex_unlock(&matching_lock
);
405 * This routine creates an auth handle assocaited with the
406 * negotiated security flavor contained in nfs_sec. The auth
407 * handle will be used in the next LOOKUP request to fetch
411 nfs_create_ah(CLIENT
*cl
, char *hostname
, seconfig_t
*nfs_sec
)
413 char netname
[MAXNETNAMELEN
+1];
414 char svc_name
[MAXNETNAMELEN
+1];
416 static int window
= 60;
421 switch (nfs_sec
->sc_rpcnum
) {
427 if (!host2netname(netname
, hostname
, NULL
))
430 return (authdes_seccreate(netname
, window
, hostname
,
437 if (nfs_sec
->sc_gss_mech_type
== NULL
) {
439 "nfs_create_ah: need mechanism information\n");
444 * RPCSEC_GSS service names are of the form svc@host.dom
446 (void) sprintf(svc_name
, "nfs@%s", hostname
);
448 gss_qop
= nfs_get_qop_name(nfs_sec
);
452 return (rpc_gss_seccreate(cl
, svc_name
,
453 nfs_sec
->sc_gss_mech
, nfs_sec
->sc_service
, gss_qop
,
457 syslog(LOG_ERR
, "nfs_create_ah: unknown flavor\n");
461 syslog(LOG_ERR
, "nfs_create_ah: failed to make auth handle\n");
467 * This routine negotiates sec flavors with server and returns:
468 * SNEGO_SUCCESS: successful; sec flavors are
470 * SNEGO_DEF_VALID: default sec flavor valid; no need
471 * to negotiate flavors,
472 * SNEGO_ARRAY_TOO_SMALL: array too small,
473 * SNEGO_FAILURE: failure
476 * The following depicts how sec flavors are placed in an
477 * overloaded V2 fhandle:
479 * Note that the first four octets contain the length octet,
480 * the status octet, and two padded octets to make them XDR
481 * four-octet aligned.
484 * +---+---+---+---+---+---+---+---+ +---+---+---+---+ +---+
485 * | l | s | | | sec_1 |...| sec_n |...| |
486 * +---+---+---+---+---+---+---+---+ +---+---+---+---+ +---+
490 * the status octet s indicates whether there are more security
491 * flavors(1 means yes, 0 means no) that require the client to
492 * perform another 0x81 LOOKUP to get them,
494 * the length octet l is the length describing the number of
495 * valid octets that follow. (l = 4 * n, where n is the number
497 * The following depicts how sec flavors are placed in an
498 * overloaded V3 fhandle:
505 * +--+--+--+--+--+--+--+--+--+--+--+--+ +--+--+--+--+
506 * |s | | | | sec_1 | sec_2 | ... | sec_n |
507 * +--+--+--+--+--+--+--+--+--+--+--+--+ +--+--+--+--+
509 * len = 4 * (n+1), where n is the number of security flavors
510 * sent in the current overloaded filehandle.
512 * the status octet s indicates whether there are more security
513 * mechanisms(1 means yes, 0 means no) that require the client
514 * to perform another 0x81 LOOKUP to get them.
516 * Three octets are padded after the status octet.
519 nfs_sec_nego(rpcprog_t vers
, CLIENT
*clnt
, char *fspath
, struct snego_t
*snego
)
521 enum clnt_stat rpc_stat
;
522 static int MAX_V2_CNT
= (WNL_FHSIZE
/sizeof (int)) - 1;
523 static int MAX_V3_CNT
= (WNL3_FHSIZE
/sizeof (int)) - 1;
524 static struct timeval TIMEOUT
= { 25, 0 };
527 if (clnt
== NULL
|| fspath
== NULL
|| snego
== NULL
)
528 return (SNEGO_FAILURE
);
530 if (vers
== WNL_V2
) {
532 wnl_diropres clnt_res
;
534 memset((char *)&arg
.dir
, 0, sizeof (wnl_fh
));
536 memset((char *)&clnt_res
, 0, sizeof (clnt_res
));
537 rpc_stat
= clnt_call(clnt
, WNLPROC_LOOKUP
,
538 (xdrproc_t
)xdr_wnl_diropargs
, (caddr_t
)&arg
,
539 (xdrproc_t
)xdr_wnl_diropres
, (caddr_t
)&clnt_res
,
541 if (rpc_stat
== RPC_SUCCESS
&& clnt_res
.status
== WNL_OK
)
542 return (SNEGO_DEF_VALID
);
543 if (rpc_stat
!= RPC_AUTHERROR
)
544 return (SNEGO_FAILURE
);
552 CLNT_GETERR(clnt
, &e
);
553 if (e
.re_why
!= AUTH_TOOWEAK
)
554 return (SNEGO_FAILURE
);
556 if ((p
= malloc(strlen(fspath
)+3)) == NULL
) {
557 syslog(LOG_ERR
, "no memory\n");
558 return (SNEGO_FAILURE
);
563 p
[0] = (char)WNL_SEC_NEGO
;
564 strcpy(&p
[2], fspath
);
566 p
[1] = (char)(1+snego
->cnt
); /* sec index */
568 memset((char *)&res
, 0, sizeof (wnl_diropres
));
569 if (wnlproc_lookup_2(&arg
, &res
, clnt
) !=
570 RPC_SUCCESS
|| res
.status
!= WNL_OK
) {
572 return (SNEGO_FAILURE
);
576 * retrieve flavors from filehandle:
580 * 5th and after: sec flavors.
583 char *c
= (char *)&res
.wnl_diropres_u
.
586 int cnt
= ((int)*c
)/sizeof (uint_t
);
587 /* LINTED pointer alignment */
588 int *ip
= (int *)(c
+sizeof (int));
591 if (tot
>= MAX_FLAVORS
) {
593 return (SNEGO_ARRAY_TOO_SMALL
);
595 status
= (int)*(c
+1);
596 if (cnt
> MAX_V2_CNT
|| cnt
< 0) {
598 return (SNEGO_FAILURE
);
600 for (ii
= 0; ii
< cnt
; ii
++)
601 snego
->array
[snego
->cnt
+ii
] =
607 return (SNEGO_SUCCESS
);
609 } else if (vers
== WNL_V3
) {
611 WNL_LOOKUP3res clnt_res
;
613 memset((char *)&arg
.what
.dir
, 0, sizeof (wnl_fh3
));
614 arg
.what
.name
= fspath
;
615 arg
.what
.dir
.data
.data_len
= 0;
616 arg
.what
.dir
.data
.data_val
= 0;
617 memset((char *)&clnt_res
, 0, sizeof (clnt_res
));
618 rpc_stat
= clnt_call(clnt
, WNLPROC3_LOOKUP
,
619 (xdrproc_t
)xdr_WNL_LOOKUP3args
, (caddr_t
)&arg
,
620 (xdrproc_t
)xdr_WNL_LOOKUP3res
, (caddr_t
)&clnt_res
,
622 if (rpc_stat
== RPC_SUCCESS
&& clnt_res
.status
== WNL3_OK
)
623 return (SNEGO_DEF_VALID
);
624 if (rpc_stat
!= RPC_AUTHERROR
)
625 return (SNEGO_FAILURE
);
633 CLNT_GETERR(clnt
, &e
);
634 if (e
.re_why
!= AUTH_TOOWEAK
)
635 return (SNEGO_FAILURE
);
637 if ((p
= malloc(strlen(fspath
)+3)) == NULL
) {
638 syslog(LOG_ERR
, "no memory\n");
639 return (SNEGO_FAILURE
);
644 p
[0] = (char)WNL_SEC_NEGO
;
645 strcpy(&p
[2], fspath
);
647 p
[1] = (char)(1+snego
->cnt
); /* sec index */
649 memset((char *)&res
, 0,
650 sizeof (WNL_LOOKUP3res
));
651 if (wnlproc3_lookup_3(&arg
, &res
, clnt
) !=
652 RPC_SUCCESS
|| res
.status
!= WNL3_OK
) {
654 return (SNEGO_FAILURE
);
658 * retrieve flavors from filehandle:
662 * 5th and after: sec flavors.
665 char *c
= res
.WNL_LOOKUP3res_u
.
666 res_ok
.object
.data
.data_val
;
668 int len
= res
.WNL_LOOKUP3res_u
.res_ok
.
669 object
.data
.data_len
;
671 /* LINTED pointer alignment */
672 int *ip
= (int *)(c
+sizeof (int));
674 cnt
= len
/sizeof (uint_t
) - 1;
676 if (tot
>= MAX_FLAVORS
) {
678 return (SNEGO_ARRAY_TOO_SMALL
);
681 if (cnt
> MAX_V3_CNT
|| cnt
< 0) {
683 return (SNEGO_FAILURE
);
685 for (ii
= 0; ii
< cnt
; ii
++)
686 snego
->array
[snego
->cnt
+ii
] =
692 return (SNEGO_SUCCESS
);
695 return (SNEGO_FAILURE
);
700 * Get seconfig from /etc/nfssec.conf by name or by number or
705 get_seconfig(int whichway
, char *name
, int num
,
706 rpc_gss_service_t service
, seconfig_t
*entryp
)
708 char line
[BUFSIZ
]; /* holds each line of NFSSEC_CONF */
709 FILE *fp
; /* file stream for NFSSEC_CONF */
711 if ((whichway
== GETBYNAME
) && (name
== NULL
))
712 return (SC_NOTFOUND
);
714 (void) mutex_lock(&matching_lock
);
715 if ((fp
= fopen(NFSSEC_CONF
, "r")) == NULL
) {
716 (void) mutex_unlock(&matching_lock
);
717 return (SC_OPENFAIL
);
720 while (fgets(line
, BUFSIZ
, fp
)) {
721 if (!(blank(line
) || comment(line
))) {
724 if (matchname(line
, name
, entryp
)) {
730 if (matchnum(line
, num
, entryp
)) {
741 (void) mutex_unlock(&matching_lock
);
742 return (SC_NOTFOUND
);
746 (void) mutex_unlock(&matching_lock
);
747 (void) get_rpcnum(entryp
);
753 * NFS project private API.
754 * Get a seconfig entry from /etc/nfssec.conf by nfs specific sec name,
755 * e.g. des, krb5p, etc.
758 nfs_getseconfig_byname(char *secmode_name
, seconfig_t
*entryp
)
763 return (get_seconfig(GETBYNAME
, secmode_name
, 0, rpc_gss_svc_none
,
768 * NFS project private API.
770 * Get a seconfig entry from /etc/nfssec.conf by nfs specific sec number,
771 * e.g. AUTH_DES, AUTH_KRB5_P, etc.
774 nfs_getseconfig_bynumber(int nfs_secnum
, seconfig_t
*entryp
)
779 return (get_seconfig(GETBYNUM
, NULL
, nfs_secnum
, rpc_gss_svc_none
,
784 * NFS project private API.
786 * Get a seconfig_t entry used as the default for NFS operations.
787 * The default flavor entry is defined in /etc/nfssec.conf.
789 * Assume user has allocate spaces for secp.
792 nfs_getseconfig_default(seconfig_t
*secp
)
797 return (nfs_getseconfig_byname("default", secp
));
802 * NFS project private API.
804 * Free an sec_data structure.
805 * Free the parts that nfs_clnt_secdata allocates.
808 nfs_free_secdata(sec_data_t
*secdata
)
810 dh_k4_clntdata_t
*dkdata
;
811 gss_clntdata_t
*gdata
;
816 switch (secdata
->rpcflavor
) {
822 /* LINTED pointer alignment */
823 dkdata
= (dh_k4_clntdata_t
*)secdata
->data
;
826 free(dkdata
->netname
);
827 if (dkdata
->syncaddr
.buf
)
828 free(dkdata
->syncaddr
.buf
);
834 /* LINTED pointer alignment */
835 gdata
= (gss_clntdata_t
*)secdata
->data
;
837 if (gdata
->mechanism
.elements
)
838 free(gdata
->mechanism
.elements
);
851 * Make an client side sec_data structure and fill in appropriate value
852 * based on its rpc security flavor.
854 * It is caller's responsibility to allocate space for seconfig_t,
855 * and this routine will allocate space for the sec_data structure
856 * and related data field.
858 * Return the sec_data_t on success.
859 * If fail, return NULL pointer.
862 nfs_clnt_secdata(seconfig_t
*secp
, char *hostname
, struct knetconfig
*knconf
,
863 struct netbuf
*syncaddr
, int flags
)
865 char netname
[MAXNETNAMELEN
+1];
867 dh_k4_clntdata_t
*dkdata
;
868 gss_clntdata_t
*gdata
;
870 secdata
= malloc(sizeof (sec_data_t
));
872 syslog(LOG_ERR
, "nfs_clnt_secdata: no memory\n");
875 (void) memset(secdata
, 0, sizeof (sec_data_t
));
877 secdata
->secmod
= secp
->sc_nfsnum
;
878 secdata
->rpcflavor
= secp
->sc_rpcnum
;
879 secdata
->uid
= secp
->sc_uid
;
880 secdata
->flags
= flags
;
883 * Now, fill in the information for client side secdata :
885 * For AUTH_UNIX, AUTH_DES
886 * hostname can be in the form of
890 * For RPCSEC_GSS security flavor
891 * hostname can be in the form of
894 * nodename@realm (realm can be the same as the domain) or
895 * nodename.domain@realm
897 switch (secp
->sc_rpcnum
) {
900 secdata
->data
= NULL
;
905 * If hostname is in the format of host.nisdomain
906 * the netname will be constructed with
907 * this nisdomain name rather than the default
908 * domain of the machine.
910 if (!host2netname(netname
, hostname
, NULL
)) {
911 syslog(LOG_ERR
, "host2netname: %s: unknown\n",
915 dkdata
= malloc(sizeof (dh_k4_clntdata_t
));
918 "nfs_clnt_secdata: no memory\n");
921 (void) memset((char *)dkdata
, 0,
922 sizeof (dh_k4_clntdata_t
));
923 if ((dkdata
->netname
= strdup(netname
)) == NULL
) {
925 "nfs_clnt_secdata: no memory\n");
928 dkdata
->netnamelen
= strlen(netname
);
929 dkdata
->knconf
= knconf
;
930 dkdata
->syncaddr
= *syncaddr
;
931 dkdata
->syncaddr
.buf
= malloc(syncaddr
->len
);
932 if (dkdata
->syncaddr
.buf
== NULL
) {
934 "nfs_clnt_secdata: no memory\n");
937 (void) memcpy(dkdata
->syncaddr
.buf
, syncaddr
->buf
,
939 secdata
->data
= (caddr_t
)dkdata
;
943 if (secp
->sc_gss_mech_type
== NULL
) {
945 "nfs_clnt_secdata: need mechanism information\n");
949 gdata
= malloc(sizeof (gss_clntdata_t
));
952 "nfs_clnt_secdata: no memory\n");
956 (void) strcpy(gdata
->uname
, "nfs");
957 if (!parsehostname(hostname
, gdata
->inst
,
960 "nfs_clnt_secdata: bad host name\n");
964 gdata
->mechanism
.length
=
965 secp
->sc_gss_mech_type
->length
;
966 if (!(gdata
->mechanism
.elements
=
967 malloc(secp
->sc_gss_mech_type
->length
))) {
969 "nfs_clnt_secdata: no memory\n");
972 (void) memcpy(gdata
->mechanism
.elements
,
973 secp
->sc_gss_mech_type
->elements
,
974 secp
->sc_gss_mech_type
->length
);
976 gdata
->qop
= secp
->sc_qop
;
977 gdata
->service
= secp
->sc_service
;
978 secdata
->data
= (caddr_t
)gdata
;
982 syslog(LOG_ERR
, "nfs_clnt_secdata: unknown flavor\n");
994 * nfs_get_root_principal() maps a host name to its principal name
995 * based on the given security information.
997 * input : seconfig - security configuration information
998 * host - the host name which could be in the following forms:
1001 * node@secdomain (e.g. kerberos realm is a secdomain)
1002 * node.namedomain@secdomain
1003 * output : rootname_p - address of the principal name for the host
1005 * Currently, this routine is only used by share program.
1009 nfs_get_root_principal(seconfig_t
*seconfig
, char *host
, caddr_t
*rootname_p
)
1011 char netname
[MAXNETNAMELEN
+1], node
[MAX_NAME_LEN
];
1012 char secdomain
[MAX_NAME_LEN
];
1013 rpc_gss_principal_t gssname
;
1015 switch (seconfig
->sc_rpcnum
) {
1017 if (!host2netname(netname
, host
, NULL
)) {
1019 "nfs_get_root_principal: unknown host: %s\n", host
);
1022 *rootname_p
= strdup(netname
);
1025 "nfs_get_root_principal: no memory\n");
1031 if (!parsehostname(host
, node
, secdomain
)) {
1033 "nfs_get_root_principal: bad host name\n");
1036 if (!rpc_gss_get_principal_name(&gssname
,
1037 seconfig
->sc_gss_mech
, "root", node
, secdomain
)) {
1039 "nfs_get_root_principal: can not get principal name : %s\n", host
);
1043 *rootname_p
= (caddr_t
)gssname
;
1054 * SYSLOG SC_* errors.
1057 nfs_syslog_scerr(int scerror
, char msg
[])
1061 sprintf(msg
, "%s : no memory", NFSSEC_CONF
);
1064 sprintf(msg
, "can not open %s", NFSSEC_CONF
);
1067 sprintf(msg
, "has no entry in %s", NFSSEC_CONF
);
1069 case SC_BADENTRIES
:
1070 sprintf(msg
, "bad entry in %s", NFSSEC_CONF
);