Attila Bogar reported a bug in mountd when multiple export
entries with different security flavors are in the exports(5) file. For that case, mountd replies with the security flavors of the last entry and not the correct one for the client host. This patch fixes that by storing separate copies of the flavors for each host/net case, plus a default one for the case where no hosts/nets are specified on an entry in the exports(5) file. Unlike the patch in the PR, it replies with the security flavors for the entry instead of merging the security flavors for all the entries and replying with that. Tested by: attila.bogar at linguamatics.com PR: kern/164933 MFC after: 2 weeks
This commit is contained in:
parent
6aa3468375
commit
c3f86a256c
@ -117,6 +117,8 @@ struct exportlist {
|
|||||||
char *ex_indexfile;
|
char *ex_indexfile;
|
||||||
int ex_numsecflavors;
|
int ex_numsecflavors;
|
||||||
int ex_secflavors[MAXSECFLAVORS];
|
int ex_secflavors[MAXSECFLAVORS];
|
||||||
|
int ex_defnumsecflavors;
|
||||||
|
int ex_defsecflavors[MAXSECFLAVORS];
|
||||||
};
|
};
|
||||||
/* ex_flag bits */
|
/* ex_flag bits */
|
||||||
#define EX_LINKED 0x1
|
#define EX_LINKED 0x1
|
||||||
@ -136,6 +138,8 @@ struct grouplist {
|
|||||||
int gr_type;
|
int gr_type;
|
||||||
union grouptypes gr_ptr;
|
union grouptypes gr_ptr;
|
||||||
struct grouplist *gr_next;
|
struct grouplist *gr_next;
|
||||||
|
int gr_numsecflavors;
|
||||||
|
int gr_secflavors[MAXSECFLAVORS];
|
||||||
};
|
};
|
||||||
/* Group types */
|
/* Group types */
|
||||||
#define GT_NULL 0x0
|
#define GT_NULL 0x0
|
||||||
@ -163,12 +167,13 @@ struct fhreturn {
|
|||||||
/* Global defs */
|
/* Global defs */
|
||||||
char *add_expdir(struct dirlist **, char *, int);
|
char *add_expdir(struct dirlist **, char *, int);
|
||||||
void add_dlist(struct dirlist **, struct dirlist *,
|
void add_dlist(struct dirlist **, struct dirlist *,
|
||||||
struct grouplist *, int);
|
struct grouplist *, int, struct exportlist *);
|
||||||
void add_mlist(char *, char *);
|
void add_mlist(char *, char *);
|
||||||
int check_dirpath(char *);
|
int check_dirpath(char *);
|
||||||
int check_options(struct dirlist *);
|
int check_options(struct dirlist *);
|
||||||
int checkmask(struct sockaddr *sa);
|
int checkmask(struct sockaddr *sa);
|
||||||
int chk_host(struct dirlist *, struct sockaddr *, int *, int *);
|
int chk_host(struct dirlist *, struct sockaddr *, int *, int *, int *,
|
||||||
|
int **);
|
||||||
static int create_service(struct netconfig *nconf);
|
static int create_service(struct netconfig *nconf);
|
||||||
static void complete_service(struct netconfig *nconf, char *port_str);
|
static void complete_service(struct netconfig *nconf, char *port_str);
|
||||||
static void clearout_service(void);
|
static void clearout_service(void);
|
||||||
@ -938,6 +943,7 @@ mntsrv(struct svc_req *rqstp, SVCXPRT *transp)
|
|||||||
char rpcpath[MNTPATHLEN + 1], dirpath[MAXPATHLEN];
|
char rpcpath[MNTPATHLEN + 1], dirpath[MAXPATHLEN];
|
||||||
int bad = 0, defset, hostset;
|
int bad = 0, defset, hostset;
|
||||||
sigset_t sighup_mask;
|
sigset_t sighup_mask;
|
||||||
|
int numsecflavors, *secflavorsp;
|
||||||
|
|
||||||
sigemptyset(&sighup_mask);
|
sigemptyset(&sighup_mask);
|
||||||
sigaddset(&sighup_mask, SIGHUP);
|
sigaddset(&sighup_mask, SIGHUP);
|
||||||
@ -1000,9 +1006,11 @@ mntsrv(struct svc_req *rqstp, SVCXPRT *transp)
|
|||||||
sigprocmask(SIG_BLOCK, &sighup_mask, NULL);
|
sigprocmask(SIG_BLOCK, &sighup_mask, NULL);
|
||||||
ep = ex_search(&fsb.f_fsid);
|
ep = ex_search(&fsb.f_fsid);
|
||||||
hostset = defset = 0;
|
hostset = defset = 0;
|
||||||
if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset) ||
|
if (ep && (chk_host(ep->ex_defdir, saddr, &defset, &hostset,
|
||||||
|
&numsecflavors, &secflavorsp) ||
|
||||||
((dp = dirp_search(ep->ex_dirl, dirpath)) &&
|
((dp = dirp_search(ep->ex_dirl, dirpath)) &&
|
||||||
chk_host(dp, saddr, &defset, &hostset)) ||
|
chk_host(dp, saddr, &defset, &hostset, &numsecflavors,
|
||||||
|
&secflavorsp)) ||
|
||||||
(defset && scan_tree(ep->ex_defdir, saddr) == 0 &&
|
(defset && scan_tree(ep->ex_defdir, saddr) == 0 &&
|
||||||
scan_tree(ep->ex_dirl, saddr) == 0))) {
|
scan_tree(ep->ex_dirl, saddr) == 0))) {
|
||||||
if (bad) {
|
if (bad) {
|
||||||
@ -1012,10 +1020,15 @@ mntsrv(struct svc_req *rqstp, SVCXPRT *transp)
|
|||||||
sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
|
sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (hostset & DP_HOSTSET)
|
if (hostset & DP_HOSTSET) {
|
||||||
fhr.fhr_flag = hostset;
|
fhr.fhr_flag = hostset;
|
||||||
else
|
fhr.fhr_numsecflavors = numsecflavors;
|
||||||
|
fhr.fhr_secflavors = secflavorsp;
|
||||||
|
} else {
|
||||||
fhr.fhr_flag = defset;
|
fhr.fhr_flag = defset;
|
||||||
|
fhr.fhr_numsecflavors = ep->ex_defnumsecflavors;
|
||||||
|
fhr.fhr_secflavors = ep->ex_defsecflavors;
|
||||||
|
}
|
||||||
fhr.fhr_vers = rqstp->rq_vers;
|
fhr.fhr_vers = rqstp->rq_vers;
|
||||||
/* Get the file handle */
|
/* Get the file handle */
|
||||||
memset(&fhr.fhr_fh, 0, sizeof(nfsfh_t));
|
memset(&fhr.fhr_fh, 0, sizeof(nfsfh_t));
|
||||||
@ -1028,8 +1041,6 @@ mntsrv(struct svc_req *rqstp, SVCXPRT *transp)
|
|||||||
sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
|
sigprocmask(SIG_UNBLOCK, &sighup_mask, NULL);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fhr.fhr_numsecflavors = ep->ex_numsecflavors;
|
|
||||||
fhr.fhr_secflavors = ep->ex_secflavors;
|
|
||||||
if (!svc_sendreply(transp, (xdrproc_t)xdr_fhs,
|
if (!svc_sendreply(transp, (xdrproc_t)xdr_fhs,
|
||||||
(caddr_t)&fhr))
|
(caddr_t)&fhr))
|
||||||
syslog(LOG_ERR, "can't send reply");
|
syslog(LOG_ERR, "can't send reply");
|
||||||
@ -1881,11 +1892,21 @@ hang_dirp(struct dirlist *dp, struct grouplist *grp, struct exportlist *ep,
|
|||||||
ep->ex_defdir = dp;
|
ep->ex_defdir = dp;
|
||||||
if (grp == (struct grouplist *)NULL) {
|
if (grp == (struct grouplist *)NULL) {
|
||||||
ep->ex_defdir->dp_flag |= DP_DEFSET;
|
ep->ex_defdir->dp_flag |= DP_DEFSET;
|
||||||
|
/* Save the default security flavors list. */
|
||||||
|
ep->ex_defnumsecflavors = ep->ex_numsecflavors;
|
||||||
|
if (ep->ex_numsecflavors > 0)
|
||||||
|
memcpy(ep->ex_defsecflavors, ep->ex_secflavors,
|
||||||
|
sizeof(ep->ex_secflavors));
|
||||||
} else while (grp) {
|
} else while (grp) {
|
||||||
hp = get_ht();
|
hp = get_ht();
|
||||||
hp->ht_grp = grp;
|
hp->ht_grp = grp;
|
||||||
hp->ht_next = ep->ex_defdir->dp_hosts;
|
hp->ht_next = ep->ex_defdir->dp_hosts;
|
||||||
ep->ex_defdir->dp_hosts = hp;
|
ep->ex_defdir->dp_hosts = hp;
|
||||||
|
/* Save the security flavors list for this host set. */
|
||||||
|
grp->gr_numsecflavors = ep->ex_numsecflavors;
|
||||||
|
if (ep->ex_numsecflavors > 0)
|
||||||
|
memcpy(grp->gr_secflavors, ep->ex_secflavors,
|
||||||
|
sizeof(ep->ex_secflavors));
|
||||||
grp = grp->gr_next;
|
grp = grp->gr_next;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1895,7 +1916,7 @@ hang_dirp(struct dirlist *dp, struct grouplist *grp, struct exportlist *ep,
|
|||||||
*/
|
*/
|
||||||
while (dp) {
|
while (dp) {
|
||||||
dp2 = dp->dp_left;
|
dp2 = dp->dp_left;
|
||||||
add_dlist(&ep->ex_dirl, dp, grp, flags);
|
add_dlist(&ep->ex_dirl, dp, grp, flags, ep);
|
||||||
dp = dp2;
|
dp = dp2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1907,7 +1928,7 @@ hang_dirp(struct dirlist *dp, struct grouplist *grp, struct exportlist *ep,
|
|||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
add_dlist(struct dirlist **dpp, struct dirlist *newdp, struct grouplist *grp,
|
add_dlist(struct dirlist **dpp, struct dirlist *newdp, struct grouplist *grp,
|
||||||
int flags)
|
int flags, struct exportlist *ep)
|
||||||
{
|
{
|
||||||
struct dirlist *dp;
|
struct dirlist *dp;
|
||||||
struct hostlist *hp;
|
struct hostlist *hp;
|
||||||
@ -1917,10 +1938,10 @@ add_dlist(struct dirlist **dpp, struct dirlist *newdp, struct grouplist *grp,
|
|||||||
if (dp) {
|
if (dp) {
|
||||||
cmp = strcmp(dp->dp_dirp, newdp->dp_dirp);
|
cmp = strcmp(dp->dp_dirp, newdp->dp_dirp);
|
||||||
if (cmp > 0) {
|
if (cmp > 0) {
|
||||||
add_dlist(&dp->dp_left, newdp, grp, flags);
|
add_dlist(&dp->dp_left, newdp, grp, flags, ep);
|
||||||
return;
|
return;
|
||||||
} else if (cmp < 0) {
|
} else if (cmp < 0) {
|
||||||
add_dlist(&dp->dp_right, newdp, grp, flags);
|
add_dlist(&dp->dp_right, newdp, grp, flags, ep);
|
||||||
return;
|
return;
|
||||||
} else
|
} else
|
||||||
free((caddr_t)newdp);
|
free((caddr_t)newdp);
|
||||||
@ -1939,10 +1960,20 @@ add_dlist(struct dirlist **dpp, struct dirlist *newdp, struct grouplist *grp,
|
|||||||
hp->ht_grp = grp;
|
hp->ht_grp = grp;
|
||||||
hp->ht_next = dp->dp_hosts;
|
hp->ht_next = dp->dp_hosts;
|
||||||
dp->dp_hosts = hp;
|
dp->dp_hosts = hp;
|
||||||
|
/* Save the security flavors list for this host set. */
|
||||||
|
grp->gr_numsecflavors = ep->ex_numsecflavors;
|
||||||
|
if (ep->ex_numsecflavors > 0)
|
||||||
|
memcpy(grp->gr_secflavors, ep->ex_secflavors,
|
||||||
|
sizeof(ep->ex_secflavors));
|
||||||
grp = grp->gr_next;
|
grp = grp->gr_next;
|
||||||
} while (grp);
|
} while (grp);
|
||||||
} else {
|
} else {
|
||||||
dp->dp_flag |= DP_DEFSET;
|
dp->dp_flag |= DP_DEFSET;
|
||||||
|
/* Save the default security flavors list. */
|
||||||
|
ep->ex_defnumsecflavors = ep->ex_numsecflavors;
|
||||||
|
if (ep->ex_numsecflavors > 0)
|
||||||
|
memcpy(ep->ex_defsecflavors, ep->ex_secflavors,
|
||||||
|
sizeof(ep->ex_secflavors));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1971,7 +2002,7 @@ dirp_search(struct dirlist *dp, char *dirp)
|
|||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
chk_host(struct dirlist *dp, struct sockaddr *saddr, int *defsetp,
|
chk_host(struct dirlist *dp, struct sockaddr *saddr, int *defsetp,
|
||||||
int *hostsetp)
|
int *hostsetp, int *numsecflavors, int **secflavorsp)
|
||||||
{
|
{
|
||||||
struct hostlist *hp;
|
struct hostlist *hp;
|
||||||
struct grouplist *grp;
|
struct grouplist *grp;
|
||||||
@ -1990,6 +2021,12 @@ chk_host(struct dirlist *dp, struct sockaddr *saddr, int *defsetp,
|
|||||||
if (!sacmp(ai->ai_addr, saddr, NULL)) {
|
if (!sacmp(ai->ai_addr, saddr, NULL)) {
|
||||||
*hostsetp =
|
*hostsetp =
|
||||||
(hp->ht_flag | DP_HOSTSET);
|
(hp->ht_flag | DP_HOSTSET);
|
||||||
|
if (numsecflavors != NULL) {
|
||||||
|
*numsecflavors =
|
||||||
|
grp->gr_numsecflavors;
|
||||||
|
*secflavorsp =
|
||||||
|
grp->gr_secflavors;
|
||||||
|
}
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2000,6 +2037,12 @@ chk_host(struct dirlist *dp, struct sockaddr *saddr, int *defsetp,
|
|||||||
(struct sockaddr *)
|
(struct sockaddr *)
|
||||||
&grp->gr_ptr.gt_net.nt_mask)) {
|
&grp->gr_ptr.gt_net.nt_mask)) {
|
||||||
*hostsetp = (hp->ht_flag | DP_HOSTSET);
|
*hostsetp = (hp->ht_flag | DP_HOSTSET);
|
||||||
|
if (numsecflavors != NULL) {
|
||||||
|
*numsecflavors =
|
||||||
|
grp->gr_numsecflavors;
|
||||||
|
*secflavorsp =
|
||||||
|
grp->gr_secflavors;
|
||||||
|
}
|
||||||
return (1);
|
return (1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -2021,7 +2064,7 @@ scan_tree(struct dirlist *dp, struct sockaddr *saddr)
|
|||||||
if (dp) {
|
if (dp) {
|
||||||
if (scan_tree(dp->dp_left, saddr))
|
if (scan_tree(dp->dp_left, saddr))
|
||||||
return (1);
|
return (1);
|
||||||
if (chk_host(dp, saddr, &defset, &hostset))
|
if (chk_host(dp, saddr, &defset, &hostset, NULL, NULL))
|
||||||
return (1);
|
return (1);
|
||||||
if (scan_tree(dp->dp_right, saddr))
|
if (scan_tree(dp->dp_right, saddr))
|
||||||
return (1);
|
return (1);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user