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} |