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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * Change the label of a file
28 */
29
30 #include <ctype.h>
31 #include <locale.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <strings.h>
35 #include <errno.h>
36
37 #include <tsol/label.h>
38
39 #include "labeld.h"
40 #include <sys/tsol/label_macro.h>
41
42 #include <sys/types.h>
43
44 #include <zone.h>
45 #include <sys/zone.h>
46 #include <sys/param.h>
47 #include <string.h>
48
49 static int abspath(char *, const char *, char *);
50
51 /*
52 * setflabel(3TSOL) - set file label
53 *
54 * This is the library interface to the door call.
55 */
56
57 #define clcall callp->param.acall.cargs.setfbcl_arg
58 #define clret callp->param.aret.rvals.setfbcl_ret
59 /*
60 *
61 * Exit error = If error reported, the error indicator,
62 * -1, Unable to access label encodings file;
63 * 0, Invalid binary label passed;
64 * >0, Position after the first character in
65 * string of error, 1 indicates entire string.
66 * Otherwise, unchanged.
67 *
68 * Returns 0, If error.
69 * 1, If successful.
70 *
71 * Calls __call_labeld(SETFLABEL)
72 *
73 */
74
75 int
setflabel(const char * path,m_label_t * label)76 setflabel(const char *path, m_label_t *label)
77 {
78 labeld_data_t call;
79 labeld_data_t *callp = &call;
80 size_t bufsize = sizeof (labeld_data_t);
81 size_t datasize;
82 size_t path_len;
83 static char cwd[MAXPATHLEN];
84 char canon[MAXPATHLEN];
85
86
87 /*
88 * If path is relative and we haven't already determined the current
89 * working directory, do so now. Calculating the working directory
90 * here lets us do the work once, instead of (potentially) repeatedly
91 * in realpath().
92 */
93 if (*path != '/' && cwd[0] == '\0') {
94 if (getcwd(cwd, MAXPATHLEN) == NULL) {
95 cwd[0] = '\0';
96 return (-1);
97 }
98 }
99 /*
100 * Find an absolute pathname in the native file system name space that
101 * corresponds to path, stuffing it into canon.
102 */
103 if (abspath(cwd, path, canon) < 0)
104 return (-1);
105
106 path_len = strlen(canon) + 1;
107
108 datasize = CALL_SIZE(setfbcl_call_t, path_len - BUFSIZE);
109 datasize += 2; /* PAD */
110
111 if (datasize > bufsize) {
112 if ((callp = (labeld_data_t *)malloc(datasize)) == NULL) {
113 return (-1);
114 }
115 bufsize = datasize;
116 }
117
118 callp->callop = SETFLABEL;
119
120 clcall.sl = *label;
121 (void) strcpy(clcall.pathname, canon);
122
123 if (__call_labeld(&callp, &bufsize, &datasize) == SUCCESS) {
124 int err = callp->reterr;
125
126 if (callp != &call) {
127 /* free allocated buffer */
128 free(callp);
129 }
130 /*
131 * reterr == 0, OK,
132 * reterr < 0, invalid binary label,
133 */
134 if (err == 0) {
135 if (clret.status > 0) {
136 errno = clret.status;
137 return (-1);
138 } else {
139 return (0);
140 }
141 } else if (err < 0) {
142 err = 0;
143 }
144 errno = ECONNREFUSED;
145 return (-1);
146 } else {
147 if (callp != &call) {
148 /* free allocated buffer */
149 free(callp);
150 }
151 /* server not present */
152 errno = ECONNREFUSED;
153 return (-1);
154 }
155 } /* setflabel */
156
157 #undef clcall
158 #undef clret
159
160 #define clcall callp->param.acall.cargs.zcopy_arg
161 #define clret callp->param.aret.rvals.zcopy_ret
162 /*
163 *
164 * Exit status = result of zone copy request
165 * -1, Copy not confirmed
166 * Otherwise, unchanged.
167 *
168 * Returns 0, If error.
169 * 1, If successful.
170 *
171 * Calls __call_labeld(ZCOPY)
172 *
173 */
174 int
zonecopy(m_label_t * src_win_sl,char * remote_dir,char * filename,char * local_dir,int transfer_mode)175 zonecopy(m_label_t *src_win_sl, char *remote_dir, char *filename,
176 char *local_dir, int transfer_mode)
177 {
178 labeld_data_t call;
179 labeld_data_t *callp = &call;
180 size_t bufsize = sizeof (labeld_data_t);
181 size_t datasize;
182 size_t strings;
183 size_t remote_dir_len;
184 size_t filename_len;
185 size_t local_dir_len;
186 size_t display_len;
187 char *display;
188
189 remote_dir_len = strlen(remote_dir) + 1;
190 filename_len = strlen(filename) + 1;
191 local_dir_len = strlen(local_dir) + 1;
192
193 if ((display = getenv("DISPLAY")) == NULL)
194 display = "";
195 display_len = strlen(display) + 1;
196
197 strings = remote_dir_len + filename_len + local_dir_len + display_len;
198
199 datasize = CALL_SIZE(zcopy_call_t, strings - BUFSIZE);
200
201 datasize += 4; /* PAD */
202
203 if (datasize > bufsize) {
204 if ((callp = (labeld_data_t *)malloc(datasize)) == NULL) {
205 return (0);
206 }
207 bufsize = datasize;
208 }
209
210 strings = 0;
211 callp->callop = ZCOPY;
212
213 clcall.src_win_sl = *src_win_sl;
214 clcall.transfer_mode = transfer_mode;
215 clcall.remote_dir = strings;
216 strings += remote_dir_len;
217 clcall.filename = strings;
218 strings += filename_len;
219 clcall.local_dir = strings;
220 strings += local_dir_len;
221 clcall.display = strings;
222
223 (void) strcpy(&clcall.buf[clcall.remote_dir], remote_dir);
224 (void) strcpy(&clcall.buf[clcall.filename], filename);
225 (void) strcpy(&clcall.buf[clcall.local_dir], local_dir);
226 (void) strcpy(&clcall.buf[clcall.display], display);
227
228 if (__call_labeld(&callp, &bufsize, &datasize) == SUCCESS) {
229 int err = callp->reterr;
230
231 if (callp != &call) {
232 /* free allocated buffer */
233 free(callp);
234 }
235 /*
236 * reterr == 0, OK,
237 * reterr < 0, transer not confirmed
238 */
239 if (err == 0) {
240 return (clret.status);
241 } else if (err < 0) {
242 err = 0;
243 }
244 return (PIPEMSG_CANCEL);
245 } else {
246 if (callp != &call) {
247 /* free allocated buffer */
248 free(callp);
249 }
250 /* server not present */
251 return (PIPEMSG_CANCEL);
252 }
253 }
254
255 /*
256 * Convert the path given in raw to canonical, absolute, symlink-free
257 * form, storing the result in the buffer named by canon, which must be
258 * at least MAXPATHLEN bytes long. If wd is non-NULL, assume that it
259 * points to a path for the current working directory and use it instead
260 * of invoking getcwd; accepting this value as an argument lets our caller
261 * cache the value, so that realpath (called from this routine) doesn't have
262 * to recalculate it each time it's given a relative pathname.
263 *
264 * Return 0 on success, -1 on failure.
265 */
266 int
abspath(char * wd,const char * raw,char * canon)267 abspath(char *wd, const char *raw, char *canon)
268 {
269 char absbuf[MAXPATHLEN];
270
271 /*
272 * Preliminary sanity check.
273 */
274 if (raw == NULL || canon == NULL)
275 return (-1);
276
277 /*
278 * If the path is relative, convert it to absolute form,
279 * using wd if it's been supplied.
280 */
281 if (raw[0] != '/') {
282 char *limit = absbuf + sizeof (absbuf);
283 char *d;
284
285 /* Fill in working directory. */
286 if (wd != NULL)
287 (void) strncpy(absbuf, wd, sizeof (absbuf));
288 else if (getcwd(absbuf, strlen(absbuf)) == NULL)
289 return (-1);
290
291 /* Add separating slash. */
292 d = absbuf + strlen(absbuf);
293 if (d < limit)
294 *d++ = '/';
295
296 /* Glue on the relative part of the path. */
297 while (d < limit && (*d++ = *raw++))
298 continue;
299
300 raw = absbuf;
301 }
302
303 /*
304 * Call realpath to canonicalize and resolve symlinks.
305 */
306 return (realpath(raw, canon) == NULL ? -1 : 0);
307 }
308