warmstart.c (7c478bd95313f5f23a4c958a745db2134aa03244) warmstart.c (8f6d9dae92449b59bdafcb7777bc32f1b2726e48)
1/*
2 * CDDL HEADER START
3 *
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
7 * with the License.
8 *

--- 12 unchanged lines hidden (view full) ---

21 */
22/*
23 * warmstart.c
24 * Allows for gathering of registrations from a earlier dumped file.
25 *
26 * Copyright 1990,2002-2003 Sun Microsystems, Inc. All rights reserved.
27 * Use is subject to license terms.
28 */
1/*
2 * CDDL HEADER START
3 *
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
7 * with the License.
8 *

--- 12 unchanged lines hidden (view full) ---

21 */
22/*
23 * warmstart.c
24 * Allows for gathering of registrations from a earlier dumped file.
25 *
26 * Copyright 1990,2002-2003 Sun Microsystems, Inc. All rights reserved.
27 * Use is subject to license terms.
28 */
29/*
30 * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
31 */
29
32
30#pragma ident "%Z%%M% %I% %E% SMI"
31
32#include <stdio.h>
33#include <errno.h>
34#include <rpc/rpc.h>
35#include <rpc/rpcb_prot.h>
36#include <sys/types.h>
37#include <sys/stat.h>
38#ifdef PORTMAP
39#include <netinet/in.h>
40#include <rpc/pmap_prot.h>
41#endif
42#include "rpcbind.h"
43#include <syslog.h>
44#include <unistd.h>
45#include <rpcsvc/daemon_utils.h>
33#include <stdio.h>
34#include <errno.h>
35#include <rpc/rpc.h>
36#include <rpc/rpcb_prot.h>
37#include <sys/types.h>
38#include <sys/stat.h>
39#ifdef PORTMAP
40#include <netinet/in.h>
41#include <rpc/pmap_prot.h>
42#endif
43#include "rpcbind.h"
44#include <syslog.h>
45#include <unistd.h>
46#include <rpcsvc/daemon_utils.h>
47#include <assert.h>
46
47/* These files keep the pmap_list and rpcb_list in XDR format */
48static const char rpcbfile[] = DAEMON_DIR "/rpcbind.file";
49#ifdef PORTMAP
50static const char pmapfile[] = DAEMON_DIR "/portmap.file";
51#endif
52
48
49/* These files keep the pmap_list and rpcb_list in XDR format */
50static const char rpcbfile[] = DAEMON_DIR "/rpcbind.file";
51#ifdef PORTMAP
52static const char pmapfile[] = DAEMON_DIR "/portmap.file";
53#endif
54
53
54static bool_t write_struct();
55static bool_t read_struct();
56
57FILE *
58open_tmp_file(filename)
59 char *filename;
55static FILE *
56open_tmp_file(const char *filename)
60{
61 int fd;
62 FILE *fp;
63
64 /*
65 * Remove any existing files, and create a new one.
66 * Ensure that rpcbind is not forced to overwrite
67 * a file pointed to by a symbolic link created

--- 13 unchanged lines hidden (view full) ---

81 close(fd);
82 return (NULL);
83 }
84
85 return (fp);
86}
87
88static bool_t
57{
58 int fd;
59 FILE *fp;
60
61 /*
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

--- 13 unchanged lines hidden (view full) ---

78 close(fd);
79 return (NULL);
80 }
81
82 return (fp);
83}
84
85static bool_t
89write_struct(filename, structproc, list)
90 char *filename;
91 xdrproc_t structproc;
92 void *list;
86write_struct(const char *filename, xdrproc_t structproc, void *list)
93{
94 FILE *fp;
95 XDR xdrs;
96
97 fp = open_tmp_file(filename);
98 if (fp == NULL) {
99 int i;
100
101 for (i = 0; i < 10; i++)
102 close(i);
103 fp = open_tmp_file(filename);
104 if (fp == NULL) {
105 syslog(LOG_ERR,
87{
88 FILE *fp;
89 XDR xdrs;
90
91 fp = open_tmp_file(filename);
92 if (fp == NULL) {
93 int i;
94
95 for (i = 0; i < 10; i++)
96 close(i);
97 fp = open_tmp_file(filename);
98 if (fp == NULL) {
99 syslog(LOG_ERR,
106 "cannot open file = %s for writing", filename);
100 "cannot open file = %s for writing", filename);
107 syslog(LOG_ERR, "cannot save any registration");
108 return (FALSE);
109 }
110 }
111 xdrstdio_create(&xdrs, fp, XDR_ENCODE);
112
113 if (structproc(&xdrs, list) == FALSE) {
101 syslog(LOG_ERR, "cannot save any registration");
102 return (FALSE);
103 }
104 }
105 xdrstdio_create(&xdrs, fp, XDR_ENCODE);
106
107 if (structproc(&xdrs, list) == FALSE) {
108 XDR_DESTROY(&xdrs);
114 syslog(LOG_ERR, "rpcbind: xdr_%s: failed", filename);
115 fclose(fp);
116 return (FALSE);
117 }
118 XDR_DESTROY(&xdrs);
119 fclose(fp);
120 return (TRUE);
121}
122
123static bool_t
109 syslog(LOG_ERR, "rpcbind: xdr_%s: failed", filename);
110 fclose(fp);
111 return (FALSE);
112 }
113 XDR_DESTROY(&xdrs);
114 fclose(fp);
115 return (TRUE);
116}
117
118static bool_t
124read_struct(filename, structproc, list)
125 char *filename;
126 xdrproc_t structproc;
127 void *list;
119read_struct(const char *filename, xdrproc_t structproc, void *list)
128{
129 int fd;
130 FILE *fp = NULL;
131 XDR xdrs;
132 struct stat sbuf_fstat, sbuf_lstat;
133
134 fd = open(filename, O_RDONLY, 0600);
135 if (fd == -1) {
136 fprintf(stderr,
120{
121 int fd;
122 FILE *fp = NULL;
123 XDR xdrs;
124 struct stat sbuf_fstat, sbuf_lstat;
125
126 fd = open(filename, O_RDONLY, 0600);
127 if (fd == -1) {
128 fprintf(stderr,
137 "rpcbind: cannot open file = %s for reading\n", filename);
129 "rpcbind: cannot open file = %s for reading\n", filename);
138 goto error;
139 }
140 fp = fdopen(fd, "r");
141 if (fp == NULL) {
142 close(fd);
143 fprintf(stderr,
130 goto error;
131 }
132 fp = fdopen(fd, "r");
133 if (fp == NULL) {
134 close(fd);
135 fprintf(stderr,
144 "rpcbind: cannot open file = %s for reading\n", filename);
136 "rpcbind: cannot open file = %s for reading\n", filename);
145 goto error;
146 }
147 if (fstat(fd, &sbuf_fstat) != 0) {
148 fprintf(stderr,
137 goto error;
138 }
139 if (fstat(fd, &sbuf_fstat) != 0) {
140 fprintf(stderr,
149 "rpcbind: cannot stat file = %s for reading\n", filename);
141 "rpcbind: cannot stat file = %s for reading\n", filename);
150 goto error;
151 }
152 if (sbuf_fstat.st_uid != DAEMON_UID ||
153 (!S_ISREG(sbuf_fstat.st_mode)) ||
154 (sbuf_fstat.st_mode & S_IRWXG) ||
155 (sbuf_fstat.st_mode & S_IRWXO) ||
156 (sbuf_fstat.st_nlink != 1)) {
142 goto error;
143 }
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)) {
157 fprintf(stderr,
158 "rpcbind: invalid permissions on file = %s for reading\n",
159 filename);
149 fprintf(stderr, "rpcbind: invalid permissions on file = %s for "
150 "reading\n", filename);
160 goto error;
161 }
162 /*
163 * Make sure that the pathname for fstat and lstat is the same and
164 * that it's not a link. An attacker can create symbolic or
165 * hard links and use them to gain unauthorised access to the
166 * system when rpcbind aborts or terminates on SIGINT or SIGTERM.
167 */
168 if (lstat(filename, &sbuf_lstat) != 0) {
169 fprintf(stderr,
151 goto error;
152 }
153 /*
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.
158 */
159 if (lstat(filename, &sbuf_lstat) != 0) {
160 fprintf(stderr,
170 "rpcbind: cannot lstat file = %s for reading\n", filename);
161 "rpcbind: cannot lstat file = %s for reading\n", filename);
171 goto error;
172 }
173 if (sbuf_lstat.st_uid != DAEMON_UID ||
174 (!S_ISREG(sbuf_lstat.st_mode)) ||
175 (sbuf_lstat.st_mode & S_IRWXG) ||
176 (sbuf_lstat.st_mode & S_IRWXO) ||
177 (sbuf_lstat.st_nlink != 1) ||
178 (sbuf_fstat.st_dev != sbuf_lstat.st_dev) ||
179 (sbuf_fstat.st_ino != sbuf_lstat.st_ino)) {
162 goto error;
163 }
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)) {
180 fprintf(stderr,
181 "rpcbind: invalid lstat permissions on file = %s for reading\n",
182 filename);
171 fprintf(stderr, "rpcbind: invalid lstat permissions on file = "
172 "%s for reading\n", filename);
183 goto error;
184 }
185 xdrstdio_create(&xdrs, fp, XDR_DECODE);
186
187 if (structproc(&xdrs, list) == FALSE) {
173 goto error;
174 }
175 xdrstdio_create(&xdrs, fp, XDR_DECODE);
176
177 if (structproc(&xdrs, list) == FALSE) {
178 XDR_DESTROY(&xdrs);
188 fprintf(stderr, "rpcbind: xdr_%s: failed\n", filename);
189 goto error;
190 }
191 XDR_DESTROY(&xdrs);
192 fclose(fp);
193 return (TRUE);
194
179 fprintf(stderr, "rpcbind: xdr_%s: failed\n", filename);
180 goto error;
181 }
182 XDR_DESTROY(&xdrs);
183 fclose(fp);
184 return (TRUE);
185
195error: fprintf(stderr, "rpcbind: will start from scratch\n");
186error:
187 fprintf(stderr, "rpcbind: will start from scratch\n");
196 if (fp != NULL)
197 fclose(fp);
198 return (FALSE);
199}
200
201void
202write_warmstart(void)
203{
188 if (fp != NULL)
189 fclose(fp);
190 return (FALSE);
191}
192
193void
194write_warmstart(void)
195{
196 assert(RW_WRITE_HELD(&list_rbl_lock));
204 (void) write_struct(rpcbfile, xdr_rpcblist_ptr, &list_rbl);
205#ifdef PORTMAP
197 (void) write_struct(rpcbfile, xdr_rpcblist_ptr, &list_rbl);
198#ifdef PORTMAP
199 assert(RW_WRITE_HELD(&list_pml_lock));
206 (void) write_struct(pmapfile, xdr_pmaplist_ptr, &list_pml);
207#endif
208
209}
210
211void
212read_warmstart(void)
213{
214 rpcblist_ptr tmp_rpcbl = NULL;
215#ifdef PORTMAP
216 pmaplist_ptr tmp_pmapl = NULL;
217#endif
200 (void) write_struct(pmapfile, xdr_pmaplist_ptr, &list_pml);
201#endif
202
203}
204
205void
206read_warmstart(void)
207{
208 rpcblist_ptr tmp_rpcbl = NULL;
209#ifdef PORTMAP
210 pmaplist_ptr tmp_pmapl = NULL;
211#endif
218 int ok1, ok2 = TRUE;
219
212
220 ok1 = read_struct(rpcbfile, xdr_rpcblist_ptr, &tmp_rpcbl);
221 if (ok1 == FALSE)
213 if (read_struct(rpcbfile, xdr_rpcblist_ptr, &tmp_rpcbl) == FALSE)
222 return;
214 return;
215
223#ifdef PORTMAP
216#ifdef PORTMAP
224 ok2 = read_struct(pmapfile, xdr_pmaplist_ptr, &tmp_pmapl);
225#endif
226 if (ok2 == FALSE) {
217 if (read_struct(pmapfile, xdr_pmaplist_ptr, &tmp_pmapl) == FALSE) {
227 xdr_free((xdrproc_t)xdr_rpcblist_ptr, (char *)&tmp_rpcbl);
228 return;
229 }
218 xdr_free((xdrproc_t)xdr_rpcblist_ptr, (char *)&tmp_rpcbl);
219 return;
220 }
221#endif
222
230 xdr_free((xdrproc_t)xdr_rpcblist_ptr, (char *)&list_rbl);
231 list_rbl = tmp_rpcbl;
232#ifdef PORTMAP
233 xdr_free((xdrproc_t)xdr_pmaplist_ptr, (char *)&list_pml);
234 list_pml = (pmaplist *)tmp_pmapl;
235#endif
236}
223 xdr_free((xdrproc_t)xdr_rpcblist_ptr, (char *)&list_rbl);
224 list_rbl = tmp_rpcbl;
225#ifdef PORTMAP
226 xdr_free((xdrproc_t)xdr_pmaplist_ptr, (char *)&list_pml);
227 list_pml = (pmaplist *)tmp_pmapl;
228#endif
229}