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