4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
24 * Allows for gathering of registrations from a earlier dumped file.
26 * Copyright 1990,2002-2003 Sun Microsystems, Inc. All rights reserved.
27 * Use is subject to license terms.
30 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
36 #include <rpc/rpcb_prot.h>
37 #include <sys/types.h>
40 #include <netinet/in.h>
41 #include <rpc/pmap_prot.h>
46 #include <rpcsvc/daemon_utils.h>
49 /* These files keep the pmap_list and rpcb_list in XDR format */
50 static const char rpcbfile
[] = DAEMON_DIR
"/rpcbind.file";
52 static const char pmapfile
[] = DAEMON_DIR
"/portmap.file";
56 open_tmp_file(const char *filename
)
62 * Remove any existing files, and create a new one.
63 * Ensure that rpcbind is not forced to overwrite
64 * a file pointed to by a symbolic link created
66 * Use open O_CREAT|O_EXCL so file is not created
67 * between unlink() and open() operation.
69 if (unlink(filename
) == -1) {
73 fd
= open(filename
, O_CREAT
|O_EXCL
|O_WRONLY
, 0600);
86 write_struct(const char *filename
, xdrproc_t structproc
, void *list
)
91 fp
= open_tmp_file(filename
);
95 for (i
= 0; i
< 10; i
++)
97 fp
= open_tmp_file(filename
);
100 "cannot open file = %s for writing", filename
);
101 syslog(LOG_ERR
, "cannot save any registration");
105 xdrstdio_create(&xdrs
, fp
, XDR_ENCODE
);
107 if (structproc(&xdrs
, list
) == FALSE
) {
109 syslog(LOG_ERR
, "rpcbind: xdr_%s: failed", filename
);
119 read_struct(const char *filename
, xdrproc_t structproc
, void *list
)
124 struct stat sbuf_fstat
, sbuf_lstat
;
126 fd
= open(filename
, O_RDONLY
, 0600);
129 "rpcbind: cannot open file = %s for reading\n", filename
);
132 fp
= fdopen(fd
, "r");
136 "rpcbind: cannot open file = %s for reading\n", filename
);
139 if (fstat(fd
, &sbuf_fstat
) != 0) {
141 "rpcbind: cannot stat file = %s for reading\n", filename
);
144 if (sbuf_fstat
.st_uid
!= DAEMON_UID
||
145 (!S_ISREG(sbuf_fstat
.st_mode
)) ||
146 (sbuf_fstat
.st_mode
& S_IRWXG
) ||
147 (sbuf_fstat
.st_mode
& S_IRWXO
) ||
148 (sbuf_fstat
.st_nlink
!= 1)) {
149 fprintf(stderr
, "rpcbind: invalid permissions on file = %s for "
150 "reading\n", filename
);
154 * Make sure that the pathname for fstat and lstat is the same and
155 * that it's not a link. An attacker can create symbolic or
156 * hard links and use them to gain unauthorised access to the
157 * system when rpcbind aborts or terminates on SIGINT or SIGTERM.
159 if (lstat(filename
, &sbuf_lstat
) != 0) {
161 "rpcbind: cannot lstat file = %s for reading\n", filename
);
164 if (sbuf_lstat
.st_uid
!= DAEMON_UID
||
165 (!S_ISREG(sbuf_lstat
.st_mode
)) ||
166 (sbuf_lstat
.st_mode
& S_IRWXG
) ||
167 (sbuf_lstat
.st_mode
& S_IRWXO
) ||
168 (sbuf_lstat
.st_nlink
!= 1) ||
169 (sbuf_fstat
.st_dev
!= sbuf_lstat
.st_dev
) ||
170 (sbuf_fstat
.st_ino
!= sbuf_lstat
.st_ino
)) {
171 fprintf(stderr
, "rpcbind: invalid lstat permissions on file = "
172 "%s for reading\n", filename
);
175 xdrstdio_create(&xdrs
, fp
, XDR_DECODE
);
177 if (structproc(&xdrs
, list
) == FALSE
) {
179 fprintf(stderr
, "rpcbind: xdr_%s: failed\n", filename
);
187 fprintf(stderr
, "rpcbind: will start from scratch\n");
194 write_warmstart(void)
196 assert(RW_WRITE_HELD(&list_rbl_lock
));
197 (void) write_struct(rpcbfile
, xdr_rpcblist_ptr
, &list_rbl
);
199 assert(RW_WRITE_HELD(&list_pml_lock
));
200 (void) write_struct(pmapfile
, xdr_pmaplist_ptr
, &list_pml
);
208 rpcblist_ptr tmp_rpcbl
= NULL
;
210 pmaplist_ptr tmp_pmapl
= NULL
;
213 if (read_struct(rpcbfile
, xdr_rpcblist_ptr
, &tmp_rpcbl
) == FALSE
)
217 if (read_struct(pmapfile
, xdr_pmaplist_ptr
, &tmp_pmapl
) == FALSE
) {
218 xdr_free((xdrproc_t
)xdr_rpcblist_ptr
, (char *)&tmp_rpcbl
);
223 xdr_free((xdrproc_t
)xdr_rpcblist_ptr
, (char *)&list_rbl
);
224 list_rbl
= tmp_rpcbl
;
226 xdr_free((xdrproc_t
)xdr_pmaplist_ptr
, (char *)&list_pml
);
227 list_pml
= (pmaplist
*)tmp_pmapl
;