Changeset 231
- Timestamp:
- 05/20/05 02:29:47 (4 years ago)
- Files:
-
- op/trunk/ChangeLog (modified) (1 diff)
- op/trunk/defs.h (modified) (3 diffs)
- op/trunk/lex.l (modified) (7 diffs)
- op/trunk/main.c (modified) (12 diffs)
- op/trunk/Makefile (modified) (2 diffs)
- op/trunk/op.1 (modified) (4 diffs)
- op/trunk/README (modified) (1 diff)
- op/trunk/.todo (modified) (2 diffs)
- op/trunk/util.c (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
op/trunk/ChangeLog
r226 r231 150 150 151 151 Closes #4 152 153 20/05/05 - op 1.30 154 ================== 155 Fixed use of DEFAULT section, closes #5. Quite a pain in the arse actually. 156 157 Environment variables can now be propagated into child environments even when 158 "environment" is specified. This will override any existing variables. 159 160 Now using vsnprintf rather than snprintf. Correspondingly, changed preprocessor 161 define which may mean build scripts need to be changed. op/trunk/defs.h
r226 r231 39 39 int array_extend(array_t *array, int capacity); 40 40 41 extern cmd_t *First, *Build() ;41 extern cmd_t *First, *Build(), *BuildSingle(); 42 42 extern var_t *Variables; 43 43 extern unsigned minimum_logging_level; … … 45 45 void fatal(int logit, const char *format, ...); 46 46 int logger(unsigned flags, const char *format, ...); 47 void strnprintf(char *out, int len, const char *format, ...); 48 char *strtolower(char *in); 47 49 48 50 int ReadFile(char *file); … … 54 56 #define OP_ACCESS "/etc/op.conf" 55 57 #define OP_ACCESS_DIR "/etc/op.d" 56 #define VERSION "1. 29"58 #define VERSION "1.30" 57 59 58 60 #define VAR_EXPAND_LEN 8192 op/trunk/lex.l
r227 r231 244 244 } 245 245 246 static cmd_t *newcmd(name) 247 char *name; 246 static cmd_t *alloccmd(char *name) 248 247 { 249 248 cmd_t *cmd = (cmd_t *)malloc(sizeof(cmd_t)); … … 251 250 if (cmd == NULL) 252 251 fatal(1, "Unable to alloc space for new command"); 253 254 cmd->next = First;255 First = cmd;256 252 257 253 cmd->name = savestr(name); … … 265 261 266 262 return cmd; 263 } 264 265 static cmd_t *newcmd(char *name) 266 { 267 cmd_t *cmd = alloccmd(name); 268 269 cmd->next = First; 270 First = cmd; 271 272 return cmd; 273 267 274 } 268 275 … … 380 387 } 381 388 382 cmd_t *Build(def, cmd) 383 cmd_t * def, *cmd;384 { 385 cmd_t *new = newcmd("");386 char defname[MAXSTRLEN], optname[MAXSTRLEN], *cp;389 /* Build a new command but don't merge it into the global list */ 390 cmd_t *BuildSingle(cmd_t *def, cmd_t *cmd) 391 { 392 cmd_t *new = alloccmd(cmd->name ? cmd->name : ""); 393 char defname[MAXSTRLEN], optname[MAXSTRLEN], *cp; 387 394 int i, j; 388 395 #ifndef _AIX … … 398 405 399 406 for (i = 0; i < def->nopts; i++) { 407 int skipped = 0; 408 400 409 if ((cp = strchr(def->opts[i], '=')) == NULL) 401 410 strcpy(defname, def->opts[i]); … … 413 422 optname[l] = '\0'; 414 423 } 415 if (strcmp(defname, optname) == 0) 416 def->opts[i][0] = '\0'; 424 if (strcmp(defname, optname) == 0) { 425 skipped = 1; 426 break; 427 } 417 428 } 429 if (skipped) continue; 418 430 if (def->opts[i][0] != '\0') 419 431 addarg(1, new, def->opts[i]); … … 426 438 return new; 427 439 } 440 441 442 /* Build a new command *and* merge it with the global command list */ 443 cmd_t *Build(cmd_t *def, cmd_t *cmd) 444 { 445 cmd_t *new = BuildSingle(def, cmd); 446 447 new->next = First; 448 First = new; 449 450 return new; 451 } op/trunk/main.c
r230 r231 107 107 void ListCommands() 108 108 { 109 cmd_t * cmd;109 cmd_t *def, *cmd; 110 110 array_t *cmds = array_alloc(); 111 111 int length = 0, i; 112 112 113 def = Find("DEFAULT"); 113 114 /* first pass, get maximum command length and number of commands we have 114 115 permission to use */ 115 116 for (cmd = First; cmd != NULL; cmd = cmd->next) { 116 if (strcmp(cmd->name, "DEFAULT") && VerifyPermissions(cmd) >= 0) { 117 int l = strlen(cmd->name); 118 119 for (i = 0; i < cmds->size; ++i) 120 if (!strcmp(((cmd_t*)cmds->data[i])->name, cmd->name)) 121 break; 122 if (i == cmds->size) { 123 if (l > length) length = l; 124 array_push(cmds, cmd); 117 118 if (strcmp(cmd->name, "DEFAULT")) { 119 cmd_t *new = BuildSingle(def, cmd); 120 121 if (VerifyPermissions(new) >= 0) { 122 int l = strlen(new->name); 123 124 for (i = 0; i < cmds->size; ++i) 125 if (!strcmp(((cmd_t*)cmds->data[i])->name, new->name)) 126 break; 127 if (i == cmds->size) { 128 if (l > length) length = l; 129 array_push(cmds, new); 130 } 125 131 } 126 132 } … … 133 139 cmd = cmds->data[i]; 134 140 135 if (!strcmp(cmd->name, "DEFAULT")) continue; 136 137 if (VerifyPermissions(cmd) >= 0) { 138 char *help = FindOpt(cmd, "help"); 139 140 if (!help || !*help) help = "(no help available)"; 141 printf("%-*s", length + 2, cmd->name); 142 while (*help) { 143 int j; 144 145 printf("%-*.*s\n", 77 - length, 77 - length, help); 146 for (j = 0; j < 77 - length && *help; ++j, ++help) ; 147 if (j == 77 - length) 148 printf("%-*s", length + 2, ""); 141 if (strcmp(cmd->name, "DEFAULT")) { 142 cmd_t *new = BuildSingle(def, cmd); 143 144 if (VerifyPermissions(new) >= 0) { 145 char *help = FindOpt(new, "help"); 146 147 if (!help || !*help) help = "(no help available)"; 148 printf("%-*s", length + 2, new->name); 149 while (*help) { 150 int j; 151 152 printf("%-*.*s\n", 77 - length, 77 - length, help); 153 for (j = 0; j < 77 - length && *help; ++j, ++help) ; 154 if (j == 77 - length) 155 printf("%-*s", length + 2, ""); 156 } 149 157 } 150 158 } … … 174 182 for (i = 0; i < dir_list->size; ++i) { 175 183 char full_path[PATH_MAX]; 176 #ifdef HAVE_SNPRINTF 177 snprintf(full_path, PATH_MAX, "%s/%s", OP_ACCESS_DIR, (char*)dir_list->data[i]); 178 #else 179 sprintf(full_path, "%s/%s", OP_ACCESS_DIR, (char*)dir_list->data[i]); 180 #endif 184 strnprintf(full_path, PATH_MAX, "%s/%s", OP_ACCESS_DIR, (char*)dir_list->data[i]); 181 185 if (ReadFile(full_path)) successes++; 182 186 } … … 299 303 300 304 new = Build(def, cmd); 305 301 306 num = CountArgs(new); 302 307 … … 321 326 322 327 for (cmd = First; cmd != NULL; cmd = cmd ->next) { 323 if (strcmp(cmd->name, name) == 0 && VerifyPermissions(cmd) >= 0)328 if (strcmp(cmd->name, name) == 0) 324 329 break; 325 330 } … … 449 454 regexp *reg1 = NULL; 450 455 struct passwd *pw; 451 #ifdef USE_PAM452 struct pam_conv pamconv = { pam_conversation, NULL };453 pam_handle_t *pam;454 #endif455 456 struct group *gr; 456 457 … … 950 951 if (cmd->opts[i][0] != '$') 951 952 continue; 953 /* Skip positional constraints */ 952 954 cp = cmd->opts[i] + 1; 953 955 flag = 0; … … 957 959 cp++; 958 960 } 959 if (! flag)961 if (!flag) 960 962 continue; 961 if (strchr(cmd->opts[i], '=') != NULL) { 962 if (curenv + 1 >= MAXENV) 963 fatal(1, "Environment length exceeded"); 964 new_envp[curenv++] = cmd->opts[i] + 1; 965 continue; 966 } 963 /* Propagate variable into environment if it exists */ 967 964 for (j = 0; environ[j] != NULL ; j++) { 968 965 if ((cp = strchr(environ[j], '=')) == NULL) 969 966 continue; 970 if (strncmp(cmd->opts[i] + 1, environ[j], 971 cp - environ[j]) == 0) { 967 if (strncmp(cmd->opts[i] + 1, environ[j], cp - environ[j]) == 0) { 972 968 if (curenv + 1 >= MAXENV) 973 969 fatal(1, "Environment length exceeded"); … … 982 978 fatal(1, "Environment length exceeded"); 983 979 new_envp[curenv++] = environ[i]; 980 } 981 } 982 /* Allow over-ride of environment variables. */ 983 for (i = 0; i < cmd->nopts; ++i) { 984 /* Skip positional constraints */ 985 cp = cmd->opts[i] + 1; 986 flag = 0; 987 while ((*cp != '\0') && (*cp != '=')) { 988 if (! isdigit(*cp)) 989 flag = 1; 990 cp++; 991 } 992 if (!flag) 993 continue; 994 if (cmd->opts[i][0] == '$' && strchr(cmd->opts[i], '=') != NULL) { 995 if (curenv + 1 >= MAXENV) 996 fatal(1, "Environment length exceeded"); 997 new_envp[curenv++] = cmd->opts[i] + 1; 998 continue; 984 999 } 985 1000 } … … 1171 1186 } 1172 1187 1173 #ifndef HAVE_SNPRINTF1174 #warning You have not compiled op with snprintf support, presumably because1175 #warning your system does not have it. This leaves op potentially open to1176 #warning buffer overflows.1177 #endif1178 1179 1188 unsigned minimum_logging_level = 99; 1180 1189 … … 1187 1196 if (realuser) username = realuser->pw_name; 1188 1197 1189 #ifdef HAVE_SNPRINTF 1190 vsnprintf(buffer2, MAXSTRLEN, format, args); 1191 #else 1192 vsprintf(buffer2, format, args); 1193 #endif 1198 strnprintf(buffer2, MAXSTRLEN, format, args); 1194 1199 if (level & LOG_PRINT) printf("%s\n", buffer2); 1195 1200 level &= ~LOG_PRINT; 1196 #ifdef HAVE_SNPRINTF 1197 snprintf(buffer, MAXSTRLEN, "%s =>%s: %s", username, 1201 strnprintf(buffer, MAXSTRLEN, "%s =>%s: %s", username, 1198 1202 format_cmd(gargc, gargv, buffer3, MAXSTRLEN), 1199 1203 buffer2); 1200 #else1201 sprintf(buffer, "%s =>%s: %s", username,1202 format_cmd(gargc, gargv, buffer3, MAXSTRLEN),1203 buffer2);1204 #endif1205 1204 syslog(level, "%s", buffer); 1206 1205 return -1; … … 1221 1220 1222 1221 va_start(ap, format); 1223 #ifdef HAVE_SNPRINTF 1224 vsnprintf(buffer, MAXSTRLEN, format, ap); 1225 #else 1226 vsprintf(buffer, format, ap); 1227 #endif 1222 strnprintf(buffer, MAXSTRLEN, format, ap); 1228 1223 fprintf(stderr, "%s\n", buffer); 1229 1224 if (logit) logger(LOG_ERR, "%s", buffer); op/trunk/Makefile
r226 r231 4 4 CC=gcc 5 5 INC= -I. -Wall 6 LIBS= -l l -L/lib -lcrypt6 LIBS= -lfl -L/lib -lcrypt 7 7 DESTDIR= 8 8 PREFIX=/usr … … 27 27 28 28 # Enable PAM support 29 #OPTS += -DUSE_PAM30 #LDFLAGS += -lpam29 OPTS += -DUSE_PAM 30 LDFLAGS += -lpam 31 31 32 32 # Enable shadow support (generally not used in conjunction with PAM) 33 OPTS += -DUSE_SHADOW33 #OPTS += -DUSE_SHADOW 34 34 35 35 # Enable XAUTH support 36 36 OPTS += -DXAUTH=\"/usr/X11R6/bin/xauth\" 37 37 38 # We have snprintf(3)39 OPTS += -DHAVE_ SNPRINTF38 # We have vsnprintf(3) (more secure) 39 OPTS += -DHAVE_VSNPRINTF 40 40 41 41 ############################ LEGACY CONFIG #################################### op/trunk/op.1
r226 r231 167 167 .B $USER) 168 168 means that this environment variable is inherited unchanged from 169 the caller's shell. 169 the caller's shell. If the $VAR is an assignment the environment variable 170 is set to the specified value in the new environment. 170 171 .TP 171 172 .B environment … … 297 298 .br 298 299 password 300 .br 301 help="Root shell" 299 302 .PP 300 303 .br … … 308 311 .br 309 312 password 313 .br 314 help="Reboot system" 310 315 .PP 311 316 # 'op shutdown <time>' - shutdown at a … … 322 327 .br 323 328 $1=(now|[0-1]?[0-9]:[0-9][0-9]|2[0-3]:[0-5][0-9]|\+[0-9]+) 329 .br 330 help="Shutdown system" 324 331 .PP 325 332 # Switch inetd on and off, shows complex op/trunk/README
r207 r231 79 79 Howard Owen. (hbo@egbok.com) 80 80 81 And again for contributions by me, Alec Thomas, Copyright (C) 2002-2004. 81 And again for contributions by me, Alec Thomas (alec@swapoff.org), 82 Copyright (C) 2002-2005. 82 83 op/trunk/.todo
r228 r231 1 <!-- Automagically generated by the ToDo program on 14/04/05, 23:43-->1 <!-- Automagically generated by the ToDo program on 20/05/05, 12:57 --> 2 2 <todo version="0.1.18"> 3 3 <note priority="medium" time="1031933086" done="1049945562"> … … 28 28 Make a "nolog" option to prevent logging - for automated commands. 29 29 </note> 30 <note priority="medium" time="1113486219" >30 <note priority="medium" time="1113486219" done="1116557866"> 31 31 Fix bug where $VARS aren't being expanded correctly inside quotes. This is occurring in main.c. 32 32 </note> op/trunk/util.c
r226 r231 1 #include <stdio.h> 2 #include <ctype.h> 3 #include <stdarg.h> 1 4 #include <stdlib.h> 2 5 #include "defs.h" 6 7 #ifndef HAVE_VSNPRINTF 8 #warning You have not compiled op with vsnprintf 9 #warning support, presumably because your system 10 #warning does not have it. This leaves op open 11 #warning to potential buffer overflows. 12 #endif 13 14 #ifdef HAVE_SNPRINTF 15 #error "Now using 'vsnprintf' instead of snprintf. Adjust your build to define HAVE_VSNPRINTF." 16 #endif 17 18 void strnprintf(char *out, int len, const char *format, ...) { 19 va_list args; 20 21 va_start(args, format); 22 #ifdef HAVE_VSNPRINTF 23 vsnprintf(out, len, format, args); 24 #else 25 vsprintf(out, format, args); 26 #endif 27 va_end(args); 28 } 29 30 char *strtolower(char *in) { 31 char *i; 32 33 for (i = in; *i; ++i) *i = tolower(*i); 34 return in; 35 } 3 36 4 37 array_t *array_alloc() {
