Changeset 231

Show
Ignore:
Timestamp:
05/20/05 02:29:47 (4 years ago)
Author:
athomas
Message:
  • Fixed use of DEFAULT section, closes #5. Quite a pain in the arse actually.
  • Environment variables can now be propagated into child environments even when "environment" is specified. This will override any existing variables.
  • Now using vsnprintf rather than snprintf. Correspondingly, changed preprocessor define which may mean build scripts need to be changed.
Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • op/trunk/ChangeLog

    r226 r231  
    150150 
    151151Closes #4 
     152 
     15320/05/05 - op 1.30 
     154================== 
     155Fixed use of DEFAULT section, closes #5. Quite a pain in the arse actually. 
     156 
     157Environment variables can now be propagated into child environments even when 
     158"environment" is specified. This will override any existing variables. 
     159 
     160Now using vsnprintf rather than snprintf. Correspondingly, changed preprocessor 
     161define which may mean build scripts need to be changed. 
  • op/trunk/defs.h

    r226 r231  
    3939int array_extend(array_t *array, int capacity); 
    4040 
    41 extern cmd_t    *First, *Build()
     41extern cmd_t    *First, *Build(), *BuildSingle()
    4242extern var_t    *Variables; 
    4343extern unsigned minimum_logging_level; 
     
    4545void fatal(int logit, const char *format, ...); 
    4646int logger(unsigned flags, const char *format, ...); 
     47void strnprintf(char *out, int len, const char *format, ...); 
     48char *strtolower(char *in); 
    4749 
    4850int ReadFile(char *file); 
     
    5456#define OP_ACCESS       "/etc/op.conf" 
    5557#define OP_ACCESS_DIR   "/etc/op.d" 
    56 #define VERSION     "1.29
     58#define VERSION     "1.30
    5759 
    5860#define VAR_EXPAND_LEN  8192 
  • op/trunk/lex.l

    r227 r231  
    244244} 
    245245 
    246 static cmd_t    *newcmd(name) 
    247 char    *name; 
     246static cmd_t    *alloccmd(char *name) 
    248247{ 
    249248        cmd_t   *cmd = (cmd_t *)malloc(sizeof(cmd_t)); 
     
    251250        if (cmd == NULL) 
    252251                fatal(1, "Unable to alloc space for new command"); 
    253  
    254         cmd->next = First; 
    255         First = cmd; 
    256252 
    257253        cmd->name = savestr(name); 
     
    265261 
    266262        return cmd; 
     263} 
     264 
     265static 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 
    267274} 
    268275 
     
    380387} 
    381388 
    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 */ 
     390cmd_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; 
    387394        int             i, j; 
    388395#ifndef _AIX 
     
    398405 
    399406        for (i = 0; i < def->nopts; i++) { 
     407        int skipped = 0; 
     408 
    400409                if ((cp = strchr(def->opts[i], '=')) == NULL) 
    401410                        strcpy(defname, def->opts[i]); 
     
    413422                                optname[l] = '\0'; 
    414423                        } 
    415                         if (strcmp(defname, optname) == 0) 
    416                                 def->opts[i][0] = '\0'; 
     424                        if (strcmp(defname, optname) == 0) { 
     425                                skipped = 1; 
     426                                break; 
     427                        } 
    417428                } 
     429                if (skipped) continue; 
    418430                if (def->opts[i][0] != '\0') 
    419431                        addarg(1, new, def->opts[i]); 
     
    426438        return new; 
    427439} 
     440 
     441 
     442/* Build a new command *and* merge it with the global command list */ 
     443cmd_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  
    107107void ListCommands() 
    108108{ 
    109 cmd_t *cmd; 
     109cmd_t *def, *cmd; 
    110110array_t *cmds = array_alloc(); 
    111111int length = 0, i; 
    112112 
     113        def = Find("DEFAULT"); 
    113114        /*      first pass, get maximum command length and number of commands we have 
    114115                permission to use */ 
    115116        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                                } 
    125131                        } 
    126132                } 
     
    133139                cmd = cmds->data[i]; 
    134140 
    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                                } 
    149157                        } 
    150158                } 
     
    174182                for (i = 0; i < dir_list->size; ++i) { 
    175183                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]); 
    181185                        if (ReadFile(full_path)) successes++; 
    182186                } 
     
    299303 
    300304        new = Build(def, cmd); 
     305 
    301306        num = CountArgs(new); 
    302307 
     
    321326 
    322327        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
    324329                        break; 
    325330        } 
     
    449454regexp          *reg1 = NULL; 
    450455struct passwd   *pw; 
    451 #ifdef USE_PAM 
    452 struct pam_conv pamconv = { pam_conversation, NULL }; 
    453 pam_handle_t *pam; 
    454 #endif 
    455456struct group    *gr; 
    456457 
     
    950951                        if (cmd->opts[i][0] != '$') 
    951952                                continue; 
     953                        /* Skip positional constraints */ 
    952954                        cp = cmd->opts[i] + 1; 
    953955                        flag = 0; 
     
    957959                                cp++; 
    958960                        } 
    959                         if (! flag) 
     961                        if (!flag) 
    960962                                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 */ 
    967964                        for (j = 0; environ[j] != NULL ; j++) { 
    968965                                if ((cp = strchr(environ[j], '=')) == NULL) 
    969966                                        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) { 
    972968                                        if (curenv + 1 >= MAXENV) 
    973969                                                fatal(1, "Environment length exceeded"); 
     
    982978                                fatal(1, "Environment length exceeded"); 
    983979                        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; 
    984999                } 
    9851000        } 
     
    11711186} 
    11721187 
    1173 #ifndef HAVE_SNPRINTF 
    1174 #warning You have not compiled op with snprintf support, presumably because 
    1175 #warning your system does not have it. This leaves op potentially open to 
    1176 #warning buffer overflows. 
    1177 #endif 
    1178  
    11791188unsigned minimum_logging_level = 99; 
    11801189 
     
    11871196        if (realuser) username = realuser->pw_name; 
    11881197 
    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); 
    11941199        if (level & LOG_PRINT) printf("%s\n", buffer2); 
    11951200        level &= ~LOG_PRINT; 
    1196 #ifdef HAVE_SNPRINTF 
    1197         snprintf(buffer, MAXSTRLEN, "%s =>%s: %s", username,  
     1201        strnprintf(buffer, MAXSTRLEN, "%s =>%s: %s", username,  
    11981202                format_cmd(gargc, gargv, buffer3, MAXSTRLEN), 
    11991203                buffer2); 
    1200 #else 
    1201         sprintf(buffer, "%s =>%s: %s", username,  
    1202                 format_cmd(gargc, gargv, buffer3, MAXSTRLEN), 
    1203                 buffer2); 
    1204 #endif 
    12051204        syslog(level, "%s", buffer); 
    12061205        return -1; 
     
    12211220 
    12221221        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); 
    12281223        fprintf(stderr, "%s\n", buffer); 
    12291224        if (logit) logger(LOG_ERR, "%s", buffer); 
  • op/trunk/Makefile

    r226 r231  
    44CC=gcc 
    55INC= -I. -Wall 
    6 LIBS= -ll -L/lib -lcrypt 
     6LIBS= -lfl -L/lib -lcrypt 
    77DESTDIR= 
    88PREFIX=/usr 
     
    2727 
    2828# Enable PAM support 
    29 #OPTS += -DUSE_PAM 
    30 #LDFLAGS += -lpam 
     29OPTS += -DUSE_PAM 
     30LDFLAGS += -lpam 
    3131 
    3232# Enable shadow support (generally not used in conjunction with PAM) 
    33 OPTS += -DUSE_SHADOW 
     33#OPTS += -DUSE_SHADOW 
    3434 
    3535# Enable XAUTH support 
    3636OPTS += -DXAUTH=\"/usr/X11R6/bin/xauth\" 
    3737 
    38 # We have snprintf(3
    39 OPTS += -DHAVE_SNPRINTF 
     38# We have vsnprintf(3) (more secure
     39OPTS += -DHAVE_VSNPRINTF 
    4040 
    4141############################ LEGACY CONFIG #################################### 
  • op/trunk/op.1

    r226 r231  
    167167.B $USER) 
    168168means that this environment variable is inherited unchanged from 
    169 the caller's shell. 
     169the caller's shell. If the $VAR is an assignment the environment variable 
     170is set to the specified value in the new environment. 
    170171.TP 
    171172.B environment 
     
    297298.br 
    298299        password 
     300.br 
     301    help="Root shell" 
    299302.PP 
    300303.br 
     
    308311.br 
    309312        password 
     313.br 
     314    help="Reboot system" 
    310315.PP 
    311316# 'op shutdown <time>' - shutdown at a  
     
    322327.br 
    323328    $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" 
    324331.PP 
    325332# Switch inetd on and off, shows complex 
  • op/trunk/README

    r207 r231  
    7979        Howard Owen. (hbo@egbok.com) 
    8080 
    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. 
    8283 
  • 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 --> 
    22<todo version="0.1.18"> 
    33    <note priority="medium" time="1031933086" done="1049945562"> 
     
    2828        Make a "nolog" option to prevent logging - for automated commands. 
    2929    </note> 
    30     <note priority="medium" time="1113486219"
     30    <note priority="medium" time="1113486219" done="1116557866"
    3131        Fix bug where $VARS aren't being expanded correctly inside quotes. This is occurring in main.c. 
    3232    </note> 
  • op/trunk/util.c

    r226 r231  
     1#include <stdio.h> 
     2#include <ctype.h> 
     3#include <stdarg.h> 
    14#include <stdlib.h> 
    25#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 
     18void strnprintf(char *out, int len, const char *format, ...) { 
     19va_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 
     30char *strtolower(char *in) { 
     31char *i; 
     32 
     33        for (i = in; *i; ++i) *i = tolower(*i); 
     34        return in; 
     35} 
    336 
    437array_t *array_alloc() {