o a new -U flag can be used in conjunction with "sudo -l" to allow
root (or a user with "sudo ALL") list another user's privileges.
+ * A new -g flag has been added to allow the user to specify a
+ primary group to run the command as. The sudoers syntax has been
+ extended to include a group section in the Runas specification.
+
* A uid may now be used anywhere a username is valid.
* The "secure_path" run-time Defaults option has been restored.
break;
case 'U':
p++;
- len += strlen(*user_runas) - 2;
+ len += strlen(runas_pw->pw_name) - 2;
subst = 1;
break;
case '%':
continue;
case 'U':
p++;
- n = strlcpy(np, *user_runas, np - endp);
+ n = strlcpy(np, runas_pw->pw_name, np - endp);
if (n >= np - endp)
goto oflow;
np += n;
p = user_tty;
if (def_targetpw)
len = easprintf(timestampfile, "%s/%s/%s:%s", dirparent, user_name,
- p, *user_runas);
+ p, runas_pw->pw_name);
else
len = easprintf(timestampfile, "%s/%s/%s", dirparent, user_name, p);
if (len >= PATH_MAX)
log_error(0, "timestamp path too long: %s", *timestampfile);
} else if (def_targetpw) {
len = easprintf(timestampfile, "%s/%s/%s", dirparent, user_name,
- *user_runas);
+ runas_pw->pw_name);
if (len >= PATH_MAX)
log_error(0, "timestamp path too long: %s", *timestampfile);
} else
runas_default
T_STR
"Default user to run commands as: %s"
- *set_runaspw
secure_path
T_STR|T_BOOL
"Value to override user's $PATH with: %s"
/* Finally do the lists (currently just environment tables). */
init_envtables();
- /*
- * The following depend on the above values.
- * We use a pointer to the string so that if its
- * value changes we get the change.
- */
- if (user_runas == NULL)
- user_runas = &def_runas_default;
-
firsttime = 0;
}
return(FALSE);
break;
case DEFAULTS_RUNAS:
- if (runaslist_matches(&def->binding) &&
+ if (runaslist_matches(&def->binding, NULL) &&
!set_default(def->var, def->val, def->op))
return(FALSE);
break;
#define yyerrok (yyerrflag=0)
#define YYRECOVERING() (yyerrflag!=0)
#define YYPREFIX "yy"
-#line 2 "./gram.y"
+#line 2 "gram.y"
/*
* Copyright (c) 1996, 1998-2005, 2007
* Todd C. Miller <Todd.Miller@courtesan.com>
}
parse_error = TRUE;
}
-#line 103 "./gram.y"
+#line 103 "gram.y"
#ifndef YYSTYPE_DEFINED
#define YYSTYPE_DEFINED
typedef union {
struct cmndspec *cmndspec;
struct defaults *defaults;
struct member *member;
+ struct runascontainer *runas;
struct privilege *privilege;
struct sudo_command command;
struct cmndtag tag;
int tok;
} YYSTYPE;
#endif /* YYSTYPE_DEFINED */
-#line 134 "y.tab.c"
+#line 135 "y.tab.c"
#define COMMAND 257
#define ALIAS 258
#define DEFVAR 259
short yylhs[] =
#endif
{ -1,
- 0, 0, 21, 21, 22, 22, 22, 22, 22, 22,
- 22, 22, 22, 22, 22, 22, 4, 4, 3, 3,
- 3, 3, 3, 19, 19, 18, 10, 10, 8, 8,
- 8, 8, 8, 2, 2, 1, 6, 6, 14, 14,
- 13, 13, 11, 11, 15, 15, 15, 15, 15, 20,
- 20, 20, 20, 20, 20, 20, 5, 5, 5, 24,
- 24, 27, 9, 9, 25, 25, 28, 7, 7, 26,
- 26, 29, 23, 23, 30, 17, 17, 12, 12, 16,
- 16, 16, 16, 16,
+ 0, 0, 22, 22, 23, 23, 23, 23, 23, 23,
+ 23, 23, 23, 23, 23, 23, 4, 4, 3, 3,
+ 3, 3, 3, 20, 20, 19, 10, 10, 8, 8,
+ 8, 8, 8, 2, 2, 1, 6, 6, 17, 17,
+ 18, 18, 18, 21, 21, 21, 21, 21, 21, 21,
+ 5, 5, 5, 25, 25, 28, 9, 9, 26, 26,
+ 29, 7, 7, 27, 27, 30, 24, 24, 31, 13,
+ 13, 11, 11, 12, 12, 12, 12, 12, 16, 16,
+ 14, 14, 15, 15, 15,
};
#if defined(__cplusplus) || defined(__STDC__)
const short yylen[] =
2, 2, 3, 3, 3, 3, 1, 3, 1, 2,
3, 3, 3, 1, 3, 3, 1, 2, 1, 1,
1, 1, 1, 1, 3, 3, 1, 2, 0, 3,
- 1, 3, 1, 2, 1, 1, 1, 1, 1, 0,
- 2, 2, 2, 2, 2, 2, 1, 1, 1, 1,
- 3, 3, 1, 3, 1, 3, 3, 1, 3, 1,
- 3, 3, 1, 3, 3, 1, 3, 1, 2, 1,
- 1, 1, 1, 1,
+ 1, 3, 2, 0, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 3, 3, 1, 3, 1, 3,
+ 3, 1, 3, 1, 3, 3, 1, 3, 3, 1,
+ 3, 1, 2, 1, 1, 1, 1, 1, 1, 3,
+ 1, 2, 1, 1, 1,
};
#if defined(__cplusplus) || defined(__STDC__)
const short yydefred[] =
short yydefred[] =
#endif
{ 0,
- 0, 80, 82, 83, 84, 0, 0, 0, 0, 0,
- 81, 5, 0, 0, 0, 0, 0, 0, 76, 78,
+ 0, 74, 76, 77, 78, 0, 0, 0, 0, 0,
+ 75, 5, 0, 0, 0, 0, 0, 0, 70, 72,
0, 0, 3, 6, 0, 0, 17, 0, 29, 32,
- 31, 33, 30, 0, 27, 0, 63, 0, 45, 47,
- 48, 49, 46, 0, 41, 0, 43, 59, 58, 57,
- 0, 37, 68, 0, 0, 0, 60, 0, 0, 65,
- 0, 0, 73, 0, 0, 70, 79, 0, 0, 24,
- 0, 4, 0, 0, 0, 20, 0, 28, 0, 0,
- 0, 44, 0, 0, 38, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 77, 0, 0, 21, 22,
- 23, 18, 64, 42, 69, 0, 61, 0, 66, 0,
- 74, 0, 71, 0, 34, 0, 50, 25, 0, 0,
- 0, 40, 35, 51, 52, 53, 54, 55, 56, 36,
+ 31, 33, 30, 0, 27, 0, 57, 0, 0, 53,
+ 52, 51, 0, 37, 62, 0, 0, 0, 54, 0,
+ 0, 59, 0, 0, 67, 0, 0, 64, 73, 0,
+ 0, 24, 0, 4, 0, 0, 0, 20, 0, 28,
+ 0, 0, 0, 0, 38, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 71, 0, 0, 21, 22,
+ 23, 18, 58, 63, 0, 55, 0, 60, 0, 68,
+ 0, 65, 0, 34, 0, 44, 25, 0, 0, 0,
+ 0, 0, 83, 85, 84, 0, 79, 81, 0, 0,
+ 40, 35, 45, 46, 47, 48, 49, 50, 36, 82,
+ 0, 0, 80,
};
#if defined(__cplusplus) || defined(__STDC__)
const short yydgoto[] =
short yydgoto[] =
#endif
{ 18,
- 115, 116, 27, 28, 52, 53, 54, 35, 69, 37,
- 45, 19, 46, 117, 47, 20, 21, 70, 71, 121,
- 22, 23, 62, 56, 59, 65, 57, 60, 66, 63,
+ 104, 105, 27, 28, 44, 45, 46, 35, 61, 37,
+ 19, 20, 21, 117, 118, 119, 106, 110, 62, 63,
+ 112, 22, 23, 54, 48, 51, 57, 49, 52, 58,
+ 55,
};
#if defined(__cplusplus) || defined(__STDC__)
const short yysindex[] =
short yysindex[] =
#endif
{ -33,
- -269, 0, 0, 0, 0, -6, 217, 454, 461, -17,
- 0, 0, -250, -247, -240, -238, -220, 0, 0, 0,
- 141, -33, 0, 0, -26, -231, 0, -4, 0, 0,
- 0, 0, 0, -212, 0, -23, 0, -21, 0, 0,
- 0, 0, 0, -205, 0, -11, 0, 0, 0, 0,
- -243, 0, 0, -8, -1, -14, 0, 3, 4, 0,
- 5, 7, 0, 6, 10, 0, 0, 454, -31, 0,
- 11, 0, -213, -209, -202, 0, -6, 0, 217, -4,
- -4, 0, 461, -4, 0, -17, -4, 217, -250, -17,
- -247, 454, -240, 461, -238, 0, 31, 217, 0, 0,
- 0, 0, 0, 0, 0, 28, 0, 29, 0, 30,
- 0, 32, 0, 461, 0, 33, 0, 0, -35, 31,
- 250, 0, 0, 0, 0, 0, 0, 0, 0, 0,};
+ -269, 0, 0, 0, 0, -8, 454, 458, 458, -17,
+ 0, 0, -249, -247, -241, -231, -243, 0, 0, 0,
+ 141, -33, 0, 0, -37, -216, 0, -16, 0, 0,
+ 0, 0, 0, -221, 0, -23, 0, -21, -21, 0,
+ 0, 0, -244, 0, 0, -11, -14, -1, 0, -6,
+ 2, 0, 3, 4, 0, 5, 7, 0, 0, 458,
+ -15, 0, 9, 0, -219, -207, -202, 0, -8, 0,
+ 454, -16, -16, -16, 0, -17, -16, 454, -249, -17,
+ -247, 458, -241, 458, -231, 0, 23, 454, 0, 0,
+ 0, 0, 0, 0, 24, 0, 25, 0, 27, 0,
+ 27, 0, 217, 0, 28, 0, 0, -3, -9, 29,
+ 23, 250, 0, 0, 0, -222, 0, 0, 30, -3,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ -3, 30, 0,};
#if defined(__cplusplus) || defined(__STDC__)
const short yyrindex[] =
#else
short yyrindex[] =
#endif
- { 75,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ { 73,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 79, 0, 0, 1, 0, 0, 156, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 75, 0, 0, 1, 0, 0, 156, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 181, 0, 0, 206, 0,
- 0, 237, 0, 0, 274, 0, 0, 0, 0, 0,
- 300, 0, 0, 0, 0, 0, 0, 0, 0, 326,
- 352, 0, 0, 378, 0, 0, 430, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 181, 0, 0,
+ 206, 0, 0, 237, 0, 0, 274, 0, 0, 0,
+ 0, 0, 300, 0, 0, 0, 0, 0, 0, 0,
+ 0, 326, 352, 378, 0, 0, 430, 0, 0, 0,
0, 0, 0, 0, 0, 0, 392, 0, 0, 0,
- 0, 0, 0, 0, 0, 26, 0, 52, 0, 78,
- 0, 104, 0, 0, 0, 130, 0, 0, 0, 392,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,};
+ 0, 0, 0, 0, 26, 0, 52, 0, 78, 0,
+ 104, 0, 0, 0, 130, 0, 0, 0, 39, 0,
+ 392, 0, 0, 0, 0, 0, 0, 0, 40, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 41, 0,};
#if defined(__cplusplus) || defined(__STDC__)
const short yygindex[] =
#else
short yygindex[] =
#endif
{ 0,
- -40, 0, 12, -7, 37, -84, -9, 48, -2, 13,
- 8, 15, -90, 0, 46, 76, -5, -3, 0, 0,
- 0, 72, 0, 0, 0, 0, 9, 14, 2, 16,
+ -28, 0, 17, 12, 44, -74, 8, 55, -2, 19,
+ 31, 76, -5, -39, -22, -25, 0, 0, 11, 0,
+ 0, 0, 74, 0, 0, 0, 0, 18, 20, 15,
+ 22,
};
-#define YYTABLESIZE 736
+#define YYTABLESIZE 733
#if defined(__cplusplus) || defined(__STDC__)
const short yytable[] =
#else
short yytable[] =
#endif
{ 17,
- 19, 105, 38, 112, 36, 122, 24, 55, 83, 26,
- 58, 26, 79, 48, 49, 51, 74, 61, 75, 64,
- 79, 26, 68, 119, 26, 62, 26, 76, 80, 97,
- 81, 50, 83, 19, 73, 86, 130, 2, 84, 77,
- 3, 4, 5, 89, 19, 29, 87, 30, 31, 99,
- 32, 67, 39, 100, 11, 40, 41, 42, 62, 88,
- 101, 91, 33, 90, 93, 92, 94, 95, 98, 43,
- 114, 79, 86, 68, 1, 83, 120, 75, 2, 123,
- 108, 78, 96, 62, 67, 106, 110, 85, 102, 82,
- 104, 103, 67, 72, 118, 0, 113, 107, 0, 0,
- 0, 0, 0, 72, 109, 0, 0, 0, 111, 67,
- 75, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 19, 94, 38, 39, 36, 66, 24, 67, 47, 26,
+ 50, 26, 40, 41, 2, 43, 53, 3, 4, 5,
+ 71, 26, 60, 65, 26, 56, 56, 69, 71, 116,
+ 42, 11, 76, 19, 60, 113, 29, 129, 30, 31,
+ 114, 32, 68, 89, 19, 87, 78, 72, 120, 73,
+ 74, 61, 115, 33, 80, 90, 79, 77, 56, 81,
+ 91, 83, 103, 82, 85, 84, 88, 71, 76, 121,
+ 60, 111, 1, 131, 2, 95, 99, 69, 101, 41,
+ 43, 42, 122, 56, 61, 92, 75, 97, 70, 93,
+ 86, 133, 59, 130, 132, 64, 96, 109, 107, 102,
+ 98, 0, 0, 66, 100, 0, 0, 0, 0, 61,
+ 69, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 26,
- 0, 0, 0, 0, 0, 75, 72, 0, 0, 0,
+ 0, 0, 0, 0, 0, 69, 66, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 12, 0, 0, 0, 0,
- 0, 72, 26, 0, 0, 0, 0, 0, 0, 0,
+ 0, 66, 26, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 34, 0, 0, 0, 0, 0, 0,
- 9, 0, 0, 0, 68, 0, 0, 26, 12, 0,
+ 9, 0, 0, 0, 60, 0, 0, 26, 12, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 10, 0, 0, 0, 0,
0, 0, 0, 9, 0, 0, 0, 0, 0, 0,
0, 0, 1, 0, 2, 0, 0, 3, 4, 5,
- 6, 7, 8, 9, 10, 25, 8, 25, 10, 48,
- 49, 11, 12, 13, 14, 15, 16, 25, 0, 34,
- 25, 0, 25, 0, 0, 0, 19, 50, 19, 0,
+ 6, 7, 8, 9, 10, 25, 8, 25, 10, 40,
+ 41, 11, 12, 13, 14, 15, 16, 25, 0, 17,
+ 25, 0, 0, 0, 113, 0, 19, 42, 19, 114,
0, 19, 19, 19, 19, 19, 19, 19, 19, 8,
- 0, 0, 0, 11, 0, 19, 19, 19, 19, 19,
- 19, 62, 51, 62, 0, 0, 62, 62, 62, 62,
- 62, 62, 62, 62, 0, 0, 0, 0, 0, 7,
- 62, 62, 62, 62, 62, 62, 11, 67, 0, 67,
- 0, 0, 67, 67, 67, 67, 67, 67, 67, 67,
- 0, 0, 0, 0, 0, 15, 67, 67, 67, 67,
- 67, 67, 7, 75, 0, 75, 0, 0, 75, 75,
- 75, 75, 75, 75, 75, 75, 0, 0, 0, 0,
- 0, 13, 75, 75, 75, 75, 75, 75, 15, 72,
- 0, 72, 0, 0, 72, 72, 72, 72, 72, 72,
- 72, 72, 0, 0, 0, 0, 0, 14, 72, 72,
- 72, 72, 72, 72, 13, 26, 0, 26, 0, 0,
+ 0, 115, 0, 11, 108, 19, 19, 19, 19, 19,
+ 19, 56, 43, 56, 0, 0, 56, 56, 56, 56,
+ 56, 56, 56, 56, 0, 0, 0, 0, 0, 7,
+ 56, 56, 56, 56, 56, 56, 11, 61, 0, 61,
+ 0, 0, 61, 61, 61, 61, 61, 61, 61, 61,
+ 0, 0, 0, 0, 0, 15, 61, 61, 61, 61,
+ 61, 61, 7, 69, 0, 69, 0, 0, 69, 69,
+ 69, 69, 69, 69, 69, 69, 0, 0, 0, 0,
+ 0, 13, 69, 69, 69, 69, 69, 69, 15, 66,
+ 0, 66, 0, 0, 66, 66, 66, 66, 66, 66,
+ 66, 66, 0, 0, 0, 0, 0, 14, 66, 66,
+ 66, 66, 66, 66, 13, 26, 0, 26, 0, 0,
26, 26, 26, 26, 26, 26, 26, 26, 29, 0,
30, 31, 0, 32, 26, 26, 26, 26, 26, 26,
14, 12, 0, 12, 0, 33, 12, 12, 12, 12,
0, 9, 9, 9, 9, 9, 9, 9, 9, 0,
0, 0, 0, 0, 0, 9, 9, 9, 9, 9,
9, 10, 16, 10, 0, 0, 10, 10, 10, 10,
- 10, 10, 10, 10, 29, 0, 30, 31, 0, 32,
- 10, 10, 10, 10, 10, 10, 17, 0, 0, 0,
- 0, 33, 8, 44, 8, 0, 0, 8, 8, 8,
- 8, 8, 8, 8, 8, 0, 48, 49, 0, 0,
- 0, 8, 8, 8, 8, 8, 8, 0, 124, 125,
- 126, 127, 128, 129, 50, 0, 0, 0, 0, 11,
+ 10, 10, 10, 10, 2, 0, 0, 3, 4, 5,
+ 10, 10, 10, 10, 10, 10, 34, 0, 0, 0,
+ 17, 11, 8, 0, 8, 0, 0, 8, 8, 8,
+ 8, 8, 8, 8, 8, 0, 40, 41, 0, 0,
+ 0, 8, 8, 8, 8, 8, 8, 0, 123, 124,
+ 125, 126, 127, 128, 42, 0, 0, 0, 0, 11,
0, 11, 0, 0, 11, 11, 11, 11, 11, 11,
11, 11, 0, 0, 0, 0, 0, 0, 11, 11,
11, 11, 11, 11, 0, 7, 0, 7, 0, 0,
0, 0, 0, 0, 0, 16, 0, 16, 0, 0,
16, 16, 16, 16, 16, 16, 16, 16, 0, 0,
0, 0, 0, 0, 16, 16, 16, 16, 16, 16,
- 0, 2, 0, 0, 3, 4, 5, 0, 39, 0,
- 0, 40, 41, 42, 0, 0, 0, 0, 11, 0,
- 0, 0, 0, 0, 0, 43,
+ 0, 29, 0, 30, 31, 2, 32, 0, 3, 4,
+ 5, 0, 0, 0, 0, 0, 0, 0, 33, 0,
+ 0, 0, 11,
};
#if defined(__cplusplus) || defined(__STDC__)
const short yycheck[] =
short yycheck[] =
#endif
{ 33,
- 0, 86, 8, 94, 7, 41, 276, 258, 44, 33,
- 258, 33, 44, 257, 258, 33, 43, 258, 45, 258,
- 44, 33, 44, 114, 33, 0, 33, 259, 36, 61,
- 38, 275, 44, 33, 61, 44, 121, 258, 46, 44,
- 261, 262, 263, 58, 44, 258, 54, 260, 261, 263,
- 263, 0, 258, 263, 275, 261, 262, 263, 33, 61,
- 263, 58, 275, 61, 58, 61, 61, 58, 58, 275,
- 40, 44, 44, 44, 0, 44, 44, 0, 0, 120,
- 90, 34, 68, 58, 33, 88, 92, 51, 77, 44,
- 83, 79, 17, 22, 98, -1, 95, 89, -1, -1,
- -1, -1, -1, 0, 91, -1, -1, -1, 93, 58,
+ 0, 76, 8, 9, 7, 43, 276, 45, 258, 33,
+ 258, 33, 257, 258, 258, 33, 258, 261, 262, 263,
+ 44, 33, 44, 61, 33, 0, 258, 44, 44, 33,
+ 275, 275, 44, 33, 44, 258, 258, 112, 260, 261,
+ 263, 263, 259, 263, 44, 61, 61, 36, 58, 38,
+ 39, 0, 275, 275, 61, 263, 58, 46, 33, 58,
+ 263, 58, 40, 61, 58, 61, 58, 44, 44, 41,
+ 44, 44, 0, 44, 0, 78, 82, 0, 84, 41,
+ 41, 41, 111, 58, 33, 69, 43, 80, 34, 71,
+ 60, 131, 17, 116, 120, 22, 79, 103, 88, 85,
+ 81, -1, -1, 0, 83, -1, -1, -1, -1, 58,
33, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, 0,
-1, -1, -1, -1, -1, 58, 33, -1, -1, -1,
-1, -1, 256, -1, 258, -1, -1, 261, 262, 263,
264, 265, 266, 267, 268, 259, 0, 259, 33, 257,
258, 275, 276, 277, 278, 279, 280, 259, -1, 33,
- 259, -1, 259, -1, -1, -1, 256, 275, 258, -1,
+ 259, -1, -1, -1, 258, -1, 256, 275, 258, 263,
-1, 261, 262, 263, 264, 265, 266, 267, 268, 33,
- -1, -1, -1, 0, -1, 275, 276, 277, 278, 279,
+ -1, 275, -1, 0, 58, 275, 276, 277, 278, 279,
280, 256, 33, 258, -1, -1, 261, 262, 263, 264,
265, 266, 267, 268, -1, -1, -1, -1, -1, 0,
275, 276, 277, 278, 279, 280, 33, 256, -1, 258,
-1, 261, 262, 263, 264, 265, 266, 267, 268, -1,
-1, -1, -1, -1, -1, 275, 276, 277, 278, 279,
280, 256, 33, 258, -1, -1, 261, 262, 263, 264,
- 265, 266, 267, 268, 258, -1, 260, 261, -1, 263,
+ 265, 266, 267, 268, 258, -1, -1, 261, 262, 263,
275, 276, 277, 278, 279, 280, 33, -1, -1, -1,
- -1, 275, 256, 33, 258, -1, -1, 261, 262, 263,
+ 33, 275, 256, -1, 258, -1, -1, 261, 262, 263,
264, 265, 266, 267, 268, -1, 257, 258, -1, -1,
-1, 275, 276, 277, 278, 279, 280, -1, 269, 270,
271, 272, 273, 274, 275, -1, -1, -1, -1, 256,
-1, -1, -1, -1, -1, 256, -1, 258, -1, -1,
261, 262, 263, 264, 265, 266, 267, 268, -1, -1,
-1, -1, -1, -1, 275, 276, 277, 278, 279, 280,
- -1, 258, -1, -1, 261, 262, 263, -1, 258, -1,
- -1, 261, 262, 263, -1, -1, -1, -1, 275, -1,
- -1, -1, -1, -1, -1, 275,
+ -1, 258, -1, 260, 261, 258, 263, -1, 261, 262,
+ 263, -1, -1, -1, -1, -1, -1, -1, 275, -1,
+ -1, -1, 275,
};
#define YYFINAL 18
#ifndef YYDEBUG
"entry : RUNASALIAS runasaliases",
"entry : DEFAULTS defaults_list",
"entry : DEFAULTS_USER userlist defaults_list",
-"entry : DEFAULTS_RUNAS runaslist defaults_list",
+"entry : DEFAULTS_RUNAS userlist defaults_list",
"entry : DEFAULTS_HOST hostlist defaults_list",
"entry : DEFAULTS_CMND cmndlist defaults_list",
"defaults_list : defaults_entry",
"opcmnd : '!' cmnd",
"runasspec :",
"runasspec : '(' runaslist ')'",
-"runaslist : oprunasuser",
-"runaslist : runaslist ',' oprunasuser",
-"oprunasuser : runasuser",
-"oprunasuser : '!' runasuser",
-"runasuser : ALIAS",
-"runasuser : ALL",
-"runasuser : NETGROUP",
-"runasuser : USERGROUP",
-"runasuser : WORD",
+"runaslist : userlist",
+"runaslist : userlist ':' grouplist",
+"runaslist : ':' grouplist",
"cmndtag :",
"cmndtag : cmndtag NOPASSWD",
"cmndtag : cmndtag PASSWD",
"cmndlist : cmndlist ',' opcmnd",
"runasaliases : runasalias",
"runasaliases : runasaliases ':' runasalias",
-"runasalias : ALIAS '=' runaslist",
+"runasalias : ALIAS '=' userlist",
"useraliases : useralias",
"useraliases : useraliases ':' useralias",
"useralias : ALIAS '=' userlist",
"user : NETGROUP",
"user : USERGROUP",
"user : WORD",
+"grouplist : opgroup",
+"grouplist : grouplist ',' opgroup",
+"opgroup : group",
+"opgroup : '!' group",
+"group : ALIAS",
+"group : ALL",
+"group : WORD",
};
#endif
#ifdef YYSTACKSIZE
short *yysslim;
YYSTYPE *yyvs;
int yystacksize;
-#line 503 "./gram.y"
+#line 527 "gram.y"
static struct defaults *
new_default(var, val, op)
char *var;
int quiet;
{
struct defaults *d;
- struct member *m, *freed;
+ struct member *m, *binding;
struct userspec *us;
struct privilege *priv;
struct cmndspec *cs;
efree(m);
}
while ((priv = tq_pop(&us->privileges)) != NULL) {
+ struct member *runasuser = NULL, *runasgroup = NULL;
+
while ((m = tq_pop(&priv->hostlist)) != NULL) {
efree(m->name);
efree(m);
}
- freed = NULL;
while ((cs = tq_pop(&priv->cmndlist)) != NULL) {
- if (tq_last(&cs->runaslist) != freed) {
- freed = tq_last(&cs->runaslist);
- while ((m = tq_pop(&cs->runaslist)) != NULL) {
+ if (tq_last(&cs->runasuserlist) != runasuser) {
+ runasuser = tq_last(&cs->runasuserlist);
+ while ((m = tq_pop(&cs->runasuserlist)) != NULL) {
+ efree(m->name);
+ efree(m);
+ }
+ }
+ if (tq_last(&cs->runasgrouplist) != runasgroup) {
+ runasgroup = tq_last(&cs->runasgrouplist);
+ while ((m = tq_pop(&cs->runasgrouplist)) != NULL) {
efree(m->name);
efree(m);
}
}
tq_init(&userspecs);
- freed = NULL;
+ binding = NULL;
while ((d = tq_pop(&defaults)) != NULL) {
- if (tq_last(&d->binding) != freed) {
- freed = tq_last(&d->binding);
+ if (tq_last(&d->binding) != binding) {
+ binding = tq_last(&d->binding);
while ((m = tq_pop(&d->binding)) != NULL) {
efree(m->name);
efree(m);
sudolineno = 1;
verbose = !quiet;
}
-#line 670 "y.tab.c"
+#line 685 "y.tab.c"
/* allocate initial stack or double stack size, up to YYMAXDEPTH */
#if defined(__cplusplus) || defined(__STDC__)
static int yygrowstack(void)
switch (yyn)
{
case 1:
-#line 166 "./gram.y"
+#line 168 "gram.y"
{ ; }
break;
case 5:
-#line 174 "./gram.y"
+#line 176 "gram.y"
{
;
}
break;
case 6:
-#line 177 "./gram.y"
+#line 179 "gram.y"
{
yyerrok;
}
break;
case 7:
-#line 180 "./gram.y"
+#line 182 "gram.y"
{
add_userspec(yyvsp[-1].member, yyvsp[0].privilege);
}
break;
case 8:
-#line 183 "./gram.y"
+#line 185 "gram.y"
{
;
}
break;
case 9:
-#line 186 "./gram.y"
+#line 188 "gram.y"
{
;
}
break;
case 10:
-#line 189 "./gram.y"
+#line 191 "gram.y"
{
;
}
break;
case 11:
-#line 192 "./gram.y"
+#line 194 "gram.y"
{
;
}
break;
case 12:
-#line 195 "./gram.y"
+#line 197 "gram.y"
{
add_defaults(DEFAULTS, NULL, yyvsp[0].defaults);
}
break;
case 13:
-#line 198 "./gram.y"
+#line 200 "gram.y"
{
add_defaults(DEFAULTS_USER, yyvsp[-1].member, yyvsp[0].defaults);
}
break;
case 14:
-#line 201 "./gram.y"
+#line 203 "gram.y"
{
add_defaults(DEFAULTS_RUNAS, yyvsp[-1].member, yyvsp[0].defaults);
}
break;
case 15:
-#line 204 "./gram.y"
+#line 206 "gram.y"
{
add_defaults(DEFAULTS_HOST, yyvsp[-1].member, yyvsp[0].defaults);
}
break;
case 16:
-#line 207 "./gram.y"
+#line 209 "gram.y"
{
add_defaults(DEFAULTS_CMND, yyvsp[-1].member, yyvsp[0].defaults);
}
break;
case 18:
-#line 213 "./gram.y"
+#line 215 "gram.y"
{
list_append(yyvsp[-2].defaults, yyvsp[0].defaults);
yyval.defaults = yyvsp[-2].defaults;
}
break;
case 19:
-#line 219 "./gram.y"
+#line 221 "gram.y"
{
yyval.defaults = new_default(yyvsp[0].string, NULL, TRUE);
}
break;
case 20:
-#line 222 "./gram.y"
+#line 224 "gram.y"
{
yyval.defaults = new_default(yyvsp[0].string, NULL, FALSE);
}
break;
case 21:
-#line 225 "./gram.y"
+#line 227 "gram.y"
{
yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, TRUE);
}
break;
case 22:
-#line 228 "./gram.y"
+#line 230 "gram.y"
{
yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, '+');
}
break;
case 23:
-#line 231 "./gram.y"
+#line 233 "gram.y"
{
yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, '-');
}
break;
case 25:
-#line 237 "./gram.y"
+#line 239 "gram.y"
{
list_append(yyvsp[-2].privilege, yyvsp[0].privilege);
yyval.privilege = yyvsp[-2].privilege;
}
break;
case 26:
-#line 243 "./gram.y"
+#line 245 "gram.y"
{
struct privilege *p = emalloc(sizeof(*p));
list2tq(&p->hostlist, yyvsp[-2].member);
}
break;
case 27:
-#line 253 "./gram.y"
+#line 255 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = FALSE;
}
break;
case 28:
-#line 257 "./gram.y"
+#line 259 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = TRUE;
}
break;
case 29:
-#line 263 "./gram.y"
+#line 265 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, ALIAS);
}
break;
case 30:
-#line 266 "./gram.y"
+#line 268 "gram.y"
{
yyval.member = new_member(NULL, ALL);
}
break;
case 31:
-#line 269 "./gram.y"
+#line 271 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, NETGROUP);
}
break;
case 32:
-#line 272 "./gram.y"
+#line 274 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, NTWKADDR);
}
break;
case 33:
-#line 275 "./gram.y"
+#line 277 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, WORD);
}
break;
case 35:
-#line 281 "./gram.y"
+#line 283 "gram.y"
{
list_append(yyvsp[-2].cmndspec, yyvsp[0].cmndspec);
/* propagate tags and runas list */
if (yyvsp[0].cmndspec->tags.setenv == UNSPEC &&
yyvsp[0].cmndspec->prev->tags.setenv != IMPLIED)
yyvsp[0].cmndspec->tags.setenv = yyvsp[0].cmndspec->prev->tags.setenv;
- if (tq_empty(&yyvsp[0].cmndspec->runaslist) &&
- !tq_empty(&yyvsp[0].cmndspec->prev->runaslist))
- yyvsp[0].cmndspec->runaslist = yyvsp[0].cmndspec->prev->runaslist;
+ if ((tq_empty(&yyvsp[0].cmndspec->runasuserlist) &&
+ tq_empty(&yyvsp[0].cmndspec->runasgrouplist)) &&
+ (!tq_empty(&yyvsp[0].cmndspec->prev->runasuserlist) ||
+ !tq_empty(&yyvsp[0].cmndspec->prev->runasgrouplist))) {
+ yyvsp[0].cmndspec->runasuserlist = yyvsp[0].cmndspec->prev->runasuserlist;
+ yyvsp[0].cmndspec->runasgrouplist = yyvsp[0].cmndspec->prev->runasgrouplist;
+ }
yyval.cmndspec = yyvsp[-2].cmndspec;
}
break;
case 36:
-#line 298 "./gram.y"
+#line 304 "gram.y"
{
struct cmndspec *cs = emalloc(sizeof(*cs));
- list2tq(&cs->runaslist, yyvsp[-2].member);
+ if (yyvsp[-2].runas != NULL) {
+ list2tq(&cs->runasuserlist, yyvsp[-2].runas->runasusers);
+ list2tq(&cs->runasgrouplist, yyvsp[-2].runas->runasgroups);
+ efree(yyvsp[-2].runas);
+ } else {
+ tq_init(&cs->runasuserlist);
+ tq_init(&cs->runasgrouplist);
+ }
cs->tags = yyvsp[-1].tag;
cs->cmnd = yyvsp[0].member;
cs->prev = cs;
}
break;
case 37:
-#line 313 "./gram.y"
+#line 326 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = FALSE;
}
break;
case 38:
-#line 317 "./gram.y"
+#line 330 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = TRUE;
}
break;
case 39:
-#line 323 "./gram.y"
+#line 336 "gram.y"
{
- yyval.member = NULL;
+ yyval.runas = NULL;
}
break;
case 40:
-#line 326 "./gram.y"
-{
- yyval.member = yyvsp[-1].member;
- }
-break;
-case 42:
-#line 332 "./gram.y"
+#line 339 "gram.y"
{
- list_append(yyvsp[-2].member, yyvsp[0].member);
- yyval.member = yyvsp[-2].member;
- }
-break;
-case 43:
-#line 338 "./gram.y"
-{
- yyval.member = yyvsp[0].member;
- yyval.member->negated = FALSE;
+ yyval.runas = yyvsp[-1].runas;
}
break;
-case 44:
-#line 342 "./gram.y"
+case 41:
+#line 344 "gram.y"
{
- yyval.member = yyvsp[0].member;
- yyval.member->negated = TRUE;
+ yyval.runas = emalloc(sizeof(struct runascontainer));
+ yyval.runas->runasusers = yyvsp[0].member;
+ yyval.runas->runasgroups = NULL;
}
break;
-case 45:
-#line 348 "./gram.y"
-{
- yyval.member = new_member(yyvsp[0].string, ALIAS);
- }
-break;
-case 46:
-#line 351 "./gram.y"
-{
- yyval.member = new_member(NULL, ALL);
- }
-break;
-case 47:
-#line 354 "./gram.y"
+case 42:
+#line 349 "gram.y"
{
- yyval.member = new_member(yyvsp[0].string, NETGROUP);
+ yyval.runas = emalloc(sizeof(struct runascontainer));
+ yyval.runas->runasusers = yyvsp[-2].member;
+ yyval.runas->runasgroups = yyvsp[0].member;
}
break;
-case 48:
-#line 357 "./gram.y"
-{
- yyval.member = new_member(yyvsp[0].string, USERGROUP);
- }
-break;
-case 49:
-#line 360 "./gram.y"
+case 43:
+#line 354 "gram.y"
{
- yyval.member = new_member(yyvsp[0].string, WORD);
+ yyval.runas = emalloc(sizeof(struct runascontainer));
+ yyval.runas->runasusers = NULL;
+ yyval.runas->runasgroups = yyvsp[0].member;
}
break;
-case 50:
-#line 365 "./gram.y"
+case 44:
+#line 361 "gram.y"
{
yyval.tag.nopasswd = yyval.tag.noexec = yyval.tag.setenv = UNSPEC;
}
break;
-case 51:
-#line 368 "./gram.y"
+case 45:
+#line 364 "gram.y"
{
yyval.tag.nopasswd = TRUE;
}
break;
-case 52:
-#line 371 "./gram.y"
+case 46:
+#line 367 "gram.y"
{
yyval.tag.nopasswd = FALSE;
}
break;
-case 53:
-#line 374 "./gram.y"
+case 47:
+#line 370 "gram.y"
{
yyval.tag.noexec = TRUE;
}
break;
-case 54:
-#line 377 "./gram.y"
+case 48:
+#line 373 "gram.y"
{
yyval.tag.noexec = FALSE;
}
break;
-case 55:
-#line 380 "./gram.y"
+case 49:
+#line 376 "gram.y"
{
yyval.tag.setenv = TRUE;
}
break;
-case 56:
-#line 383 "./gram.y"
+case 50:
+#line 379 "gram.y"
{
yyval.tag.setenv = FALSE;
}
break;
-case 57:
-#line 388 "./gram.y"
+case 51:
+#line 384 "gram.y"
{
yyval.member = new_member(NULL, ALL);
}
break;
-case 58:
-#line 391 "./gram.y"
+case 52:
+#line 387 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, ALIAS);
}
break;
-case 59:
-#line 394 "./gram.y"
+case 53:
+#line 390 "gram.y"
{
struct sudo_command *c = emalloc(sizeof(*c));
c->cmnd = yyvsp[0].command.cmnd;
yyval.member = new_member((char *)c, COMMAND);
}
break;
-case 62:
-#line 406 "./gram.y"
+case 56:
+#line 402 "gram.y"
{
char *s;
if ((s = alias_add(yyvsp[-2].string, HOSTALIAS, yyvsp[0].member)) != NULL) {
}
}
break;
-case 64:
-#line 416 "./gram.y"
+case 58:
+#line 412 "gram.y"
{
list_append(yyvsp[-2].member, yyvsp[0].member);
yyval.member = yyvsp[-2].member;
}
break;
-case 67:
-#line 426 "./gram.y"
+case 61:
+#line 422 "gram.y"
{
char *s;
if ((s = alias_add(yyvsp[-2].string, CMNDALIAS, yyvsp[0].member)) != NULL) {
}
}
break;
-case 69:
-#line 436 "./gram.y"
+case 63:
+#line 432 "gram.y"
{
list_append(yyvsp[-2].member, yyvsp[0].member);
yyval.member = yyvsp[-2].member;
}
break;
-case 72:
-#line 446 "./gram.y"
+case 66:
+#line 442 "gram.y"
{
char *s;
if ((s = alias_add(yyvsp[-2].string, RUNASALIAS, yyvsp[0].member)) != NULL) {
}
}
break;
-case 75:
-#line 459 "./gram.y"
+case 69:
+#line 455 "gram.y"
{
char *s;
if ((s = alias_add(yyvsp[-2].string, USERALIAS, yyvsp[0].member)) != NULL) {
}
}
break;
-case 77:
-#line 469 "./gram.y"
+case 71:
+#line 465 "gram.y"
{
list_append(yyvsp[-2].member, yyvsp[0].member);
yyval.member = yyvsp[-2].member;
}
break;
-case 78:
-#line 475 "./gram.y"
+case 72:
+#line 471 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = FALSE;
}
break;
-case 79:
-#line 479 "./gram.y"
+case 73:
+#line 475 "gram.y"
{
yyval.member = yyvsp[0].member;
yyval.member->negated = TRUE;
}
break;
-case 80:
-#line 485 "./gram.y"
+case 74:
+#line 481 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, ALIAS);
}
break;
-case 81:
-#line 488 "./gram.y"
+case 75:
+#line 484 "gram.y"
{
yyval.member = new_member(NULL, ALL);
}
break;
-case 82:
-#line 491 "./gram.y"
+case 76:
+#line 487 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, NETGROUP);
}
break;
-case 83:
-#line 494 "./gram.y"
+case 77:
+#line 490 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, USERGROUP);
}
break;
+case 78:
+#line 493 "gram.y"
+{
+ yyval.member = new_member(yyvsp[0].string, WORD);
+ }
+break;
+case 80:
+#line 499 "gram.y"
+{
+ list_append(yyvsp[-2].member, yyvsp[0].member);
+ yyval.member = yyvsp[-2].member;
+ }
+break;
+case 81:
+#line 505 "gram.y"
+{
+ yyval.member = yyvsp[0].member;
+ yyval.member->negated = FALSE;
+ }
+break;
+case 82:
+#line 509 "gram.y"
+{
+ yyval.member = yyvsp[0].member;
+ yyval.member->negated = TRUE;
+ }
+break;
+case 83:
+#line 515 "gram.y"
+{
+ yyval.member = new_member(yyvsp[0].string, ALIAS);
+ }
+break;
case 84:
-#line 497 "./gram.y"
+#line 518 "gram.y"
+{
+ yyval.member = new_member(NULL, ALL);
+ }
+break;
+case 85:
+#line 521 "gram.y"
{
yyval.member = new_member(yyvsp[0].string, WORD);
}
break;
-#line 1326 "y.tab.c"
+#line 1364 "y.tab.c"
}
yyssp -= yym;
yystate = *yyssp;
struct cmndspec *cmndspec;
struct defaults *defaults;
struct member *member;
+ struct runascontainer *runas;
struct privilege *privilege;
struct sudo_command command;
struct cmndtag tag;
struct cmndspec *cmndspec;
struct defaults *defaults;
struct member *member;
+ struct runascontainer *runas;
struct privilege *privilege;
struct sudo_command command;
struct cmndtag tag;
%type <member> host
%type <member> hostlist
%type <member> ophost
-%type <member> oprunasuser
%type <member> opuser
-%type <member> runaslist
-%type <member> runasspec
-%type <member> runasuser
%type <member> user
%type <member> userlist
+%type <member> opgroup
+%type <member> group
+%type <member> grouplist
+%type <runas> runasspec
+%type <runas> runaslist
%type <privilege> privilege
%type <privilege> privileges
%type <tag> cmndtag
| DEFAULTS_USER userlist defaults_list {
add_defaults(DEFAULTS_USER, $2, $3);
}
- | DEFAULTS_RUNAS runaslist defaults_list {
+ | DEFAULTS_RUNAS userlist defaults_list {
add_defaults(DEFAULTS_RUNAS, $2, $3);
}
| DEFAULTS_HOST hostlist defaults_list {
if ($3->tags.setenv == UNSPEC &&
$3->prev->tags.setenv != IMPLIED)
$3->tags.setenv = $3->prev->tags.setenv;
- if (tq_empty(&$3->runaslist) &&
- !tq_empty(&$3->prev->runaslist))
- $3->runaslist = $3->prev->runaslist;
+ if ((tq_empty(&$3->runasuserlist) &&
+ tq_empty(&$3->runasgrouplist)) &&
+ (!tq_empty(&$3->prev->runasuserlist) ||
+ !tq_empty(&$3->prev->runasgrouplist))) {
+ $3->runasuserlist = $3->prev->runasuserlist;
+ $3->runasgrouplist = $3->prev->runasgrouplist;
+ }
$$ = $1;
}
;
cmndspec : runasspec cmndtag opcmnd {
struct cmndspec *cs = emalloc(sizeof(*cs));
- list2tq(&cs->runaslist, $1);
+ if ($1 != NULL) {
+ list2tq(&cs->runasuserlist, $1->runasusers);
+ list2tq(&cs->runasgrouplist, $1->runasgroups);
+ efree($1);
+ } else {
+ tq_init(&cs->runasuserlist);
+ tq_init(&cs->runasgrouplist);
+ }
cs->tags = $2;
cs->cmnd = $3;
cs->prev = cs;
}
;
-runaslist : oprunasuser
- | runaslist ',' oprunasuser {
- list_append($1, $3);
- $$ = $1;
+runaslist : userlist {
+ $$ = emalloc(sizeof(struct runascontainer));
+ $$->runasusers = $1;
+ $$->runasgroups = NULL;
}
- ;
-
-oprunasuser : runasuser {
- $$ = $1;
- $$->negated = FALSE;
+ | userlist ':' grouplist {
+ $$ = emalloc(sizeof(struct runascontainer));
+ $$->runasusers = $1;
+ $$->runasgroups = $3;
}
- | '!' runasuser {
- $$ = $2;
- $$->negated = TRUE;
- }
- ;
-
-runasuser : ALIAS {
- $$ = new_member($1, ALIAS);
- }
- | ALL {
- $$ = new_member(NULL, ALL);
- }
- | NETGROUP {
- $$ = new_member($1, NETGROUP);
- }
- | USERGROUP {
- $$ = new_member($1, USERGROUP);
- }
- | WORD {
- $$ = new_member($1, WORD);
+ | ':' grouplist {
+ $$ = emalloc(sizeof(struct runascontainer));
+ $$->runasusers = NULL;
+ $$->runasgroups = $2;
}
;
| runasaliases ':' runasalias
;
-runasalias : ALIAS '=' runaslist {
+runasalias : ALIAS '=' userlist {
char *s;
if ((s = alias_add($1, RUNASALIAS, $3)) != NULL) {
yyerror(s);
}
;
+grouplist : opgroup
+ | grouplist ',' opgroup {
+ list_append($1, $3);
+ $$ = $1;
+ }
+ ;
+
+opgroup : group {
+ $$ = $1;
+ $$->negated = FALSE;
+ }
+ | '!' group {
+ $$ = $2;
+ $$->negated = TRUE;
+ }
+ ;
+
+group : ALIAS {
+ $$ = new_member($1, ALIAS);
+ }
+ | ALL {
+ $$ = new_member(NULL, ALL);
+ }
+ | WORD {
+ $$ = new_member($1, WORD);
+ }
+ ;
+
%%
static struct defaults *
new_default(var, val, op)
int quiet;
{
struct defaults *d;
- struct member *m, *freed;
+ struct member *m, *binding;
struct userspec *us;
struct privilege *priv;
struct cmndspec *cs;
efree(m);
}
while ((priv = tq_pop(&us->privileges)) != NULL) {
+ struct member *runasuser = NULL, *runasgroup = NULL;
+
while ((m = tq_pop(&priv->hostlist)) != NULL) {
efree(m->name);
efree(m);
}
- freed = NULL;
while ((cs = tq_pop(&priv->cmndlist)) != NULL) {
- if (tq_last(&cs->runaslist) != freed) {
- freed = tq_last(&cs->runaslist);
- while ((m = tq_pop(&cs->runaslist)) != NULL) {
+ if (tq_last(&cs->runasuserlist) != runasuser) {
+ runasuser = tq_last(&cs->runasuserlist);
+ while ((m = tq_pop(&cs->runasuserlist)) != NULL) {
+ efree(m->name);
+ efree(m);
+ }
+ }
+ if (tq_last(&cs->runasgrouplist) != runasgroup) {
+ runasgroup = tq_last(&cs->runasgrouplist);
+ while ((m = tq_pop(&cs->runasgrouplist)) != NULL) {
efree(m->name);
efree(m);
}
}
tq_init(&userspecs);
- freed = NULL;
+ binding = NULL;
while ((d = tq_pop(&defaults)) != NULL) {
- if (tq_last(&d->binding) != freed) {
- freed = tq_last(&d->binding);
+ if (tq_last(&d->binding) != binding) {
+ binding = tq_last(&d->binding);
while ((m = tq_pop(&d->binding)) != NULL) {
efree(m->name);
efree(m);
if (!entry)
return(ret);
+ /* If no runas user, just check the group. */
+ /* XXX - implement runas group checking via sudoRunasGroup */
+ if (!runas_pw)
+ return(TRUE);
+
/* get the values from the entry */
v = ldap_get_values(ld, entry, "sudoRunAs");
user_name, user_shost);
else
(void) fprintf(stderr,
- "Sorry, user %s is not allowed to execute '%s%s%s' as %s on %s.\n",
+ "Sorry, user %s is not allowed to execute '%s%s%s' as %s%s%s on %s.\n",
user_name, user_cmnd, user_args ? " " : "",
user_args ? user_args : "",
- list_pw ? list_pw->pw_name : *user_runas, user_host);
+ list_pw ? list_pw->pw_name : runas_pw ?
+ runas_pw->pw_name : user_name, runas_gr ? ":" : "",
+ runas_gr ? runas_gr->gr_name : "", user_host);
}
/*
}
len += sizeof(LL_TTY_STR) + 2 + strlen(user_tty);
len += sizeof(LL_CWD_STR) + 2 + strlen(user_cwd);
- len += sizeof(LL_USER_STR) + 2 + strlen(*user_runas);
+ if (runas_pw != NULL)
+ len += sizeof(LL_USER_STR) + 2 + strlen(runas_pw->pw_name);
+ if (runas_gr != NULL)
+ len += sizeof(LL_GROUP_STR) + 2 + strlen(runas_gr->gr_name);
if (sudo_user.env_vars != NULL) {
size_t evlen = 0;
struct list_member *cur;
strlcat(line, user_cwd, len) >= len ||
strlcat(line, " ; ", len) >= len)
goto toobig;
- if (strlcat(line, LL_USER_STR, len) >= len ||
- strlcat(line, *user_runas, len) >= len ||
- strlcat(line, " ; ", len) >= len)
- goto toobig;
+ if (runas_pw != NULL) {
+ if (strlcat(line, LL_USER_STR, len) >= len ||
+ strlcat(line, runas_pw->pw_name, len) >= len ||
+ strlcat(line, " ; ", len) >= len)
+ goto toobig;
+ }
+ if (runas_gr != NULL) {
+ if (strlcat(line, LL_GROUP_STR, len) >= len ||
+ strlcat(line, runas_gr->gr_name, len) >= len ||
+ strlcat(line, " ; ", len) >= len)
+ goto toobig;
+ }
if (evstr != NULL) {
if (strlcat(line, LL_ENV_STR, len) >= len ||
strlcat(line, evstr, len) >= len ||
__unused static const char rcsid[] = "$Sudo$";
#endif /* lint */
+static struct member_list empty;
+
/*
* Returns TRUE if string 's' contains meta characters.
*/
/*
* Check for user described by pw in a list of members.
- * If list is NULL compare against def_runas_default.
+ * If both lists are empty compare against def_runas_default.
* Returns ALLOW, DENY or UNSPEC.
*/
static int
-_runaslist_matches(list)
- struct member_list *list;
+_runaslist_matches(user_list, group_list)
+ struct member_list *user_list;
+ struct member_list *group_list;
{
struct member *m;
struct alias *a;
int rval, matched = UNSPEC;
- if (tq_empty(list))
+ /* Deny if user specified a group but there is no group in sudoers */
+ if (runas_gr != NULL && tq_empty(group_list))
+ return(DENY);
+
+ if (tq_empty(user_list) && tq_empty(group_list))
return(userpw_matches(def_runas_default, runas_pw->pw_name, runas_pw));
- tq_foreach_rev(list, m) {
- switch (m->type) {
- case ALL:
- matched = !m->negated;
- break;
- case NETGROUP:
- if (netgr_matches(m->name, NULL, NULL, runas_pw->pw_name))
+ if (runas_pw != NULL) {
+ tq_foreach_rev(user_list, m) {
+ switch (m->type) {
+ case ALL:
matched = !m->negated;
+ break;
+ case NETGROUP:
+ if (netgr_matches(m->name, NULL, NULL, runas_pw->pw_name))
+ matched = !m->negated;
+ break;
+ case USERGROUP:
+ if (usergr_matches(m->name, runas_pw->pw_name, runas_pw))
+ matched = !m->negated;
+ break;
+ case ALIAS:
+ if ((a = find_alias(m->name, RUNASALIAS)) != NULL) {
+ rval = _runaslist_matches(&a->members, &empty);
+ if (rval != UNSPEC)
+ matched = m->negated ? !rval : rval;
+ break;
+ }
+ /* FALLTHROUGH */
+ case WORD:
+ if (userpw_matches(m->name, runas_pw->pw_name, runas_pw))
+ matched = !m->negated;
+ break;
+ }
+ if (matched != UNSPEC)
break;
- case USERGROUP:
- if (usergr_matches(m->name, runas_pw->pw_name, runas_pw))
+ }
+ }
+
+ if (runas_gr != NULL) {
+ tq_foreach_rev(group_list, m) {
+ switch (m->type) {
+ case ALL:
matched = !m->negated;
- break;
- case ALIAS:
- if ((a = find_alias(m->name, RUNASALIAS)) != NULL) {
- rval = _runaslist_matches(&a->members);
- if (rval != UNSPEC)
- matched = m->negated ? !rval : rval;
break;
- }
- /* FALLTHROUGH */
- case WORD:
- if (userpw_matches(m->name, runas_pw->pw_name, runas_pw))
- matched = !m->negated;
+ case ALIAS:
+ if ((a = find_alias(m->name, RUNASALIAS)) != NULL) {
+ rval = _runaslist_matches(&a->members, &empty);
+ if (rval != UNSPEC)
+ matched = m->negated ? !rval : rval;
+ break;
+ }
+ /* FALLTHROUGH */
+ case WORD:
+ if (group_matches(m->name, runas_gr))
+ matched = !m->negated;
+ break;
+ }
+ if (matched != UNSPEC)
break;
}
- if (matched != UNSPEC)
- break;
}
+
return(matched);
}
int
-runaslist_matches(list)
- struct member_list *list;
+runaslist_matches(user_list, group_list)
+ struct member_list *user_list;
+ struct member_list *group_list;
{
alias_seqno++;
- return(_runaslist_matches(list));
+ return(_runaslist_matches(user_list ? user_list : &empty,
+ group_list ? group_list : &empty));
}
/*
if (pw != NULL && *sudoers_user == '#') {
uid_t uid = (uid_t) atoi(sudoers_user + 1);
if (uid == pw->pw_uid)
- return(1);
+ return(TRUE);
}
return(strcmp(sudoers_user, user) == 0);
}
+/*
+ * Returns TRUE if the group/gid from sudoers matches the specified group/gid,
+ * else returns FALSE.
+ */
+int
+group_matches(sudoers_group, gr)
+ char *sudoers_group;
+ struct group *gr;
+{
+ if (*sudoers_group == '#') {
+ gid_t gid = (gid_t) atoi(sudoers_group + 1);
+ if (gid == gr->gr_gid)
+ return(TRUE);
+ }
+ return(strcmp(gr->gr_name, sudoers_group) == 0);
+}
+
/*
* Returns TRUE if the given user belongs to the named group,
* else returns FALSE.
init_defaults();
def_authenticate = FALSE;
runas_pw = info->pw;
- user_runas = &info->pw->pw_name;
validated = VALIDATE_NOT_OK;
#ifdef HAVE_LDAP
if ((ld = sudo_ldap_open()) != NULL) {
else
continue;
tq_foreach_rev(&priv->cmndlist, cs) {
- runas_match = runaslist_matches(&cs->runaslist);
+ runas_match = runaslist_matches(&cs->runasuserlist,
+ &cs->runasgrouplist);
if (runas_match == ALLOW) {
cmnd_match = cmnd_matches(cs->cmnd);
if (cmnd_match != UNSPEC) {
if (cs != tq_first(&priv->cmndlist))
lbuf_append(&lbuf, ", ", NULL);
lbuf_append(&lbuf, "(", NULL);
- if (!tq_empty(&cs->runaslist)) {
- tq_foreach_fwd(&cs->runaslist, m) {
- if (m != tq_first(&cs->runaslist))
+ if (!tq_empty(&cs->runasuserlist)) {
+ tq_foreach_fwd(&cs->runasuserlist, m) {
+ if (m != tq_first(&cs->runasuserlist))
lbuf_append(&lbuf, ", ", NULL);
print_member(&lbuf, m->name, m->type, m->negated,
RUNASALIAS);
} else {
lbuf_append(&lbuf, def_runas_default, NULL);
}
+ if (!tq_empty(&cs->runasgrouplist)) {
+ lbuf_append(&lbuf, " : ", NULL);
+ tq_foreach_fwd(&cs->runasgrouplist, m) {
+ if (m != tq_first(&cs->runasgrouplist))
+ lbuf_append(&lbuf, ", ", NULL);
+ print_member(&lbuf, m->name, m->type, m->negated,
+ RUNASALIAS);
+ }
+ }
lbuf_append(&lbuf, ") ", NULL);
if (TAG_CHANGED(setenv)) {
lbuf_append(&lbuf, cs->tags.setenv ? "SETENV: " :
if (host_match != ALLOW)
continue;
tq_foreach_rev(&priv->cmndlist, cs) {
- runas_match = runaslist_matches(&cs->runaslist);
+ runas_match = runaslist_matches(&cs->runasuserlist,
+ &cs->runasgrouplist);
if (runas_match == ALLOW) {
cmnd_match = cmnd_matches(cs->cmnd);
if (cmnd_match != UNSPEC) {
*/
struct cmndspec {
struct cmndspec *prev, *next;
- struct member_list runaslist; /* list of runas users */
+ struct member_list runasuserlist; /* list of runas users */
+ struct member_list runasgrouplist; /* list of runas groups */
struct member *cmnd; /* command to allow/deny */
struct cmndtag tags; /* tag specificaion */
};
short negated; /* negated via '!'? */
};
+struct runascontainer {
+ struct member *runasusers;
+ struct member *runasgroups;
+};
+
/*
* Generic structure to hold {User,Host,Runas,Cmnd}_Alias
* Aliases are stored in a red-black tree, sorted by name and type.
int hostname_matches __P((char *, char *, char *));
int netgr_matches __P((char *, char *, char *, char *));
int no_aliases __P((void));
-int runaslist_matches __P((struct member_list *));
+int runaslist_matches __P((struct member_list *, struct member_list *));
int userlist_matches __P((struct passwd *, struct member_list *));
int usergr_matches __P((char *, char *, struct passwd *));
int userpw_matches __P((char *, char *, struct passwd *));
+int group_matches __P((char *, struct group *));
struct alias *find_alias __P((char *, int));
void alias_apply __P((int (*)(void *, void *), void *));
void init_aliases __P((void));
return(pw);
}
+/*
+ * Take a gid in string form "#123" and return a faked up group struct.
+ */
+struct group *
+sudo_fakegrnam(group)
+ const char *group;
+{
+ struct group *gr;
+ struct rbnode *node;
+ size_t len;
+
+ len = strlen(group);
+ gr = emalloc(sizeof(struct group) + len + 1);
+ memset(gr, 0, sizeof(struct group));
+ gr->gr_gid = (gid_t) atoi(group + 1);
+ gr->gr_name = (char *)gr + sizeof(struct group);
+ strlcpy(gr->gr_name, group, len + 1);
+
+ /* Store by gid and by name, overwriting cached version. */
+ if ((node = rbinsert(grcache_bygid, gr)) != NULL) {
+ efree(node->data);
+ node->data = (void *) gr;
+ }
+ if ((node = rbinsert(grcache_byname, gr)) != NULL) {
+ efree(node->data);
+ node->data = (void *) gr;
+ }
+ return(gr);
+}
+
void
sudo_setpwent()
{
break;
case PERM_RUNAS:
- (void) setresgid(-1, runas_pw->pw_gid, -1);
- if (setresuid(-1, runas_pw->pw_uid, -1))
+ (void) setresgid(-1, runas_gr ?
+ runas_gr->gr_gid : runas_pw->pw_gid, -1);
+ if (setresuid(-1,
+ runas_pw ? runas_pw->pw_uid : user_uid, -1))
error(1, "unable to change to runas uid");
break;
break;
case PERM_RUNAS:
- (void) setregid(-1, runas_pw->pw_gid);
- if (setreuid(-1, runas_pw->pw_uid))
+ (void) setregid(-1, runas_gr ?
+ runas_gr->gr_gid : runas_pw->pw_gid);
+ if (setreuid(-1,
+ runas_pw ? runas_pw->pw_uid : user_uid))
error(1, "unable to change to runas uid");
break;
break;
case PERM_RUNAS:
- (void) setegid(runas_pw->pw_gid);
- if (seteuid(runas_pw->pw_uid))
+ (void) setegid(runas_gr ?
+ runas_gr->gr_gid : runas_pw->pw_gid);
+ if (seteuid(runas_pw ? runas_pw->pw_uid : user_uid))
error(1, "unable to change to runas uid");
break;
static void
runas_setup()
{
+ gid_t gid;
#ifdef HAVE_LOGIN_CAP_H
int flags;
extern login_cap_t *lc;
#endif
if (runas_pw->pw_name != NULL) {
+ gid = runas_gr ? runas_gr->gr_gid : runas_pw->pw_gid;
#ifdef HAVE_PAM
pam_prep_user(runas_pw);
#endif /* HAVE_PAM */
flags = LOGIN_SETRESOURCES|LOGIN_SETPRIORITY;
if (!def_preserve_groups)
SET(flags, LOGIN_SETGROUP);
- else if (setgid(runas_pw->pw_gid))
+ else if (setgid(gid))
warning("cannot set gid to runas gid");
if (setusercontext(lc, runas_pw, runas_pw->pw_uid, flags)) {
if (runas_pw->pw_uid != ROOT_UID)
} else
#endif /* HAVE_LOGIN_CAP_H */
{
- if (setgid(runas_pw->pw_gid))
+ if (setgid(gid))
warning("cannot set gid to runas gid");
#ifdef HAVE_INITGROUPS
/*
* Initialize group vector unless asked not to.
*/
if (!def_preserve_groups &&
- initgroups(*user_runas, runas_pw->pw_gid) < 0)
+ initgroups(runas_pw->pw_name, runas_pw->pw_gid) < 0)
warning("cannot set group vector");
#endif /* HAVE_INITGROUPS */
}
static void initial_setup __P((void));
static void set_loginclass __P((struct passwd *));
static void set_project __P((struct passwd *));
+static void set_runasgr __P((char *));
static void usage __P((int))
__attribute__((__noreturn__));
static void usage_excl __P((int))
char *login_style;
#endif /* HAVE_BSD_AUTH_H */
sigaction_t saved_sa_int, saved_sa_quit, saved_sa_tstp, saved_sa_chld;
+static char *runas_user;
+static char *runas_group;
int
log_error(NO_STDERR|NO_EXIT, "problem with defaults entries");
}
+ /*
+ * Set runas passwd/group entries based on command line or sudoers.
+ * Note that if runas_group was specified without runas_user we
+ * defer setting runas_pw so the match routines know to ignore it.
+ * XXX - early enough?
+ */
+ if (runas_group != NULL) {
+ set_runasgr(runas_group);
+ if (runas_user != NULL)
+ set_runaspw(runas_user);
+ } else
+ set_runaspw(runas_user ? runas_user : def_runas_default);
+
/* This goes after sudoers is parsed since it may have timestamp options. */
if (sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE) {
remove_timestamp((sudo_mode == MODE_KILL));
if (safe_cmnd == NULL)
safe_cmnd = estrdup(user_cmnd);
+ /* If only a group was specified, set runas_pw based on invoking user. */
+ if (runas_pw == NULL)
+ set_runaspw(user_name);
+
/*
* Look up the timestamp dir owner if one is specified.
*/
* be run during reboot after the YP/NIS/NIS+/LDAP/etc daemon has died.
*/
if (sudo_mode & (MODE_INVALIDATE|MODE_KILL))
- errorx(1, "uid %s does not exist in the passwd file!", pw_name);
- log_error(0, "uid %s does not exist in the passwd file!", pw_name);
+ errorx(1, "unknown uid: %s", pw_name);
+ log_error(0, "unknown uid: %s", pw_name);
}
if (user_shell == NULL || *user_shell == '\0')
user_shell = estrdup(sudo_user.pw->pw_shell);
if (nohostname)
log_error(USE_ERRNO|MSG_ONLY, "can't get hostname");
- set_runaspw(*user_runas); /* may call log_error() */
- if (*user_runas[0] == '#' && runas_pw->pw_name[0] != '#')
- *user_runas = estrdup(runas_pw->pw_name);
-
/*
* Get current working directory. Try as user, fall back to root.
*/
}
/* Set login class if applicable. */
+ /* XXX - should move to after sudoers_lookup */
set_loginclass(sudo_user.pw);
}
}
/*
- * Command line argument parsing, can't use getopt(3).
+ * Command line argument parsing, can't use getopt(3) due to optional args.
*/
static int
parse_args(argc, argv)
if (NewArgv[1] == NULL)
usage(1);
- user_runas = &NewArgv[1];
+ runas_user = NewArgv[1];
+
+ NewArgc--;
+ NewArgv++;
+ break;
+ case 'g':
+ /* Must have an associated runas group. */
+ if (NewArgv[1] == NULL)
+ usage(1);
+
+ runas_group = NewArgv[1];
NewArgc--;
NewArgv++;
if (NewArgv[1] == NULL)
usage(1);
if ((list_pw = sudo_getpwnam(NewArgv[1])) == NULL)
- errorx(1, "unknown user %s", NewArgv[1]);
+ errorx(1, "unknown user: %s", NewArgv[1]);
NewArgc--;
NewArgv++;
break;
usage(1);
}
- if (user_runas != NULL && !ISSET(rval, (MODE_EDIT|MODE_RUN|MODE_CHECK))) {
+ if ((runas_user != NULL || runas_group != NULL) &&
+ !ISSET(rval, (MODE_EDIT|MODE_RUN|MODE_CHECK))) {
if (excl != '\0')
- warningx("the `-u' and `-%c' options may not be used together",
- excl);
+ warningx("the `-%c' and `-%c' options may not be used together",
+ runas_user ? 'u' : 'g', excl);
usage(1);
}
if (list_pw != NULL && rval != MODE_LIST && rval != MODE_CHECK) {
errflags = NO_MAIL|MSG_ONLY|NO_EXIT;
if (login_class && strcmp(login_class, "-") != 0) {
- if (strcmp(*user_runas, "root") != 0 && user_uid != 0)
+ /* XXX - def_runas user may change after sudoers parse */
+ if (user_uid != 0 &&
+ strcmp(runas_user ? runas_user : def_runas_default, "root") != 0)
errorx(1, "only root can use -c %s", login_class);
} else {
login_class = pw->pw_class;
set_runaspw(user)
char *user;
{
- if (runas_pw != NULL) {
- if (user_runas != &def_runas_default)
- return(TRUE); /* don't override -u option */
- }
if (*user == '#') {
if ((runas_pw = sudo_getpwuid(atoi(user + 1))) == NULL)
runas_pw = sudo_fakepwnam(user);
} else {
if ((runas_pw = sudo_getpwnam(user)) == NULL)
- log_error(NO_MAIL|MSG_ONLY, "no passwd entry for %s!", user);
+ log_error(NO_MAIL|MSG_ONLY, "unknown user: %s", user);
}
return(TRUE);
}
+/*
+ * Get group entry for the group we are going to run commands as.
+ * Updates runas_pw as a side effect.
+ */
+static void
+set_runasgr(group)
+ char *group;
+{
+ if (*group == '#') {
+ if ((runas_gr = sudo_getgrgid(atoi(group + 1))) == NULL)
+ runas_gr = sudo_fakegrnam(group);
+ } else {
+ if ((runas_gr = sudo_getgrnam(group)) == NULL)
+ log_error(NO_MAIL|MSG_ONLY, "unknown group: %s", group);
+ }
+}
+
/*
* Get passwd entry for the user we are going to authenticate as.
* By default, this is the user invoking sudo. In the most common
if (def_rootpw) {
if ((pw = sudo_getpwuid(0)) == NULL)
- log_error(0, "uid 0 does not exist in the passwd file!");
+ log_error(0, "unknown uid: 0");
} else if (def_runaspw) {
if ((pw = sudo_getpwnam(def_runas_default)) == NULL)
- log_error(0, "user %s does not exist in the passwd file!",
- def_runas_default);
+ log_error(0, "unknown user: %s", def_runas_default);
} else if (def_targetpw) {
if (runas_pw->pw_name == NULL)
- log_error(NO_MAIL|MSG_ONLY, "no passwd entry for %lu!",
+ log_error(NO_MAIL|MSG_ONLY, "unknown uid: %lu",
(unsigned long) runas_pw->pw_uid);
pw = runas_pw;
} else
S\bSY\bYN\bNO\bOP\bPS\bSI\bIS\bS
s\bsu\bud\bdo\bo -\b-h\bh | -\b-K\bK | -\b-k\bk | -\b-L\bL | -\b-V\bV | -\b-v\bv
- s\bsu\bud\bdo\bo -\b-l\bl [-\b-U\bU _\bu_\bs_\be_\br_\bn_\ba_\bm_\be] [-\b-u\bu _\bu_\bs_\be_\br_\bn_\ba_\bm_\be|_\b#_\bu_\bi_\bd] [_\bc_\bo_\bm_\bm_\ba_\bn_\bd]
+ s\bsu\bud\bdo\bo -\b-l\bl [-\b-g\bg _\bg_\br_\bo_\bu_\bp_\bn_\ba_\bm_\be|_\b#_\bg_\bi_\bd] [-\b-U\bU _\bu_\bs_\be_\br_\bn_\ba_\bm_\be] [-\b-u\bu _\bu_\bs_\be_\br_\b-
+ _\bn_\ba_\bm_\be|_\b#_\bu_\bi_\bd] [_\bc_\bo_\bm_\bm_\ba_\bn_\bd]
s\bsu\bud\bdo\bo [-\b-b\bbE\bEH\bHP\bPS\bS] [-\b-a\ba _\ba_\bu_\bt_\bh_\b__\bt_\by_\bp_\be] [-\b-C\bC _\bf_\bd] [-\b-c\bc _\bc_\bl_\ba_\bs_\bs|_\b-]
- [-\b-p\bp _\bp_\br_\bo_\bm_\bp_\bt] [-\b-u\bu _\bu_\bs_\be_\br_\bn_\ba_\bm_\be|_\b#_\bu_\bi_\bd] [V\bVA\bAR\bR=_\bv_\ba_\bl_\bu_\be] {-\b-i\bi | -\b-s\bs | _\bc_\bo_\bm_\b-
- _\bm_\ba_\bn_\bd}
+ [-\b-g\bg _\bg_\br_\bo_\bu_\bp_\bn_\ba_\bm_\be|_\b#_\bg_\bi_\bd] [-\b-p\bp _\bp_\br_\bo_\bm_\bp_\bt] [-\b-u\bu _\bu_\bs_\be_\br_\bn_\ba_\bm_\be|_\b#_\bu_\bi_\bd]
+ [V\bVA\bAR\bR=_\bv_\ba_\bl_\bu_\be] {-\b-i\bi | -\b-s\bs | _\bc_\bo_\bm_\bm_\ba_\bn_\bd}
s\bsu\bud\bdo\boe\bed\bdi\bit\bt [-\b-S\bS] [-\b-a\ba _\ba_\bu_\bt_\bh_\b__\bt_\by_\bp_\be] [-\b-C\bC _\bf_\bd] [-\b-c\bc _\bc_\bl_\ba_\bs_\bs|_\b-]
- [-\b-p\bp _\bp_\br_\bo_\bm_\bp_\bt] [-\b-u\bu _\bu_\bs_\be_\br_\bn_\ba_\bm_\be|_\b#_\bu_\bi_\bd] file ...
+ [-\b-g\bg _\bg_\br_\bo_\bu_\bp_\bn_\ba_\bm_\be|_\b#_\bg_\bi_\bd] [-\b-p\bp _\bp_\br_\bo_\bm_\bp_\bt] [-\b-u\bu _\bu_\bs_\be_\br_\bn_\ba_\bm_\be|_\b#_\bu_\bi_\bd] file
+ ...
D\bDE\bES\bSC\bCR\bRI\bIP\bPT\bTI\bIO\bON\bN
s\bsu\bud\bdo\bo allows a permitted user to execute a _\bc_\bo_\bm_\bm_\ba_\bn_\bd as the
If s\bsu\bud\bdo\bo is run by root and the SUDO_USER environment vari-
able is set, s\bsu\bud\bdo\bo will use this value to determine who the
- actual user is. This can be used by a user to log com-
- mands through sudo even when a root shell has been
- invoked. It also allows the -\b-e\be flag to remain useful even
+ actual user is. This can be used by a user to log
-1.7 August 15, 2007 1
+1.7 November 21, 2007 1
SUDO(1m) MAINTENANCE COMMANDS SUDO(1m)
+ commands through sudo even when a root shell has been
+ invoked. It also allows the -\b-e\be flag to remain useful even
when being run via a sudo-run script or program. Note
however, that the sudoers lookup is still done for root,
not the user specified by SUDO_USER.
O\bOP\bPT\bTI\bIO\bON\bNS\bS
s\bsu\bud\bdo\bo accepts the following command line options:
- -a The -\b-a\ba (_\ba_\bu_\bt_\bh_\be_\bn_\bt_\bi_\bc_\ba_\bt_\bi_\bo_\bn _\bt_\by_\bp_\be) option causes s\bsu\bud\bdo\bo to use
- the specified authentication type when validating the
- user, as allowed by _\b/_\be_\bt_\bc_\b/_\bl_\bo_\bg_\bi_\bn_\b._\bc_\bo_\bn_\bf. The system
- administrator may specify a list of sudo-specific
- authentication methods by adding an "auth-sudo" entry
- in _\b/_\be_\bt_\bc_\b/_\bl_\bo_\bg_\bi_\bn_\b._\bc_\bo_\bn_\bf. This option is only available on
- systems that support BSD authentication.
+ -a _\bt_\by_\bp_\be The -\b-a\ba (_\ba_\bu_\bt_\bh_\be_\bn_\bt_\bi_\bc_\ba_\bt_\bi_\bo_\bn _\bt_\by_\bp_\be) option causes
+ s\bsu\bud\bdo\bo to use the specified authentication type
+ when validating the user, as allowed by
+ _\b/_\be_\bt_\bc_\b/_\bl_\bo_\bg_\bi_\bn_\b._\bc_\bo_\bn_\bf. The system administrator may
+ specify a list of sudo-specific authentication
+ methods by adding an "auth-sudo" entry in
+ _\b/_\be_\bt_\bc_\b/_\bl_\bo_\bg_\bi_\bn_\b._\bc_\bo_\bn_\bf. This option is only avail-
+ able on systems that support BSD authentica-
+ tion.
- -b The -\b-b\bb (_\bb_\ba_\bc_\bk_\bg_\br_\bo_\bu_\bn_\bd) option tells s\bsu\bud\bdo\bo to run the given
- command in the background. Note that if you use the
- -\b-b\bb option you cannot use shell job control to manipu-
- late the process.
+ -b The -\b-b\bb (_\bb_\ba_\bc_\bk_\bg_\br_\bo_\bu_\bn_\bd) option tells s\bsu\bud\bdo\bo to run
+ the given command in the background. Note
+ that if you use the -\b-b\bb option you cannot use
+ shell job control to manipulate the process.
- -C fd
- Normally, s\bsu\bud\bdo\bo will close all open file descriptors
- other than standard input, standard output and stan-
- dard error. The -\b-C\bC (_\bc_\bl_\bo_\bs_\be _\bf_\br_\bo_\bm) option allows the
- user to specify a starting point above the standard
- error (file descriptor three). Values less than three
- are not permitted. This option is only available if
- the administrator has enabled the _\bc_\bl_\bo_\bs_\be_\bf_\br_\bo_\bm_\b__\bo_\bv_\be_\br_\br_\bi_\bd_\be
- option in _\bs_\bu_\bd_\bo_\be_\br_\bs(4).
+ -C _\bf_\bd Normally, s\bsu\bud\bdo\bo will close all open file
+ descriptors other than standard input, stan-
+ dard output and standard error. The -\b-C\bC (_\bc_\bl_\bo_\bs_\be
+ _\bf_\br_\bo_\bm) option allows the user to specify a
+ starting point above the standard error (file
+ descriptor three). Values less than three are
+ not permitted. This option is only available
+ if the administrator has enabled the _\bc_\bl_\bo_\bs_\be_\b-
+ _\bf_\br_\bo_\bm_\b__\bo_\bv_\be_\br_\br_\bi_\bd_\be option in _\bs_\bu_\bd_\bo_\be_\br_\bs(4).
- -c The -\b-c\bc (_\bc_\bl_\ba_\bs_\bs) option causes s\bsu\bud\bdo\bo to run the specified
- command with resources limited by the specified login
- class. The _\bc_\bl_\ba_\bs_\bs argument can be either a class name
- as defined in _\b/_\be_\bt_\bc_\b/_\bl_\bo_\bg_\bi_\bn_\b._\bc_\bo_\bn_\bf, or a single '-' charac-
- ter. Specifying a _\bc_\bl_\ba_\bs_\bs of - indicates that the com-
- mand should be run restricted by the default login
- capabilities for the user the command is run as. If
- the _\bc_\bl_\ba_\bs_\bs argument specifies an existing user class,
- the command must be run as root, or the s\bsu\bud\bdo\bo command
- must be run from a shell that is already root. This
- option is only available on systems with BSD login
- classes.
+ -c _\bc_\bl_\ba_\bs_\bs The -\b-c\bc (_\bc_\bl_\ba_\bs_\bs) option causes s\bsu\bud\bdo\bo to run the
+ specified command with resources limited by
+ the specified login class. The _\bc_\bl_\ba_\bs_\bs argument
+ can be either a class name as defined in
+ _\b/_\be_\bt_\bc_\b/_\bl_\bo_\bg_\bi_\bn_\b._\bc_\bo_\bn_\bf, or a single '-' character.
+ Specifying a _\bc_\bl_\ba_\bs_\bs of - indicates that the
+ command should be run restricted by the
+ default login capabilities for the user the
+ command is run as. If the _\bc_\bl_\ba_\bs_\bs argument
+ specifies an existing user class, the command
+ must be run as root, or the s\bsu\bud\bdo\bo command must
+ be run from a shell that is already root.
+ This option is only available on systems with
+ BSD login classes.
- -E The -\b-E\bE (_\bp_\br_\be_\bs_\be_\br_\bv_\be _\be_\bn_\bv_\bi_\br_\bo_\bn_\bm_\be_\bn_\bt) option will override the
- _\be_\bn_\bv_\b__\br_\be_\bs_\be_\bt option in _\bs_\bu_\bd_\bo_\be_\br_\bs(4)). It is only available
- when either the matching command has the SETENV tag or
- the _\bs_\be_\bt_\be_\bn_\bv option is set in _\bs_\bu_\bd_\bo_\be_\br_\bs(4).
- -e The -\b-e\be (_\be_\bd_\bi_\bt) option indicates that, instead of
-
-1.7 August 15, 2007 2
+1.7 November 21, 2007 2
SUDO(1m) MAINTENANCE COMMANDS SUDO(1m)
- running a command, the user wishes to edit one or more
- files. In lieu of a command, the string "sudoedit" is
- used when consulting the _\bs_\bu_\bd_\bo_\be_\br_\bs file. If the user is
- authorized by _\bs_\bu_\bd_\bo_\be_\br_\bs the following steps are taken:
+ -E The -\b-E\bE (_\bp_\br_\be_\bs_\be_\br_\bv_\be _\be_\bn_\bv_\bi_\br_\bo_\bn_\bm_\be_\bn_\bt) option will
+ override the _\be_\bn_\bv_\b__\br_\be_\bs_\be_\bt option in _\bs_\bu_\bd_\bo_\be_\br_\bs(4)).
+ It is only available when either the matching
+ command has the SETENV tag or the _\bs_\be_\bt_\be_\bn_\bv
+ option is set in _\bs_\bu_\bd_\bo_\be_\br_\bs(4).
- 1. Temporary copies are made of the files to be
- edited with the owner set to the invoking user.
+ -e The -\b-e\be (_\be_\bd_\bi_\bt) option indicates that, instead
+ of running a command, the user wishes to edit
+ one or more files. In lieu of a command, the
+ string "sudoedit" is used when consulting the
+ _\bs_\bu_\bd_\bo_\be_\br_\bs file. If the user is authorized by
+ _\bs_\bu_\bd_\bo_\be_\br_\bs the following steps are taken:
- 2. The editor specified by the VISUAL or EDITOR envi-
- ronment variables is run to edit the temporary
- files. If neither VISUAL nor EDITOR are set, the
- program listed in the _\be_\bd_\bi_\bt_\bo_\br _\bs_\bu_\bd_\bo_\be_\br_\bs variable is
- used.
+ 1. Temporary copies are made of the files to
+ be edited with the owner set to the invok-
+ ing user.
- 3. If they have been modified, the temporary files
- are copied back to their original location and the
- temporary versions are removed.
+ 2. The editor specified by the VISUAL or EDI-
+ TOR environment variables is run to edit
+ the temporary files. If neither VISUAL
+ nor EDITOR are set, the program listed in
+ the _\be_\bd_\bi_\bt_\bo_\br _\bs_\bu_\bd_\bo_\be_\br_\bs variable is used.
- If the specified file does not exist, it will be cre-
- ated. Note that unlike most commands run by s\bsu\bud\bdo\bo, the
- editor is run with the invoking user's environment
- unmodified. If, for some reason, s\bsu\bud\bdo\bo is unable to
- update a file with its edited version, the user will
- receive a warning and the edited copy will remain in a
- temporary file.
+ 3. If they have been modified, the temporary
+ files are copied back to their original
+ location and the temporary versions are
+ removed.
- -H The -\b-H\bH (_\bH_\bO_\bM_\bE) option sets the HOME environment vari-
- able to the homedir of the target user (root by
- default) as specified in _\bp_\ba_\bs_\bs_\bw_\bd(4). By default, s\bsu\bud\bdo\bo
- does not modify HOME (see _\bs_\be_\bt_\b__\bh_\bo_\bm_\be and _\ba_\bl_\bw_\ba_\by_\bs_\b__\bs_\be_\bt_\b__\bh_\bo_\bm_\be
- in _\bs_\bu_\bd_\bo_\be_\br_\bs(4)).
+ If the specified file does not exist, it will
+ be created. Note that unlike most commands
+ run by s\bsu\bud\bdo\bo, the editor is run with the invok-
+ ing user's environment unmodified. If, for
+ some reason, s\bsu\bud\bdo\bo is unable to update a file
+ with its edited version, the user will receive
+ a warning and the edited copy will remain in a
+ temporary file.
- -h The -\b-h\bh (_\bh_\be_\bl_\bp) option causes s\bsu\bud\bdo\bo to print a usage mes-
- sage and exit.
+ -g _\bg_\br_\bo_\bu_\bp Normally, s\bsu\bud\bdo\bo sets the primary group to the
+ one specified by the passwd database for the
+ user the command is being run as (by default,
+ root). The -\b-g\bg (_\bg_\br_\bo_\bu_\bp) option causes s\bsu\bud\bdo\bo to
+ run the specified command with the primary
+ group set to _\bg_\br_\bo_\bu_\bp. To specify a _\bg_\bi_\bd instead
+ of a _\bg_\br_\bo_\bu_\bp _\bn_\ba_\bm_\be, use _\b#_\bg_\bi_\bd. When running com-
+ mands as a _\bg_\bi_\bd, many shells require that the
+ '#' be escaped with a backslash ('\'). If no
+ -\b-u\bu option is specified, the command will be
+ run as the invoking user (not root). In
+ either case, the primary group will be set to
+ _\bg_\br_\bo_\bu_\bp.
- -i The -\b-i\bi (_\bs_\bi_\bm_\bu_\bl_\ba_\bt_\be _\bi_\bn_\bi_\bt_\bi_\ba_\bl _\bl_\bo_\bg_\bi_\bn) option runs the shell
- specified in the _\bp_\ba_\bs_\bs_\bw_\bd(4) entry of the user that the
- command is being run as. The command name argument
- given to the shell begins with a `-' to tell the shell
- to run as a login shell. s\bsu\bud\bdo\bo attempts to change to
- that user's home directory before running the shell.
- It also initializes the environment, leaving _\bD_\bI_\bS_\bP_\bL_\bA_\bY
- and _\bT_\bE_\bR_\bM unchanged, setting _\bH_\bO_\bM_\bE, _\bS_\bH_\bE_\bL_\bL, _\bU_\bS_\bE_\bR, _\bL_\bO_\bG_\b-
- _\bN_\bA_\bM_\bE, and _\bP_\bA_\bT_\bH, and unsetting all other environment
- variables.
+ -H The -\b-H\bH (_\bH_\bO_\bM_\bE) option sets the HOME environment
+ variable to the homedir of the target user
+ (root by default) as specified in _\bp_\ba_\bs_\bs_\bw_\bd(4).
- -K The -\b-K\bK (sure _\bk_\bi_\bl_\bl) option is like -\b-k\bk except that it
- removes the user's timestamp entirely. Like -\b-k\bk, this
- option does not require a password.
- -k The -\b-k\bk (_\bk_\bi_\bl_\bl) option to s\bsu\bud\bdo\bo invalidates the user's
- timestamp by setting the time on it to the Epoch. The
- next time s\bsu\bud\bdo\bo is run a password will be required.
- This option does not require a password and was added
+1.7 November 21, 2007 3
-1.7 August 15, 2007 3
+SUDO(1m) MAINTENANCE COMMANDS SUDO(1m)
-SUDO(1m) MAINTENANCE COMMANDS SUDO(1m)
+ By default, s\bsu\bud\bdo\bo does not modify HOME (see
+ _\bs_\be_\bt_\b__\bh_\bo_\bm_\be and _\ba_\bl_\bw_\ba_\by_\bs_\b__\bs_\be_\bt_\b__\bh_\bo_\bm_\be in _\bs_\bu_\bd_\bo_\be_\br_\bs(4)).
+
+ -h The -\b-h\bh (_\bh_\be_\bl_\bp) option causes s\bsu\bud\bdo\bo to print a
+ usage message and exit.
+
+ -i The -\b-i\bi (_\bs_\bi_\bm_\bu_\bl_\ba_\bt_\be _\bi_\bn_\bi_\bt_\bi_\ba_\bl _\bl_\bo_\bg_\bi_\bn) option runs
+ the shell specified in the _\bp_\ba_\bs_\bs_\bw_\bd(4) entry of
+ the user that the command is being run as.
+ The command name argument given to the shell
+ begins with a `-' to tell the shell to run as
+ a login shell. s\bsu\bud\bdo\bo attempts to change to
+ that user's home directory before running the
+ shell. It also initializes the environment,
+ leaving _\bD_\bI_\bS_\bP_\bL_\bA_\bY and _\bT_\bE_\bR_\bM unchanged, setting
+ _\bH_\bO_\bM_\bE, _\bS_\bH_\bE_\bL_\bL, _\bU_\bS_\bE_\bR, _\bL_\bO_\bG_\bN_\bA_\bM_\bE, and _\bP_\bA_\bT_\bH, and
+ unsetting all other environment variables.
+
+ -K The -\b-K\bK (sure _\bk_\bi_\bl_\bl) option is like -\b-k\bk except
+ that it removes the user's timestamp entirely.
+ Like -\b-k\bk, this option does not require a pass-
+ word.
+
+ -k The -\b-k\bk (_\bk_\bi_\bl_\bl) option to s\bsu\bud\bdo\bo invalidates the
+ user's timestamp by setting the time on it to
+ the Epoch. The next time s\bsu\bud\bdo\bo is run a pass-
+ word will be required. This option does not
+ require a password and was added to allow a
+ user to revoke s\bsu\bud\bdo\bo permissions from a .logout
+ file.
+
+ -L The -\b-L\bL (_\bl_\bi_\bs_\bt defaults) option will list out
+ the parameters that may be set in a _\bD_\be_\bf_\ba_\bu_\bl_\bt_\bs
+ line along with a short description for each.
+ This option is useful in conjunction with
+ _\bg_\br_\be_\bp(1).
+ -l [_\bc_\bo_\bm_\bm_\ba_\bn_\bd]
+ If no _\bc_\bo_\bm_\bm_\ba_\bn_\bd is specified, the -\b-l\bl (_\bl_\bi_\bs_\bt)
+ option will list the allowed (and forbidden)
+ commands for the invoking user (or the user
+ specified by the -\b-U\bU option) on the current
+ host. If a _\bc_\bo_\bm_\bm_\ba_\bn_\bd is specified and is per-
+ mitted by _\bs_\bu_\bd_\bo_\be_\br_\bs, the fully-qualified path to
+ the command is displayed along with any com-
+ mand line arguments. If _\bc_\bo_\bm_\bm_\ba_\bn_\bd is not
+ allowed, s\bsu\bud\bdo\bo will exit with a return value of
+ 1.
- to allow a user to revoke s\bsu\bud\bdo\bo permissions from a
- .logout file.
+ -P The -\b-P\bP (_\bp_\br_\be_\bs_\be_\br_\bv_\be _\bg_\br_\bo_\bu_\bp _\bv_\be_\bc_\bt_\bo_\br) option causes
+ s\bsu\bud\bdo\bo to preserve the invoking user's group
+ vector unaltered. By default, s\bsu\bud\bdo\bo will ini-
+ tialize the group vector to the list of groups
+ the target user is in. The real and effective
- -L The -\b-L\bL (_\bl_\bi_\bs_\bt defaults) option will list out the param-
- eters that may be set in a _\bD_\be_\bf_\ba_\bu_\bl_\bt_\bs line along with a
- short description for each. This option is useful in
- conjunction with _\bg_\br_\be_\bp(1).
- -l [_\bc_\bo_\bm_\bm_\ba_\bn_\bd]
- If no _\bc_\bo_\bm_\bm_\ba_\bn_\bd is specified, the -\b-l\bl (_\bl_\bi_\bs_\bt) option will
- list the allowed (and forbidden) commands for the
- invoking user (or the user specified by the -\b-U\bU option)
- on the current host. If a _\bc_\bo_\bm_\bm_\ba_\bn_\bd is specified and is
- permitted by _\bs_\bu_\bd_\bo_\be_\br_\bs, the fully-qualified path to the
- command is displayed along with any command line argu-
- ments. If _\bc_\bo_\bm_\bm_\ba_\bn_\bd is not allowed, s\bsu\bud\bdo\bo will exit with
- a return value of 1.
- -P The -\b-P\bP (_\bp_\br_\be_\bs_\be_\br_\bv_\be _\bg_\br_\bo_\bu_\bp _\bv_\be_\bc_\bt_\bo_\br) option causes s\bsu\bud\bdo\bo to
- preserve the invoking user's group vector unaltered.
- By default, s\bsu\bud\bdo\bo will initialize the group vector to
- the list of groups the target user is in. The real
- and effective group IDs, however, are still set to
- match the target user.
+1.7 November 21, 2007 4
- -p The -\b-p\bp (_\bp_\br_\bo_\bm_\bp_\bt) option allows you to override the
- default password prompt and use a custom one. The
- following percent (`%') escapes are supported:
- %H expanded to the local hostname including the
- domain name (on if the machine's hostname is fully
- qualified or the _\bf_\bq_\bd_\bn _\bs_\bu_\bd_\bo_\be_\br_\bs option is set)
- %h expanded to the local hostname without the domain
- name
- %U expanded to the login name of the user the command
- will be run as (defaults to root)
- %u expanded to the invoking user's login name
+SUDO(1m) MAINTENANCE COMMANDS SUDO(1m)
- %% two consecutive % characters are collapsed into a
- single % character
- -S The -\b-S\bS (_\bs_\bt_\bd_\bi_\bn) option causes s\bsu\bud\bdo\bo to read the password
- from the standard input instead of the terminal
- device.
+ group IDs, however, are still set to match the
+ target user.
- -s The -\b-s\bs (_\bs_\bh_\be_\bl_\bl) option runs the shell specified by the
- _\bS_\bH_\bE_\bL_\bL environment variable if it is set or the shell
- as specified in _\bp_\ba_\bs_\bs_\bw_\bd(4).
+ -p _\bp_\br_\bo_\bm_\bp_\bt The -\b-p\bp (_\bp_\br_\bo_\bm_\bp_\bt) option allows you to override
+ the default password prompt and use a custom
+ one. The following percent (`%') escapes are
+ supported:
- -U The -\b-U\bU (_\bo_\bt_\bh_\be_\br _\bu_\bs_\be_\br) option is used in conjunction with
- the -\b-l\bl option to specify the user whose privileges
+ %H expanded to the local hostname including
+ the domain name (on if the machine's host-
+ name is fully qualified or the _\bf_\bq_\bd_\bn _\bs_\bu_\bd_\bo_\b-
+ _\be_\br_\bs option is set)
+ %h expanded to the local hostname without the
+ domain name
+ %U expanded to the login name of the user the
+ command will be run as (defaults to root)
-1.7 August 15, 2007 4
+ %u expanded to the invoking user's login name
+ %% two consecutive % characters are collapsed
+ into a single % character
+ -S The -\b-S\bS (_\bs_\bt_\bd_\bi_\bn) option causes s\bsu\bud\bdo\bo to read the
+ password from the standard input instead of
+ the terminal device.
+ -s The -\b-s\bs (_\bs_\bh_\be_\bl_\bl) option runs the shell specified
+ by the _\bS_\bH_\bE_\bL_\bL environment variable if it is set
+ or the shell as specified in _\bp_\ba_\bs_\bs_\bw_\bd(4).
+
+ -U _\bu_\bs_\be_\br The -\b-U\bU (_\bo_\bt_\bh_\be_\br _\bu_\bs_\be_\br) option is used in conjunc-
+ tion with the -\b-l\bl option to specify the user
+ whose privileges should be listed. Only root
+ or a user with s\bsu\bud\bdo\bo ALL on the current host
+ may use this option.
+
+ -u _\bu_\bs_\be_\br The -\b-u\bu (_\bu_\bs_\be_\br) option causes s\bsu\bud\bdo\bo to run the
+ specified command as a user other than _\br_\bo_\bo_\bt.
+ To specify a _\bu_\bi_\bd instead of a _\bu_\bs_\be_\br _\bn_\ba_\bm_\be, use
+ _\b#_\bu_\bi_\bd. When running commands as a _\bu_\bi_\bd, many
+ shells require that the '#' be escaped with a
+ backslash ('\'). Note that if the _\bt_\ba_\br_\bg_\be_\bt_\bp_\bw
+ Defaults option is set (see _\bs_\bu_\bd_\bo_\be_\br_\bs(4)) it is
+ not possible to run commands with a uid not
+ listed in the password database.
+
+ -V The -\b-V\bV (_\bv_\be_\br_\bs_\bi_\bo_\bn) option causes s\bsu\bud\bdo\bo to print
+ the version number and exit. If the invoking
+ user is already root the -\b-V\bV option will print
+ out a list of the defaults s\bsu\bud\bdo\bo was compiled
+ with as well as the machine's local network
+ addresses.
+
+
+
+1.7 November 21, 2007 5
-SUDO(1m) MAINTENANCE COMMANDS SUDO(1m)
- should be listed. Only root or a user with s\bsu\bud\bdo\bo ALL
- on the current host may use this option.
- -u The -\b-u\bu (_\bu_\bs_\be_\br) option causes s\bsu\bud\bdo\bo to run the specified
- command as a user other than _\br_\bo_\bo_\bt. To specify a _\bu_\bi_\bd
- instead of a _\bu_\bs_\be_\br_\bn_\ba_\bm_\be, use _\b#_\bu_\bi_\bd. When running com-
- mands as a _\bu_\bi_\bd, many shells require that the '#' be
- escaped with a backslash ('\'). Note that if the _\bt_\ba_\br_\b-
- _\bg_\be_\bt_\bp_\bw Defaults option is set (see _\bs_\bu_\bd_\bo_\be_\br_\bs(4)) it is
- not possible to run commands with a uid not listed in
- the password database.
+SUDO(1m) MAINTENANCE COMMANDS SUDO(1m)
- -V The -\b-V\bV (_\bv_\be_\br_\bs_\bi_\bo_\bn) option causes s\bsu\bud\bdo\bo to print the ver-
- sion number and exit. If the invoking user is already
- root the -\b-V\bV option will print out a list of the
- defaults s\bsu\bud\bdo\bo was compiled with as well as the
- machine's local network addresses.
- -v If given the -\b-v\bv (_\bv_\ba_\bl_\bi_\bd_\ba_\bt_\be) option, s\bsu\bud\bdo\bo will update
- the user's timestamp, prompting for the user's pass-
- word if necessary. This extends the s\bsu\bud\bdo\bo timeout for
- another 5 minutes (or whatever the timeout is set to
- in _\bs_\bu_\bd_\bo_\be_\br_\bs) but does not run a command.
+ -v If given the -\b-v\bv (_\bv_\ba_\bl_\bi_\bd_\ba_\bt_\be) option, s\bsu\bud\bdo\bo will
+ update the user's timestamp, prompting for the
+ user's password if necessary. This extends
+ the s\bsu\bud\bdo\bo timeout for another 5 minutes (or
+ whatever the timeout is set to in _\bs_\bu_\bd_\bo_\be_\br_\bs) but
+ does not run a command.
- -- The -\b--\b- flag indicates that s\bsu\bud\bdo\bo should stop processing
- command line arguments. It is most useful in conjunc-
- tion with the -\b-s\bs flag.
+ -- The -\b--\b- flag indicates that s\bsu\bud\bdo\bo should stop
+ processing command line arguments. It is most
+ useful in conjunction with the -\b-s\bs flag.
Environment variables to be set for the command may also
be passed on the command line in the form of V\bVA\bAR\bR=_\bv_\ba_\bl_\bu_\be,
passed on the command line are subject to the same
restrictions as normal environment variables with one
important exception. If the _\bs_\be_\bt_\be_\bn_\bv option is set in _\bs_\bu_\bd_\bo_\b-
- _\be_\br_\bs or the command to be run has the SETENV tag set the
- user may set variables that would overwise be forbidden.
- See _\bs_\bu_\bd_\bo_\be_\br_\bs(4) for more information.
+ _\be_\br_\bs, the command to be run has the SETENV tag set or the
+ command matched is ALL, the user may set variables that
+ would overwise be forbidden. See _\bs_\bu_\bd_\bo_\be_\br_\bs(4) for more
+ information.
R\bRE\bET\bTU\bUR\bRN\bN V\bVA\bAL\bLU\bUE\bES\bS
Upon successful execution of a program, the return value
stances. The most common reason for _\bs_\bt_\ba_\bt(2) to return
"permission denied" is if you are running an automounter
and one of the directories in your PATH is on a machine
-
-
-
-1.7 August 15, 2007 5
-
-
-
-
-
-SUDO(1m) MAINTENANCE COMMANDS SUDO(1m)
-
-
that is currently unreachable.
S\bSE\bEC\bCU\bUR\bRI\bIT\bTY\bY N\bNO\bOT\bTE\bES\bS
If, however, the _\be_\bn_\bv_\b__\br_\be_\bs_\be_\bt option is disabled in _\bs_\bu_\bd_\bo_\be_\br_\bs,
any variables not explicitly denied by the _\be_\bn_\bv_\b__\bc_\bh_\be_\bc_\bk and
+
+
+
+1.7 November 21, 2007 6
+
+
+
+
+
+SUDO(1m) MAINTENANCE COMMANDS SUDO(1m)
+
+
_\be_\bn_\bv_\b__\bd_\be_\bl_\be_\bt_\be options are inherited from the invoking pro-
cess. In this case, _\be_\bn_\bv_\b__\bc_\bh_\be_\bc_\bk and _\be_\bn_\bv_\b__\bd_\be_\bl_\be_\bt_\be behave like
a blacklist. Since it is not possible to blacklist all
timestamp directory before s\bsu\bud\bdo\bo is run. However, because
s\bsu\bud\bdo\bo checks the ownership and mode of the directory and
its contents, the only damage that can be done is to
-
-
-
-1.7 August 15, 2007 6
-
-
-
-
-
-SUDO(1m) MAINTENANCE COMMANDS SUDO(1m)
-
-
"hide" files by putting them in the timestamp dir. This
is unlikely to happen since once the timestamp dir is
owned by root and inaccessible by any other user, the user
timestamp with a bogus date on systems that allow users to
give away files.
+
+
+1.7 November 21, 2007 7
+
+
+
+
+
+SUDO(1m) MAINTENANCE COMMANDS SUDO(1m)
+
+
Please note that s\bsu\bud\bdo\bo will normally only log the command
it explicitly runs. If a user runs a command such as sudo
su or sudo sh, subsequent commands run from that shell
SUDO_UID Set to the uid of the user who invoked
sudo
-
-
-1.7 August 15, 2007 7
-
-
-
-
-
-SUDO(1m) MAINTENANCE COMMANDS SUDO(1m)
-
-
SUDO_GID Set to the gid of the user who invoked
sudo
_\b/_\be_\bt_\bc_\b/_\bs_\bu_\bd_\bo_\be_\br_\bs List of who can run what
_\b/_\bv_\ba_\br_\b/_\br_\bu_\bn_\b/_\bs_\bu_\bd_\bo Directory containing timestamps
+
+
+
+
+1.7 November 21, 2007 8
+
+
+
+
+
+SUDO(1m) MAINTENANCE COMMANDS SUDO(1m)
+
+
E\bEX\bXA\bAM\bMP\bPL\bLE\bES\bS
Note: the following examples assume suitable _\bs_\bu_\bd_\bo_\be_\br_\bs(4)
entries.
Todd C. Miller
See the HISTORY file in the s\bsu\bud\bdo\bo distribution or visit
-
-
-
-1.7 August 15, 2007 8
-
-
-
-
-
-SUDO(1m) MAINTENANCE COMMANDS SUDO(1m)
-
-
http://www.sudo.ws/sudo/history.html for a short history
of s\bsu\bud\bdo\bo.
It is not meaningful to run the cd command directly via
sudo, e.g.,
+
+
+
+1.7 November 21, 2007 9
+
+
+
+
+
+SUDO(1m) MAINTENANCE COMMANDS SUDO(1m)
+
+
$ sudo cd /usr/local/protected
since when the command exits the parent process (your
-1.7 August 15, 2007 9
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1.7 November 21, 2007 10
struct sudo_user {
struct passwd *pw;
struct passwd *_runas_pw;
+ struct group *_runas_gr;
struct stat *cmnd_stat;
char *path;
char *shell;
char *ttypath;
char *host;
char *shost;
- char **runas;
char *prompt;
char *cmnd;
char *cmnd_args;
#define user_tty (sudo_user.tty)
#define user_ttypath (sudo_user.ttypath)
#define user_cwd (sudo_user.cwd)
-#define user_runas (sudo_user.runas)
#define user_cmnd (sudo_user.cmnd)
#define user_args (sudo_user.cmnd_args)
#define user_base (sudo_user.cmnd_base)
#define safe_cmnd (sudo_user.cmnd_safe)
#define login_class (sudo_user.class_name)
#define runas_pw (sudo_user._runas_pw)
+#define runas_gr (sudo_user._runas_gr)
/*
* We used to use the system definition of PASS_MAX or _PASSWD_LEN,
struct passwd *sudo_getpwuid __P((uid_t));
struct passwd *sudo_fakepwuid __P((uid_t));
struct group *sudo_getgrnam __P((const char *));
+struct group *sudo_fakegrnam __P((const char *));
struct group *sudo_getgrgid __P((gid_t));
YY_DECL;
.\" ========================================================================
.\"
.IX Title "SUDO @mansectsu@"
-.TH SUDO @mansectsu@ "August 15, 2007" "1.7" "MAINTENANCE COMMANDS"
+.TH SUDO @mansectsu@ "November 21, 2007" "1.7" "MAINTENANCE COMMANDS"
.SH "NAME"
sudo, sudoedit \- execute a command as another user
.SH "SYNOPSIS"
.IX Header "SYNOPSIS"
\&\fBsudo\fR \fB\-h\fR | \fB\-K\fR | \fB\-k\fR | \fB\-L\fR | \fB\-V\fR | \fB\-v\fR
.PP
-\&\fBsudo\fR \fB\-l\fR [\fB\-U\fR\ \fIusername\fR] [\fB\-u\fR\ \fIusername\fR|\fI#uid\fR] [\fIcommand\fR]
+\&\fBsudo\fR \fB\-l\fR [\fB\-g\fR\ \fIgroupname\fR|\fI#gid\fR] [\fB\-U\fR\ \fIusername\fR]
+[\fB\-u\fR\ \fIusername\fR|\fI#uid\fR] [\fIcommand\fR]
.PP
\&\fBsudo\fR [\fB\-bEHPS\fR] [\fB\-a\fR\ \fIauth_type\fR] [\fB\-C\fR\ \fIfd\fR]
-[\fB\-c\fR\ \fIclass\fR|\fI\-\fR] [\fB\-p\fR\ \fIprompt\fR] [\fB\-u\fR\ \fIusername\fR|\fI#uid\fR]
-[\fB\s-1VAR\s0\fR=\fIvalue\fR] {\fB\-i\fR\ |\ \fB\-s\fR\ |\ \fIcommand\fR}
+[\fB\-c\fR\ \fIclass\fR|\fI\-\fR] [\fB\-g\fR\ \fIgroupname\fR|\fI#gid\fR] [\fB\-p\fR\ \fIprompt\fR]
+[\fB\-u\fR\ \fIusername\fR|\fI#uid\fR] [\fB\s-1VAR\s0\fR=\fIvalue\fR]
+{\fB\-i\fR\ |\ \fB\-s\fR\ |\ \fIcommand\fR}
.PP
\&\fBsudoedit\fR [\fB\-S\fR] [\fB\-a\fR\ \fIauth_type\fR] [\fB\-C\fR\ \fIfd\fR]
-[\fB\-c\fR\ \fIclass\fR|\fI\-\fR] [\fB\-p\fR\ \fIprompt\fR] [\fB\-u\fR\ \fIusername\fR|\fI#uid\fR]
-file ...
+[\fB\-c\fR\ \fIclass\fR|\fI\-\fR] [\fB\-g\fR\ \fIgroupname\fR|\fI#gid\fR] [\fB\-p\fR\ \fIprompt\fR]
+[\fB\-u\fR\ \fIusername\fR|\fI#uid\fR] file ...
.SH "DESCRIPTION"
.IX Header "DESCRIPTION"
\&\fBsudo\fR allows a permitted user to execute a \fIcommand\fR as the
.SH "OPTIONS"
.IX Header "OPTIONS"
\&\fBsudo\fR accepts the following command line options:
-.IP "\-a" 4
-.IX Item "-a"
+.IP "\-a \fItype\fR" 12
+.IX Item "-a type"
The \fB\-a\fR (\fIauthentication type\fR) option causes \fBsudo\fR to use the
specified authentication type when validating the user, as allowed
by \fI/etc/login.conf\fR. The system administrator may specify a list
of sudo-specific authentication methods by adding an \*(L"auth\-sudo\*(R"
entry in \fI/etc/login.conf\fR. This option is only available on systems
that support \s-1BSD\s0 authentication.
-.IP "\-b" 4
+.IP "\-b" 12
.IX Item "-b"
The \fB\-b\fR (\fIbackground\fR) option tells \fBsudo\fR to run the given
command in the background. Note that if you use the \fB\-b\fR
option you cannot use shell job control to manipulate the process.
-.IP "\-C fd" 4
+.IP "\-C \fIfd\fR" 12
.IX Item "-C fd"
Normally, \fBsudo\fR will close all open file descriptors other than
standard input, standard output and standard error. The \fB\-C\fR
three are not permitted. This option is only available if the
administrator has enabled the \fIclosefrom_override\fR option in
\&\fIsudoers\fR\|(@mansectform@).
-.IP "\-c" 4
-.IX Item "-c"
+.IP "\-c \fIclass\fR" 12
+.IX Item "-c class"
The \fB\-c\fR (\fIclass\fR) option causes \fBsudo\fR to run the specified command
with resources limited by the specified login class. The \fIclass\fR
argument can be either a class name as defined in \fI/etc/login.conf\fR,
argument specifies an existing user class, the command must be run
as root, or the \fBsudo\fR command must be run from a shell that is already
root. This option is only available on systems with \s-1BSD\s0 login classes.
-.IP "\-E" 4
+.IP "\-E" 12
.IX Item "-E"
The \fB\-E\fR (\fIpreserve\fR \fIenvironment\fR) option will override the
\&\fIenv_reset\fR option in \fIsudoers\fR\|(@mansectform@)). It is only
available when either the matching command has the \f(CW\*(C`SETENV\*(C'\fR tag
or the \fIsetenv\fR option is set in \fIsudoers\fR\|(@mansectform@).
-.IP "\-e" 4
+.IP "\-e" 12
.IX Item "-e"
The \fB\-e\fR (\fIedit\fR) option indicates that, instead of running
a command, the user wishes to edit one or more files. In lieu
of a command, the string \*(L"sudoedit\*(R" is used when consulting
the \fIsudoers\fR file. If the user is authorized by \fIsudoers\fR
the following steps are taken:
-.RS 4
+.RS 12
.IP "1." 4
Temporary copies are made of the files to be edited with the owner
set to the invoking user.
If they have been modified, the temporary files are copied back to
their original location and the temporary versions are removed.
.RE
-.RS 4
+.RS 12
.Sp
If the specified file does not exist, it will be created. Note
that unlike most commands run by \fBsudo\fR, the editor is run with
user will receive a warning and the edited copy will remain in a
temporary file.
.RE
-.IP "\-H" 4
+.IP "\-g \fIgroup\fR" 12
+.IX Item "-g group"
+Normally, \fBsudo\fR sets the primary group to the one specified by
+the passwd database for the user the command is being run as (by
+default, root). The \fB\-g\fR (\fIgroup\fR) option causes \fBsudo\fR to run
+the specified command with the primary group set to \fIgroup\fR. To
+specify a \fIgid\fR instead of a \fIgroup name\fR, use \fI#gid\fR. When
+running commands as a \fIgid\fR, many shells require that the '#' be
+escaped with a backslash ('\e'). If no \fB\-u\fR option is specified,
+the command will be run as the invoking user (not root). In either
+case, the primary group will be set to \fIgroup\fR.
+.IP "\-H" 12
.IX Item "-H"
The \fB\-H\fR (\fI\s-1HOME\s0\fR) option sets the \f(CW\*(C`HOME\*(C'\fR environment variable
to the homedir of the target user (root by default) as specified
in \fIpasswd\fR\|(@mansectform@). By default, \fBsudo\fR does not modify \f(CW\*(C`HOME\*(C'\fR
(see \fIset_home\fR and \fIalways_set_home\fR in \fIsudoers\fR\|(@mansectform@)).
-.IP "\-h" 4
+.IP "\-h" 12
.IX Item "-h"
The \fB\-h\fR (\fIhelp\fR) option causes \fBsudo\fR to print a usage message and exit.
-.IP "\-i" 4
+.IP "\-i" 12
.IX Item "-i"
The \fB\-i\fR (\fIsimulate initial login\fR) option runs the shell specified
in the \fIpasswd\fR\|(@mansectform@) entry of the user that the command is
shell. It also initializes the environment, leaving \fI\s-1DISPLAY\s0\fR
and \fI\s-1TERM\s0\fR unchanged, setting \fI\s-1HOME\s0\fR, \fI\s-1SHELL\s0\fR, \fI\s-1USER\s0\fR, \fI\s-1LOGNAME\s0\fR, and
\&\fI\s-1PATH\s0\fR, and unsetting all other environment variables.
-.IP "\-K" 4
+.IP "\-K" 12
.IX Item "-K"
The \fB\-K\fR (sure \fIkill\fR) option is like \fB\-k\fR except that it removes
the user's timestamp entirely. Like \fB\-k\fR, this option does not
require a password.
-.IP "\-k" 4
+.IP "\-k" 12
.IX Item "-k"
The \fB\-k\fR (\fIkill\fR) option to \fBsudo\fR invalidates the user's timestamp
by setting the time on it to the Epoch. The next time \fBsudo\fR is
run a password will be required. This option does not require a password
and was added to allow a user to revoke \fBsudo\fR permissions from a .logout
file.
-.IP "\-L" 4
+.IP "\-L" 12
.IX Item "-L"
The \fB\-L\fR (\fIlist\fR defaults) option will list out the parameters
that may be set in a \fIDefaults\fR line along with a short description
for each. This option is useful in conjunction with \fIgrep\fR\|(1).
-.IP "\-l [\fIcommand\fR]" 4
+.IP "\-l [\fIcommand\fR]" 12
.IX Item "-l [command]"
If no \fIcommand\fR is specified, the \fB\-l\fR (\fIlist\fR) option will list
the allowed (and forbidden) commands for the invoking user (or the
fully-qualified path to the command is displayed along with any
command line arguments. If \fIcommand\fR is not allowed, \fBsudo\fR will
exit with a return value of 1.
-.IP "\-P" 4
+.IP "\-P" 12
.IX Item "-P"
The \fB\-P\fR (\fIpreserve\fR \fIgroup vector\fR) option causes \fBsudo\fR to
preserve the invoking user's group vector unaltered. By default,
\&\fBsudo\fR will initialize the group vector to the list of groups the
target user is in. The real and effective group IDs, however, are
still set to match the target user.
-.IP "\-p" 4
-.IX Item "-p"
+.IP "\-p \fIprompt\fR" 12
+.IX Item "-p prompt"
The \fB\-p\fR (\fIprompt\fR) option allows you to override the default
password prompt and use a custom one. The following percent (`\f(CW\*(C`%\*(C'\fR')
escapes are supported:
-.RS 4
+.RS 12
.ie n .IP "%H" 4
.el .IP "\f(CW%H\fR" 4
.IX Item "%H"
.IX Item "%%"
two consecutive \f(CW\*(C`%\*(C'\fR characters are collapsed into a single \f(CW\*(C`%\*(C'\fR character
.RE
-.RS 4
+.RS 12
.RE
-.IP "\-S" 4
+.IP "\-S" 12
.IX Item "-S"
The \fB\-S\fR (\fIstdin\fR) option causes \fBsudo\fR to read the password from
the standard input instead of the terminal device.
-.IP "\-s" 4
+.IP "\-s" 12
.IX Item "-s"
The \fB\-s\fR (\fIshell\fR) option runs the shell specified by the \fI\s-1SHELL\s0\fR
environment variable if it is set or the shell as specified
in \fIpasswd\fR\|(@mansectform@).
-.IP "\-U" 4
-.IX Item "-U"
+.IP "\-U \fIuser\fR" 12
+.IX Item "-U user"
The \fB\-U\fR (\fIother user\fR) option is used in conjunction with the \fB\-l\fR
option to specify the user whose privileges should be listed. Only
root or a user with \fBsudo\fR \f(CW\*(C`ALL\*(C'\fR on the current host may use this
option.
-.IP "\-u" 4
-.IX Item "-u"
+.IP "\-u \fIuser\fR" 12
+.IX Item "-u user"
The \fB\-u\fR (\fIuser\fR) option causes \fBsudo\fR to run the specified
command as a user other than \fIroot\fR. To specify a \fIuid\fR instead
-of a \fIusername\fR, use \fI#uid\fR. When running commands as a \fIuid\fR,
+of a \fIuser name\fR, use \fI#uid\fR. When running commands as a \fIuid\fR,
many shells require that the '#' be escaped with a backslash ('\e').
Note that if the \fItargetpw\fR Defaults option is set (see \fIsudoers\fR\|(@mansectform@))
it is not possible to run commands with a uid not listed in the
password database.
-.IP "\-V" 4
+.IP "\-V" 12
.IX Item "-V"
The \fB\-V\fR (\fIversion\fR) option causes \fBsudo\fR to print the version
number and exit. If the invoking user is already root the \fB\-V\fR
option will print out a list of the defaults \fBsudo\fR was compiled
with as well as the machine's local network addresses.
-.IP "\-v" 4
+.IP "\-v" 12
.IX Item "-v"
If given the \fB\-v\fR (\fIvalidate\fR) option, \fBsudo\fR will update the
user's timestamp, prompting for the user's password if necessary.
This extends the \fBsudo\fR timeout for another \f(CW\*(C`@timeout@\*(C'\fR minutes
(or whatever the timeout is set to in \fIsudoers\fR) but does not run
a command.
-.IP "\-\-" 4
+.IP "\-\-" 12
The \fB\-\-\fR flag indicates that \fBsudo\fR should stop processing command
line arguments. It is most useful in conjunction with the \fB\-s\fR flag.
.PP
\&\fB\s-1LD_LIBRARY_PATH\s0\fR=\fI/usr/local/pkg/lib\fR. Variables passed on the
command line are subject to the same restrictions as normal environment
variables with one important exception. If the \fIsetenv\fR option
-is set in \fIsudoers\fR or the command to be run has the \f(CW\*(C`SETENV\*(C'\fR tag
-set the user may set variables that would overwise be forbidden.
-See \fIsudoers\fR\|(@mansectform@) for more information.
+is set in \fIsudoers\fR, the command to be run has the \f(CW\*(C`SETENV\*(C'\fR tag
+set or the command matched is \f(CW\*(C`ALL\*(C'\fR, the user may set variables
+that would overwise be forbidden. See \fIsudoers\fR\|(@mansectform@) for more information.
.SH "RETURN VALUES"
.IX Header "RETURN VALUES"
Upon successful execution of a program, the return value from \fBsudo\fR
B<sudo> B<-h> | B<-K> | B<-k> | B<-L> | B<-V> | B<-v>
-B<sudo> B<-l> S<[B<-U> I<username>]> S<[B<-u> I<username>|I<#uid>]> [I<command>]
+B<sudo> B<-l> S<[B<-g> I<groupname>|I<#gid>]> S<[B<-U> I<username>]>
+S<[B<-u> I<username>|I<#uid>]> [I<command>]
B<sudo> [B<-bEHPS>] S<[B<-a> I<auth_type>]> S<[B<-C> I<fd>]>
-S<[B<-c> I<class>|I<->]> S<[B<-p> I<prompt>]> S<[B<-u> I<username>|I<#uid>]>
-S<[B<VAR>=I<value>]> S<{B<-i> | B<-s> | I<command>}>
+S<[B<-c> I<class>|I<->]> S<[B<-g> I<groupname>|I<#gid>]> S<[B<-p> I<prompt>]>
+S<[B<-u> I<username>|I<#uid>]> S<[B<VAR>=I<value>]>
+S<{B<-i> | B<-s> | I<command>}>
B<sudoedit> [B<-S>] S<[B<-a> I<auth_type>]> S<[B<-C> I<fd>]>
-S<[B<-c> I<class>|I<->]> S<[B<-p> I<prompt>]> S<[B<-u> I<username>|I<#uid>]>
-file ...
+S<[B<-c> I<class>|I<->]> S<[B<-g> I<groupname>|I<#gid>]> S<[B<-p> I<prompt>]>
+S<[B<-u> I<username>|I<#uid>]> file ...
=head1 DESCRIPTION
user will receive a warning and the edited copy will remain in a
temporary file.
+=item -g I<group>
+
+Normally, B<sudo> sets the primary group to the one specified by
+the passwd database for the user the command is being run as (by
+default, root). The B<-g> (I<group>) option causes B<sudo> to run
+the specified command with the primary group set to I<group>. To
+specify a I<gid> instead of a I<group name>, use I<#gid>. When
+running commands as a I<gid>, many shells require that the '#' be
+escaped with a backslash ('\'). If no B<-u> option is specified,
+the command will be run as the invoking user (not root). In either
+case, the primary group will be set to I<group>.
+
=item -H
The B<-H> (I<HOME>) option sets the C<HOME> environment variable
The B<-u> (I<user>) option causes B<sudo> to run the specified
command as a user other than I<root>. To specify a I<uid> instead
-of a I<username>, use I<#uid>. When running commands as a I<uid>,
+of a I<user name>, use I<#uid>. When running commands as a I<uid>,
many shells require that the '#' be escaped with a backslash ('\').
Note that if the I<targetpw> Defaults option is set (see L<sudoers(5)>)
it is not possible to run commands with a uid not listed in the
* need to be able to substitute values from configure.
*/
#define SUDO_USAGE1 " -h | -K | -k | -L | -V | -v"
-#define SUDO_USAGE2 " -l [-U username] [-u username|#uid] [command]"
-#define SUDO_USAGE3 " [-bEHPS] @BSDAUTH_USAGE@[-C fd] @LOGINCAP_USAGE@[-p prompt] [-u username|#uid] [VAR=value] {-i | -s | <command>}"
-#define SUDO_USAGE4 " -e [-S] @BSDAUTH_USAGE@[-C fd] @LOGINCAP_USAGE@[-p prompt] [-u username|#uid] file ..."
+#define SUDO_USAGE2 " -l [-g groupname|#gid] [-U username] [-u username|#uid] [-g groupname|#gid] [command]"
+#define SUDO_USAGE3 " [-bEHPS] @BSDAUTH_USAGE@[-C fd] @LOGINCAP_USAGE@[-g groupname|#gid] [-p prompt] [-u username|#uid] [-g groupname|#gid] [VAR=value] {-i | -s | <command>}"
+#define SUDO_USAGE4 " -e [-S] @BSDAUTH_USAGE@[-C fd] @LOGINCAP_USAGE@[-g groupname|#gid] [-p prompt] [-u username|#uid] file ..."
#endif /* _SUDO_USAGE_H */
-1.7 September 5, 2007 1
+1.7 November 21, 2007 1
odd number of '!' operators negate the value of the item;
an even number just cancel each other out.
- Runas_List ::= Runas_User |
- Runas_User ',' Runas_List
+ Runas_List ::= Runas_Member |
+ Runas_Member ',' Runas_List
-1.7 September 5, 2007 2
+1.7 November 21, 2007 2
SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
- Runas_User ::= '!'* username |
- '!'* '#'uid |
- '!'* '%'group |
- '!'* +netgroup |
- '!'* Runas_Alias
+ Runas_Member ::= '!'* username |
+ '!'* '#'uid |
+ '!'* '%'group |
+ '!'* +netgroup |
+ '!'* Runas_Alias
A Runas_List is similar to a User_List except that instead
of User_Aliases it can contain Runas_Aliases. Note that
-1.7 September 5, 2007 3
+1.7 November 21, 2007 3
-1.7 September 5, 2007 4
+1.7 November 21, 2007 4
Cmnd_Spec ::= Runas_Spec? Tag_Spec* Cmnd
- Runas_Spec ::= '(' Runas_List ')'
+ Runas_Spec ::= '(' Runas_List? (: Runas_List)? ')'
Tag_Spec ::= ('NOPASSWD:' | 'PASSWD:' | 'NOEXEC:' | 'EXEC:' |
'SETENV:' | 'NOSETENV:' )
R\bRu\bun\bna\bas\bs_\b_S\bSp\bpe\bec\bc
- A Runas_Spec is simply a Runas_List (as defined above)
- enclosed in a set of parentheses. If you do not specify a
- Runas_Spec in the user specification, a default Runas_Spec
- of r\bro\boo\bot\bt will be used. A Runas_Spec sets the default for
- commands that follow it. What this means is that for the
- entry:
+ A Runas_Spec determines the user and/or the group that a
+ command may be run as. A fully-specified Runas_Spec con-
+ sists of two Runas_Lists (as defined above) separated by a
+ colon (':') and enclosed in a set of parentheses. The
+ first Runas_List indicates which users the command may be
+ run as via s\bsu\bud\bdo\bo's -\b-u\bu flag. The second defines a list of
+ groups that can be specified via s\bsu\bud\bdo\bo's -\b-g\bg flag. If both
+ Runas_Lists are specified, the command may be run with any
+ combination of users and groups listed in their respective
+ Runas_Lists. If only the first is specified, the command
+ may be run as any user in the list but no -\b-g\bg flag may be
+ specified. If the first Runas_List is empty but the sec-
+ ond is specified, the command may be run as the invoking
+ user with the group set to any listed in the Runas_List.
+ If no Runas_Spec is specified the command may be run as
+ r\bro\boo\bot\bt and no group may be specified.
+
+ A Runas_Spec sets the default for the commands that follow
+ it. What this means is that for the entry:
+
+
+
+
+1.7 November 21, 2007 5
+
+
+
+
+
+SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
+
dgb boulder = (operator) /bin/ls, /bin/kill, /usr/bin/lprm
dgb boulder = (operator) /bin/ls, (root) /bin/kill, /usr/bin/lprm
Then user d\bdg\bgb\bb is now allowed to run _\b/_\bb_\bi_\bn_\b/_\bl_\bs as o\bop\bpe\ber\bra\bat\bto\bor\br,
+ but _\b/_\bb_\bi_\bn_\b/_\bk_\bi_\bl_\bl and _\b/_\bu_\bs_\br_\b/_\bb_\bi_\bn_\b/_\bl_\bp_\br_\bm as r\bro\boo\bot\bt.
+ We can extend this to allow d\bdg\bgb\bb to run /bin/ls with either
+ the user or group set to o\bop\bpe\ber\bra\bat\bto\bor\br:
+ dgb boulder = (operator : operator) /bin/ls, (root) /bin/kill, \
+ /usr/bin/lprm
-1.7 September 5, 2007 5
-
-
-
-
-
-SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
+ In the following example, user t\btc\bcm\bm may run commands that
+ access a modem device file with the dialer group. Note
+ that in this example only the group will be set, the com-
+ mand still runs as user t\btc\bcm\bm.
-
- but _\b/_\bb_\bi_\bn_\b/_\bk_\bi_\bl_\bl and _\b/_\bu_\bs_\br_\b/_\bb_\bi_\bn_\b/_\bl_\bp_\br_\bm as r\bro\boo\bot\bt.
+ tcm boulder = (:dialer) /usr/bin/tip, /usr/bin/cu, \
+ /usr/local/bin/minicom
T\bTa\bag\bg_\b_S\bSp\bpe\bec\bc
able to run _\b/_\bb_\bi_\bn_\b/_\bk_\bi_\bl_\bl without a password the entry would
be:
+
+
+1.7 November 21, 2007 6
+
+
+
+
+
+SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
+
+
ray rushmore = NOPASSWD: /bin/kill, PASSWD: /bin/ls, /usr/bin/lprm
Note, however, that the PASSWD tag has no effect on users
aaron shanty = NOEXEC: /usr/bin/more, /usr/bin/vi
See the "PREVENTING SHELL ESCAPES" section below for more
-
-
-
-1.7 September 5, 2007 6
-
-
-
-
-
-SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
-
-
details on how NOEXEC works and whether or not it will
work on your system.
way are not subject to the restrictions imposed by
_\be_\bn_\bv_\b__\bc_\bh_\be_\bc_\bk, _\be_\bn_\bv_\b__\bd_\be_\bl_\be_\bt_\be, or _\be_\bn_\bv_\b__\bk_\be_\be_\bp. As such, only trusted
users should be allowed to set variables in this manner.
+ If the command matched is A\bAL\bLL\bL, the SETENV tag is implied
+ for that command; this default may be overridden by use of
+ the UNSETENV tag.
W\bWi\bil\bld\bdc\bca\bar\brd\bds\bs
[...] Matches any character in the specified range.
+
+
+1.7 November 21, 2007 7
+
+
+
+
+
+SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
+
+
[!...] Matches any character n\bno\bot\bt in the specified range.
\x For any character "x", evaluates to "x". This is
It is possible to include other _\bs_\bu_\bd_\bo_\be_\br_\bs files from within
the _\bs_\bu_\bd_\bo_\be_\br_\bs file currently being parsed using the #include
directive, similar to the one used by the C preprocessor.
-
-
-
-1.7 September 5, 2007 7
-
-
-
-
-
-SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
-
-
This is useful, for example, for keeping a site-wide _\bs_\bu_\bd_\bo_\b-
_\be_\br_\bs file in addition to a per-machine local one. For the
sake of this example the site-wide _\bs_\bu_\bd_\bo_\be_\br_\bs will be
comment character and any text after it, up to the end of
the line, are ignored.
+
+
+
+1.7 November 21, 2007 8
+
+
+
+
+
+SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
+
+
The reserved word A\bAL\bLL\bL is a built-in _\ba_\bl_\bi_\ba_\bs that always
causes a match to succeed. It can be used wherever one
might otherwise use a Cmnd_Alias, User_Alias, Runas_Alias,
('\') when used as part of a word (e.g. a username or
hostname): '@', '!', '=', ':', ',', '(', ')', '\'.
-
-
-
-
-1.7 September 5, 2007 8
-
-
-
-
-
-SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
-
-
S\bSU\bUD\bDO\bOE\bER\bRS\bS O\bOP\bPT\bTI\bIO\bON\bNS\bS
s\bsu\bud\bdo\bo's behavior can be modified by Default_Entry lines, as
explained earlier. A list of all supported Defaults
at which s\bsu\bud\bdo\bo begins closing open file
descriptors. This flag is _\bo_\bf_\bf by default.
+
+
+
+1.7 November 21, 2007 9
+
+
+
+
+
+SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
+
+
env_editor If set, v\bvi\bis\bsu\bud\bdo\bo will use the value of the
EDITOR or VISUAL environment variables
before falling back on the default editor
default.
fqdn Set this flag if you want to put fully
-
-
-
-1.7 September 5, 2007 9
-
-
-
-
-
-SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
-
-
qualified hostnames in the _\bs_\bu_\bd_\bo_\be_\br_\bs file.
I.e., instead of myhost you would use
myhost.mydomain.edu. You may still use
ignore_local_sudoers
If set via LDAP, parsing of
@sysconfdir@/sudoers will be skipped.
+
+
+
+1.7 November 21, 2007 10
+
+
+
+
+
+SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
+
+
This is intended for Enterprises that wish
to prevent the usage of local sudoers
files so that only LDAP is used. This
flag is _\bo_\bf_\bf by default.
long_otp_prompt When validating with a One Time Password
-
-
-
-1.7 September 5, 2007 10
-
-
-
-
-
-SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
-
-
(OPT) scheme such as S\bS/\b/K\bKe\bey\by or O\bOP\bPI\bIE\bE, a two-
line prompt is used to make it easier to
cut and paste the challenge to a local
or is explicitly denied. This flag is _\bo_\bf_\bf
by default.
+
+
+1.7 November 21, 2007 11
+
+
+
+
+
+SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
+
+
mail_no_user If set, mail will be sent to the _\bm_\ba_\bi_\bl_\bt_\bo
user if the invoking user is not in the
_\bs_\bu_\bd_\bo_\be_\br_\bs file. This flag is _\bo_\bn by default.
preserve_groups By default s\bsu\bud\bdo\bo will initialize the group
vector to the list of groups the target
-
-
-
-1.7 September 5, 2007 11
-
-
-
-
-
-SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
-
-
user is in. When _\bp_\br_\be_\bs_\be_\br_\bv_\be_\b__\bg_\br_\bo_\bu_\bp_\bs is set,
the user's existing group vector is left
unaltered. The real and effective group
by default.
rootpw If set, s\bsu\bud\bdo\bo will prompt for the root
+
+
+
+1.7 November 21, 2007 12
+
+
+
+
+
+SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
+
+
password instead of the password of the
invoking user. This flag is _\bo_\bf_\bf by
default.
since some programs (including the RCS
revision control system) use LOGNAME to
determine the real identity of the user,
- it may be desirable to change this
-
-
-
-1.7 September 5, 2007 12
-
-
-
-
-
-SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
-
-
- behavior. This can be done by negating
- the set_logname option. Note that if the
+ it may be desirable to change this behav-
+ ior. This can be done by negating the
+ set_logname option. Note that if the
_\be_\bn_\bv_\b__\br_\be_\bs_\be_\bt option has not been disabled,
entries in the _\be_\bn_\bv_\b__\bk_\be_\be_\bp list will override
the value of _\bs_\be_\bt_\b__\bl_\bo_\bg_\bn_\ba_\bm_\be. This flag is
stay_setuid Normally, when s\bsu\bud\bdo\bo executes a command the
real and effective UIDs are set to the
+
+
+
+1.7 November 21, 2007 13
+
+
+
+
+
+SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
+
+
target user (root by default). This
option changes that behavior such that the
real UID is left as the invoking user's
as the user running it. With this flag
enabled, s\bsu\bud\bdo\bo will use a file named for
the tty the user is logged in on in that
-
-
-
-1.7 September 5, 2007 13
-
-
-
-
-
-SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
-
-
directory. This flag is _\bo_\bf_\bf by default.
use_loginclass If set, s\bsu\bud\bdo\bo will apply the defaults spec-
log. This value is used to decide when to
wrap lines for nicer log files. This has
no effect on the syslog log file, only the
+
+
+
+1.7 November 21, 2007 14
+
+
+
+
+
+SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
+
+
file log. The default is 80 (use 0 or
negate the option to disable word wrap).
S\bSt\btr\bri\bin\bng\bgs\bs:
badpass_message Message that is displayed if a user enters
-
-
-
-1.7 September 5, 2007 14
-
-
-
-
-
-SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
-
-
an incorrect password. The default is
Sorry, try again. unless insults are
enabled.
_\bn_\bo_\be_\bx_\be_\bc functionality on systems that sup-
port LD_PRELOAD or its equivalent.
Defaults to
- _\b/_\bu_\bs_\br_\b/_\bl_\bo_\bc_\ba_\bl_\b/_\bl_\bi_\bb_\be_\bx_\be_\bc_\b/_\bs_\bu_\bd_\bo_\b__\bn_\bo_\be_\bx_\be_\bc.
+ _\b/_\bu_\bs_\br_\b/_\bl_\bo_\bc_\ba_\bl_\b/_\bl_\bi_\bb_\be_\bx_\be_\bc_\b/_\bs_\bu_\bd_\bo_\b__\bn_\bo_\be_\bx_\be_\bc_\b._\bs_\bo.
passprompt The default prompt to use when asking for
a password; can be overridden via the -\b-p\bp
+
+
+
+1.7 November 21, 2007 15
+
+
+
+
+
+SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
+
+
option or the SUDO_PROMPT environment
variable. The following percent (`%')
escapes are supported:
runas_default The default user to run commands as if the
-\b-u\bu flag is not specified on the command
-
-
-
-1.7 September 5, 2007 15
-
-
-
-
-
-SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
-
-
line. This defaults to root. Note that
if _\br_\bu_\bn_\ba_\bs_\b__\bd_\be_\bf_\ba_\bu_\bl_\bt is set it m\bmu\bus\bst\bt occur
before any Runas_Alias specifications.
be printed along with the password prompt. It
has the following possible values:
+
+
+1.7 November 21, 2007 16
+
+
+
+
+
+SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
+
+
always Always lecture the user.
never Never lecture the user.
current host must have the NOPASSWD
flag set to avoid entering a password.
-
-
-1.7 September 5, 2007 16
-
-
-
-
-
-SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
-
-
always The user must always enter a password
to use the -\b-l\bl flag.
mail. Defaults to the path to sendmail found
at configure time.
+
+
+
+1.7 November 21, 2007 17
+
+
+
+
+
+SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
+
+
mailto Address to send warning and error mail to.
The address should be enclosed in double
quotes (") to protect against s\bsu\bud\bdo\bo interpret-
current host must have the NOPASSWD
flag set to avoid entering a password.
-
-
-
-1.7 September 5, 2007 17
-
-
-
-
-
-SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
-
-
always The user must always enter a password
to use the -\b-v\bv flag.
gle value without double-quotes. The list
can be replaced, added to, deleted from,
or disabled by using the =, +=, -=, and !
+
+
+
+1.7 November 21, 2007 18
+
+
+
+
+
+SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
+
+
operators respectively. Regardless of
whether the env_reset option is enabled or
disabled, variables specified by env_check
env_keep Environment variables to be preserved in
the user's environment when the _\be_\bn_\bv_\b__\br_\be_\bs_\be_\bt
option is in effect. This allows fine-
-
-
-
-1.7 September 5, 2007 18
-
-
-
-
-
-SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
-
-
grained control over the environment
s\bsu\bud\bdo\bo-spawned processes will receive. The
argument may be a double-quoted, space-
Below are example _\bs_\bu_\bd_\bo_\be_\br_\bs entries. Admittedly, some of
these are a bit contrived. First, we define our _\ba_\bl_\bi_\ba_\bs_\be_\bs:
+
+
+
+1.7 November 21, 2007 19
+
+
+
+
+
+SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
+
+
# User alias specification
User_Alias FULLTIMERS = millert, mikef, dowdy
User_Alias PARTTIMERS = bostley, jwfox, crawl
Host_Alias SERVERS = master, mail, www, ns
Host_Alias CDROM = orion, perseus, hercules
-
-
-
-
-
-
-
-
-
-
-1.7 September 5, 2007 19
-
-
-
-
-
-SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
-
-
# Cmnd alias specification
Cmnd_Alias DUMPS = /usr/bin/mt, /usr/sbin/dump, /usr/sbin/rdump,\
/usr/sbin/restore, /usr/sbin/rrestore
Defaults@SERVERS log_year, logfile=/var/log/sudo.log
Defaults!PAGERS noexec
+
+
+
+1.7 November 21, 2007 20
+
+
+
+
+
+SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
+
+
The _\bU_\bs_\be_\br _\bs_\bp_\be_\bc_\bi_\bf_\bi_\bc_\ba_\bt_\bi_\bo_\bn is the part that actually deter-
mines who may run what.
any command on any host but they must authenticate them-
selves first (since the entry lacks the NOPASSWD tag).
-
-
-1.7 September 5, 2007 20
-
-
-
-
-
-SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
-
-
jack CSNETS = ALL
The user j\bja\bac\bck\bk may run any command on the machines in the
bob SPARC = (OP) ALL : SGI = (OP) ALL
+
+
+1.7 November 21, 2007 21
+
+
+
+
+
+SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
+
+
The user b\bbo\bob\bb may run anything on the _\bS_\bP_\bA_\bR_\bC and _\bS_\bG_\bI
machines as any user listed in the _\bO_\bP Runas_Alias (r\bro\boo\bot\bt
and o\bop\bpe\ber\bra\bat\bto\bor\br).
fred ALL = (DB) NOPASSWD: ALL
The user f\bfr\bre\bed\bd can run commands as any user in the _\bD_\bB
-
-
-
-1.7 September 5, 2007 21
-
-
-
-
-
-SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
-
-
Runas_Alias (o\bor\bra\bac\bcl\ble\be or s\bsy\byb\bba\bas\bse\be) without giving a password.
john ALPHA = /usr/bin/su [!-]*, !/usr/bin/su *root*
(will, wendy, and wim), may run any command as user www
(which owns the web pages) or simply _\bs_\bu(1) to www.
+
+
+
+1.7 November 21, 2007 22
+
+
+
+
+
+SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
+
+
ALL CDROM = NOPASSWD: /sbin/umount /CDROM,\
/sbin/mount -o nosuid\,nodev /dev/cd0a /CDROM
bill ALL = ALL, !SU, !SHELLS
Doesn't really prevent b\bbi\bil\bll\bl from running the commands
- listed in _\bS_\bU or _\bS_\bH_\bE_\bL_\bL_\bS since he can simply copy those
-
-
-
-1.7 September 5, 2007 22
-
-
-
-
-
-SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
-
-
- commands to a different name, or use a shell escape from
- an editor or other program. Therefore, these kind of
+ listed in _\bS_\bU or _\bS_\bH_\bE_\bL_\bL_\bS since he can simply copy those com-
+ mands to a different name, or use a shell escape from an
+ editor or other program. Therefore, these kind of
restrictions should be considered advisory at best (and
reinforced by policy).
that this applies only to native dynamically-
linked executables. Statically-linked executa-
bles and foreign executables running under
+
+
+
+1.7 November 21, 2007 23
+
+
+
+
+
+SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
+
+
binary emulation are not affected.
To tell whether or not s\bsu\bud\bdo\bo supports _\bn_\bo_\be_\bx_\be_\bc, you
_\bn_\bo_\be_\bx_\be_\bc will work at compile-time. _\bn_\bo_\be_\bx_\be_\bc should
work on SunOS, Solaris, *BSD, Linux, IRIX, Tru64
UNIX, MacOS X, and HP-UX 11.x. It is known n\bno\bot\bt
-
-
-
-1.7 September 5, 2007 23
-
-
-
-
-
-SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
-
-
to work on AIX and UnixWare. _\bn_\bo_\be_\bx_\be_\bc is expected
to work on most operating systems that support
the LD_PRELOAD environment variable. Check your
C\bCA\bAV\bVE\bEA\bAT\bTS\bS
The _\bs_\bu_\bd_\bo_\be_\br_\bs file should a\bal\blw\bwa\bay\bys\bs be edited by the v\bvi\bis\bsu\bud\bdo\bo
- command which locks the file and does grammatical check-
- ing. It is imperative that _\bs_\bu_\bd_\bo_\be_\br_\bs be free of syntax
+ command which locks the file and does grammatical
+
+
+
+1.7 November 21, 2007 24
+
+
+
+
+
+SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
+
+
+ checking. It is imperative that _\bs_\bu_\bd_\bo_\be_\br_\bs be free of syntax
errors since s\bsu\bud\bdo\bo will not run with a syntactically incor-
rect _\bs_\bu_\bd_\bo_\be_\br_\bs file.
man/listinfo/sudo-users to subscribe or search the
archives.
-
-
-1.7 September 5, 2007 24
-
-
-
-
-
-SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4)
-
-
D\bDI\bIS\bSC\bCL\bLA\bAI\bIM\bME\bER\bR
s\bsu\bud\bdo\bo is provided ``AS IS'' and any express or implied war-
ranties, including, but not limited to, the implied war-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-1.7 September 5, 2007 25
+1.7 November 21, 2007 25
.\" ========================================================================
.\"
.IX Title "SUDOERS @mansectform@"
-.TH SUDOERS @mansectform@ "September 5, 2007" "1.7" "MAINTENANCE COMMANDS"
+.TH SUDOERS @mansectform@ "November 21, 2007" "1.7" "MAINTENANCE COMMANDS"
.SH "NAME"
sudoers \- list of which users may execute what
.SH "DESCRIPTION"
the value of the item; an even number just cancel each other out.
.PP
.Vb 2
-\& Runas_List ::= Runas_User |
-\& Runas_User ',' Runas_List
+\& Runas_List ::= Runas_Member |
+\& Runas_Member ',' Runas_List
.Ve
.PP
.Vb 5
-\& Runas_User ::= '!'* username |
-\& '!'* '#'uid |
-\& '!'* '%'group |
-\& '!'* +netgroup |
-\& '!'* Runas_Alias
+\& Runas_Member ::= '!'* username |
+\& '!'* '#'uid |
+\& '!'* '%'group |
+\& '!'* +netgroup |
+\& '!'* Runas_Alias
.Ve
.PP
A \f(CW\*(C`Runas_List\*(C'\fR is similar to a \f(CW\*(C`User_List\*(C'\fR except that instead
.Ve
.PP
.Vb 1
-\& Runas_Spec ::= '(' Runas_List ')'
+\& Runas_Spec ::= '(' Runas_List? (: Runas_List)? ')'
.Ve
.PP
.Vb 2
Let's break that down into its constituent parts:
.Sh "Runas_Spec"
.IX Subsection "Runas_Spec"
-A \f(CW\*(C`Runas_Spec\*(C'\fR is simply a \f(CW\*(C`Runas_List\*(C'\fR (as defined above)
-enclosed in a set of parentheses. If you do not specify a
-\&\f(CW\*(C`Runas_Spec\*(C'\fR in the user specification, a default \f(CW\*(C`Runas_Spec\*(C'\fR
-of \fBroot\fR will be used. A \f(CW\*(C`Runas_Spec\*(C'\fR sets the default for
-commands that follow it. What this means is that for the entry:
+A \f(CW\*(C`Runas_Spec\*(C'\fR determines the user and/or the group that a command
+may be run as. A fully-specified \f(CW\*(C`Runas_Spec\*(C'\fR consists of two
+\&\f(CW\*(C`Runas_List\*(C'\fRs (as defined above) separated by a colon (':') and
+enclosed in a set of parentheses. The first \f(CW\*(C`Runas_List\*(C'\fR indicates
+which users the command may be run as via \fBsudo\fR's \fB\-u\fR flag.
+The second defines a list of groups that can be specified via
+\&\fBsudo\fR's \fB\-g\fR flag. If both \f(CW\*(C`Runas_List\*(C'\fRs are specified, the
+command may be run with any combination of users and groups listed
+in their respective \f(CW\*(C`Runas_List\*(C'\fRs. If only the first is specified,
+the command may be run as any user in the list but no \fB\-g\fR flag
+may be specified. If the first \f(CW\*(C`Runas_List\*(C'\fR is empty but the
+second is specified, the command may be run as the invoking user
+with the group set to any listed in the \f(CW\*(C`Runas_List\*(C'\fR. If no
+\&\f(CW\*(C`Runas_Spec\*(C'\fR is specified the command may be run as \fBroot\fR and
+no group may be specified.
+.PP
+A \f(CW\*(C`Runas_Spec\*(C'\fR sets the default for the commands that follow it.
+What this means is that for the entry:
.PP
.Vb 1
\& dgb boulder = (operator) /bin/ls, /bin/kill, /usr/bin/lprm
.PP
Then user \fBdgb\fR is now allowed to run \fI/bin/ls\fR as \fBoperator\fR,
but \fI/bin/kill\fR and \fI/usr/bin/lprm\fR as \fBroot\fR.
+.PP
+We can extend this to allow \fBdgb\fR to run \f(CW\*(C`/bin/ls\*(C'\fR with either
+the user or group set to \fBoperator\fR:
+.PP
+.Vb 2
+\& dgb boulder = (operator : operator) /bin/ls, (root) /bin/kill, \e
+\& /usr/bin/lprm
+.Ve
+.PP
+In the following example, user \fBtcm\fR may run commands that access
+a modem device file with the dialer group. Note that in this example
+only the group will be set, the command still runs as user \fBtcm\fR.
+.PP
+.Vb 2
+\& tcm boulder = (:dialer) /usr/bin/tip, /usr/bin/cu, \e
+\& /usr/local/bin/minicom
+.Ve
.Sh "Tag_Spec"
.IX Subsection "Tag_Spec"
A command may have zero or more tags associated with it. There are
environment variables set on the command line way are not subject
to the restrictions imposed by \fIenv_check\fR, \fIenv_delete\fR, or
\&\fIenv_keep\fR. As such, only trusted users should be allowed to set
-variables in this manner.
+variables in this manner. If the command matched is \fB\s-1ALL\s0\fR, the
+\&\f(CW\*(C`SETENV\*(C'\fR tag is implied for that command; this default may
+be overridden by use of the \f(CW\*(C`UNSETENV\*(C'\fR tag.
.Sh "Wildcards"
.IX Subsection "Wildcards"
\&\fBsudo\fR allows shell-style \fIwildcards\fR (aka meta or glob characters)
zero or more '!' operators. An odd number of '!' operators negate
the value of the item; an even number just cancel each other out.
- Runas_List ::= Runas_User |
- Runas_User ',' Runas_List
+ Runas_List ::= Runas_Member |
+ Runas_Member ',' Runas_List
- Runas_User ::= '!'* username |
- '!'* '#'uid |
- '!'* '%'group |
- '!'* +netgroup |
- '!'* Runas_Alias
+ Runas_Member ::= '!'* username |
+ '!'* '#'uid |
+ '!'* '%'group |
+ '!'* +netgroup |
+ '!'* Runas_Alias
A C<Runas_List> is similar to a C<User_List> except that instead
of C<User_Alias>es it can contain C<Runas_Alias>es. Note that
Cmnd_Spec ::= Runas_Spec? Tag_Spec* Cmnd
- Runas_Spec ::= '(' Runas_List ')'
+ Runas_Spec ::= '(' Runas_List? (: Runas_List)? ')'
Tag_Spec ::= ('NOPASSWD:' | 'PASSWD:' | 'NOEXEC:' | 'EXEC:' |
'SETENV:' | 'NOSETENV:' )
=head2 Runas_Spec
-A C<Runas_Spec> is simply a C<Runas_List> (as defined above)
-enclosed in a set of parentheses. If you do not specify a
-C<Runas_Spec> in the user specification, a default C<Runas_Spec>
-of B<root> will be used. A C<Runas_Spec> sets the default for
-commands that follow it. What this means is that for the entry:
+A C<Runas_Spec> determines the user and/or the group that a command
+may be run as. A fully-specified C<Runas_Spec> consists of two
+C<Runas_List>s (as defined above) separated by a colon (':') and
+enclosed in a set of parentheses. The first C<Runas_List> indicates
+which users the command may be run as via B<sudo>'s B<-u> flag.
+The second defines a list of groups that can be specified via
+B<sudo>'s B<-g> flag. If both C<Runas_List>s are specified, the
+command may be run with any combination of users and groups listed
+in their respective C<Runas_List>s. If only the first is specified,
+the command may be run as any user in the list but no B<-g> flag
+may be specified. If the first C<Runas_List> is empty but the
+second is specified, the command may be run as the invoking user
+with the group set to any listed in the C<Runas_List>. If no
+C<Runas_Spec> is specified the command may be run as B<root> and
+no group may be specified.
+
+A C<Runas_Spec> sets the default for the commands that follow it.
+What this means is that for the entry:
dgb boulder = (operator) /bin/ls, /bin/kill, /usr/bin/lprm
Then user B<dgb> is now allowed to run F</bin/ls> as B<operator>,
but F</bin/kill> and F</usr/bin/lprm> as B<root>.
+We can extend this to allow B<dgb> to run C</bin/ls> with either
+the user or group set to B<operator>:
+
+ dgb boulder = (operator : operator) /bin/ls, (root) /bin/kill, \
+ /usr/bin/lprm
+
+In the following example, user B<tcm> may run commands that access
+a modem device file with the dialer group. Note that in this example
+only the group will be set, the command still runs as user B<tcm>.
+
+ tcm boulder = (:dialer) /usr/bin/tip, /usr/bin/cu, \
+ /usr/local/bin/minicom
+
=head2 Tag_Spec
A command may have zero or more tags associated with it. There are
struct cmndspec *cs;
struct privilege *priv;
struct userspec *us;
- char *p, *grfile, *pwfile, *uflag, hbuf[MAXHOSTNAMELEN];
+ char *p, *grfile, *pwfile, *runas_user, hbuf[MAXHOSTNAMELEN];
int ch, dflag, rval, matched;
#ifdef YYDEBUG
extern int yydebug;
Argc = argc;
dflag = 0;
- grfile = pwfile = uflag = NULL;
+ grfile = pwfile = runas_user = NULL;
while ((ch = getopt(argc, argv, "dg:h:p:u:")) != -1) {
switch (ch) {
case 'd':
pwfile = optarg;
break;
case 'u':
- uflag = optarg;
- user_runas = &uflag;
+ runas_user = optarg;
break;
default:
usage();
/* Initialize default values. */
init_defaults();
- if (**user_runas == '#') {
- if ((runas_pw = sudo_getpwuid(atoi(*user_runas + 1))) == NULL)
- runas_pw = sudo_fakepwnam(*user_runas);
+ if (*runas_user == '#') {
+ if ((runas_pw = sudo_getpwuid(atoi(runas_user + 1))) == NULL)
+ runas_pw = sudo_fakepwnam(runas_user);
} else {
- if ((runas_pw = sudo_getpwnam(*user_runas)) == NULL)
- errorx(1, "no passwd entry for %s!", *user_runas);
+ if ((runas_pw = sudo_getpwnam(runas_user)) == NULL)
+ errorx(1, "no passwd entry for %s!", runas_user);
}
/* Load ip addr/mask for each interface. */
if (hostlist_matches(&priv->hostlist) == ALLOW) {
puts("\thost matched");
tq_foreach_rev(&priv->cmndlist, cs) {
- if (runaslist_matches(&cs->runaslist) == ALLOW) {
+ if (runaslist_matches(&cs->runasuserlist,
+ &cs->runasgrouplist) == ALLOW) {
puts("\trunas matched");
rval = cmnd_matches(cs->cmnd);
if (rval != UNSPEC)
tq_foreach_fwd(&p->cmndlist, cs) {
if (cs != tq_first(&p->cmndlist))
fputs(", ", stdout);
- if (!tq_empty(&cs->runaslist)) {
+ /* XXX - runasgrouplist too */
+ if (!tq_empty(&cs->runasuserlist)) {
fputs("(", stdout);
- tq_foreach_fwd(&cs->runaslist, m) {
- if (m != tq_first(&cs->runaslist))
+ tq_foreach_fwd(&cs->runasuserlist, m) {
+ if (m != tq_first(&cs->runasuserlist))
fputs(", ", stdout);
print_member(m);
}
sp->tpath, sp->path);
/* Clean slate for each parse */
- user_runas = NULL;
init_defaults();
init_parser(sp->path, quiet);
}
}
tq_foreach_fwd(&priv->cmndlist, cs) {
- tq_foreach_fwd(&cs->runaslist, m) {
+ tq_foreach_fwd(&cs->runasuserlist, m) {
if (m->type == RUNASALIAS) {
if (find_alias(m->name, m->type) == NULL) {
fprintf(stderr,
(void) alias_remove(m->name, m->type);
}
tq_foreach_fwd(&priv->cmndlist, cs) {
- tq_foreach_fwd(&cs->runaslist, m) {
+ tq_foreach_fwd(&cs->runasuserlist, m) {
if (m->type == RUNASALIAS)
(void) alias_remove(m->name, m->type);
}
O\bOP\bPT\bTI\bIO\bON\bNS\bS
v\bvi\bis\bsu\bud\bdo\bo accepts the following command line options:
- -c Enable c\bch\bhe\bec\bck\bk-\b-o\bon\bnl\bly\by mode. The existing _\bs_\bu_\bd_\bo_\be_\br_\bs file
- will be checked for syntax and a message will be
- printed to the standard output detailing the status of
- _\bs_\bu_\bd_\bo_\be_\br_\bs. If the syntax check completes successfully,
- v\bvi\bis\bsu\bud\bdo\bo will exit with a value of 0. If a syntax error
- is encountered, v\bvi\bis\bsu\bud\bdo\bo will exit with a value of 1.
+ -c Enable c\bch\bhe\bec\bck\bk-\b-o\bon\bnl\bly\by mode. The existing _\bs_\bu_\bd_\bo_\be_\br_\bs
+ file will be checked for syntax and a message
+ will be printed to the standard output detail-
+ ing the status of _\bs_\bu_\bd_\bo_\be_\br_\bs. If the syntax
+ check completes successfully, v\bvi\bis\bsu\bud\bdo\bo will exit
+ with a value of 0. If a syntax error is
+ encountered, v\bvi\bis\bsu\bud\bdo\bo will exit with a value of
+ 1.
- -f Specify and alternate _\bs_\bu_\bd_\bo_\be_\br_\bs file location. With
-
-1.7 August 15, 2007 1
+1.7 October 20, 2007 1
VISUDO(1m) MAINTENANCE COMMANDS VISUDO(1m)
- this option v\bvi\bis\bsu\bud\bdo\bo will edit (or check) the _\bs_\bu_\bd_\bo_\be_\br_\bs
- file of your choice, instead of the default,
- _\b/_\be_\bt_\bc_\b/_\bs_\bu_\bd_\bo_\be_\br_\bs. The lock file used is the specified
- _\bs_\bu_\bd_\bo_\be_\br_\bs file with ".tmp" appended to it.
+ -f _\bs_\bu_\bd_\bo_\be_\br_\bs Specify and alternate _\bs_\bu_\bd_\bo_\be_\br_\bs file location.
+ With this option v\bvi\bis\bsu\bud\bdo\bo will edit (or check)
+ the _\bs_\bu_\bd_\bo_\be_\br_\bs file of your choice, instead of
+ the default, _\b/_\be_\bt_\bc_\b/_\bs_\bu_\bd_\bo_\be_\br_\bs. The lock file used
+ is the specified _\bs_\bu_\bd_\bo_\be_\br_\bs file with ".tmp"
+ appended to it.
- -q Enable q\bqu\bui\bie\bet\bt mode. In this mode details about syntax
- errors are not printed. This option is only useful
- when combined with the -\b-c\bc flag.
+ -q Enable q\bqu\bui\bie\bet\bt mode. In this mode details about
+ syntax errors are not printed. This option is
+ only useful when combined with the -\b-c\bc flag.
- -s Enable s\bst\btr\bri\bic\bct\bt checking of the _\bs_\bu_\bd_\bo_\be_\br_\bs file. If an
- alias is used before it is defined, v\bvi\bis\bsu\bud\bdo\bo will con-
- sider this a parse error. Note that it is not possi-
- ble to differentiate between an alias and a hostname
- or username that consists solely of uppercase letters,
- digits, and the underscore ('_') character.
+ -s Enable s\bst\btr\bri\bic\bct\bt checking of the _\bs_\bu_\bd_\bo_\be_\br_\bs file.
+ If an alias is used before it is defined,
+ v\bvi\bis\bsu\bud\bdo\bo will consider this a parse error. Note
+ that it is not possible to differentiate
+ between an alias and a hostname or username
+ that consists solely of uppercase letters,
+ digits, and the underscore ('_') character.
- -V The -\b-V\bV (version) option causes v\bvi\bis\bsu\bud\bdo\bo to print its
- version number and exit.
+ -V The -\b-V\bV (version) option causes v\bvi\bis\bsu\bud\bdo\bo to print
+ its version number and exit.
E\bEN\bNV\bVI\bIR\bRO\bON\bNM\bME\bEN\bNT\bT
- The following environment variables are used only if
- v\bvi\bis\bsu\bud\bdo\bo was configured with the _\b-_\b-_\bw_\bi_\bt_\bh_\b-_\be_\bn_\bv_\b-_\be_\bd_\bi_\bt_\bo_\br option:
+ The following environment variables may be consulted
+ depending on the value of the _\be_\bd_\bi_\bt_\bo_\br and _\be_\bn_\bv_\b__\be_\bd_\bi_\bt_\bo_\br _\bs_\bu_\bd_\bo_\b-
+ _\be_\br_\bs variables:
VISUAL Invoked by visudo as the editor to use
will not complain). In -\b-s\bs (strict) mode these are
errors, not warnings.
- Warning: unused {User,Runas,Host,Cmnd}_Alias
- The specified {User,Runas,Host,Cmnd}_Alias was defined
- but never used. You may wish to comment out or remove
-
-1.7 August 15, 2007 2
+1.7 October 20, 2007 2
VISUDO(1m) MAINTENANCE COMMANDS VISUDO(1m)
+ Warning: unused {User,Runas,Host,Cmnd}_Alias
+ The specified {User,Runas,Host,Cmnd}_Alias was defined
+ but never used. You may wish to comment out or remove
the unused alias. In -\b-s\bs (strict) mode this is an
error, not a warning.
-
-
-
-1.7 August 15, 2007 3
+1.7 October 20, 2007 3
.\" ========================================================================
.\"
.IX Title "VISUDO @mansectsu@"
-.TH VISUDO @mansectsu@ "August 15, 2007" "1.7" "MAINTENANCE COMMANDS"
+.TH VISUDO @mansectsu@ "October 20, 2007" "1.7" "MAINTENANCE COMMANDS"
.SH "NAME"
visudo \- edit the sudoers file
.SH "SYNOPSIS"
.SH "OPTIONS"
.IX Header "OPTIONS"
\&\fBvisudo\fR accepts the following command line options:
-.IP "\-c" 4
+.IP "\-c" 12
.IX Item "-c"
Enable \fBcheck-only\fR mode. The existing \fIsudoers\fR file will be
checked for syntax and a message will be printed to the
If the syntax check completes successfully, \fBvisudo\fR will
exit with a value of 0. If a syntax error is encountered,
\&\fBvisudo\fR will exit with a value of 1.
-.IP "\-f" 4
-.IX Item "-f"
+.IP "\-f \fIsudoers\fR" 12
+.IX Item "-f sudoers"
Specify and alternate \fIsudoers\fR file location. With this option
\&\fBvisudo\fR will edit (or check) the \fIsudoers\fR file of your choice,
instead of the default, \fI@sysconfdir@/sudoers\fR. The lock file used
is the specified \fIsudoers\fR file with \*(L".tmp\*(R" appended to it.
-.IP "\-q" 4
+.IP "\-q" 12
.IX Item "-q"
Enable \fBquiet\fR mode. In this mode details about syntax errors
are not printed. This option is only useful when combined with
the \fB\-c\fR flag.
-.IP "\-s" 4
+.IP "\-s" 12
.IX Item "-s"
Enable \fBstrict\fR checking of the \fIsudoers\fR file. If an alias is
used before it is defined, \fBvisudo\fR will consider this a parse
error. Note that it is not possible to differentiate between an
alias and a hostname or username that consists solely of uppercase
letters, digits, and the underscore ('_') character.
-.IP "\-V" 4
+.IP "\-V" 12
.IX Item "-V"
The \fB\-V\fR (version) option causes \fBvisudo\fR to print its version number
and exit.
.SH "ENVIRONMENT"
.IX Header "ENVIRONMENT"
-The following environment variables are used only if \fBvisudo\fR
-was configured with the \fI\-\-with\-env\-editor\fR option:
+The following environment variables may be consulted depending on
+the value of the \fIeditor\fR and \fIenv_editor\fR \fIsudoers\fR variables:
.ie n .IP "\*(C`VISUAL\*(C'" 16
.el .IP "\f(CW\*(C`VISUAL\*(C'\fR" 16
.IX Item "VISUAL"