From 7a01b10fee894dea7ecb3252886912eab41e9693 Mon Sep 17 00:00:00 2001 From: Bdale Garbee Date: Fri, 22 Jul 2011 14:53:40 +0200 Subject: [PATCH] Imported Upstream version 1.8.1p2 --- ChangeLog | 6212 ++++++++++++----- INSTALL | 84 +- MANIFEST | 279 + Makefile.in | 623 +- NEWS | 77 +- PORTING | 85 - README | 20 +- aclocal.m4 | 34 +- auth/sudo_auth.c | 266 - auth/sudo_auth.h | 115 - common/Makefile.in | 112 + aix.c => common/aix.c | 19 +- alloc.c => common/alloc.c | 61 +- common/atobool.c | 81 + fileops.c => common/fileops.c | 27 +- common/fmt_string.c | 64 + lbuf.c => common/lbuf.c | 86 +- list.c => common/list.c | 27 +- term.c => common/term.c | 131 +- zero_bytes.c => common/zero_bytes.c | 7 +- compat/Makefile.in | 162 + {emul => compat}/charclass.h | 4 +- closefrom.c => compat/closefrom.c | 9 +- compat/dlfcn.h | 43 + compat/dlopen.c | 133 + fnmatch.c => compat/fnmatch.c | 32 +- {emul => compat}/fnmatch.h | 4 +- getcwd.c => compat/getcwd.c | 4 +- getline.c => compat/getline.c | 30 +- setsid.c => compat/getprogname.c | 43 +- glob.c => compat/glob.c | 148 +- {emul => compat}/glob.h | 16 +- isblank.c => compat/isblank.c | 5 +- memrchr.c => compat/memrchr.c | 7 +- mksiglist.c => compat/mksiglist.c | 8 +- mksiglist.h => compat/mksiglist.h | 0 mkstemps.c => compat/mktemp.c | 120 +- nanosleep.c => compat/nanosleep.c | 8 +- compat/regress/fnmatch/fnm_test.c | 76 + compat/regress/fnmatch/fnm_test.in | 5 + compat/regress/glob/files | 47 + compat/regress/glob/globtest.c | 213 + compat/regress/glob/globtest.in | 64 + compat/setenv.c | 83 + siglist.in => compat/siglist.in | 0 snprintf.c => compat/snprintf.c | 83 +- strlcat.c => compat/strlcat.c | 8 +- strlcpy.c => compat/strlcpy.c | 8 +- strsignal.c => compat/strsignal.c | 5 +- {emul => compat}/timespec.h | 2 +- compat/unsetenv.c | 76 + {emul => compat}/utime.h | 7 +- utimes.c => compat/utimes.c | 13 +- config.h.in | 147 +- configure | 2639 ++++--- configure.in | 638 +- HISTORY => doc/HISTORY | 30 +- LICENSE => doc/LICENSE | 28 - doc/Makefile.in | 196 + TROUBLESHOOTING => doc/TROUBLESHOOTING | 0 UPGRADE => doc/UPGRADE | 41 +- doc/history.pod | 79 + doc/license.pod | 78 + sample.pam => doc/sample.pam | 0 doc/sample.sudo.conf | 42 + sample.sudoers => doc/sample.sudoers | 0 sample.syslog.conf => doc/sample.syslog.conf | 0 .../schema.ActiveDirectory | 0 schema.OpenLDAP => doc/schema.OpenLDAP | 0 schema.iPlanet => doc/schema.iPlanet | 0 doc/sudo.cat | 547 ++ sudo.man.in => doc/sudo.man.in | 507 +- sudo.man.pl => doc/sudo.man.pl | 0 doc/sudo.pod | 700 ++ doc/sudo_plugin.cat | 1033 +++ doc/sudo_plugin.man.in | 1282 ++++ doc/sudo_plugin.pod | 1246 ++++ sudoers.cat => doc/sudoers.cat | 640 +- sudoers.ldap.cat => doc/sudoers.ldap.cat | 189 +- .../sudoers.ldap.man.in | 4 +- sudoers.ldap.pod => doc/sudoers.ldap.pod | 0 sudoers.man.in => doc/sudoers.man.in | 342 +- sudoers.man.pl => doc/sudoers.man.pl | 0 sudoers.pod => doc/sudoers.pod | 344 +- sudoreplay.cat => doc/sudoreplay.cat | 89 +- sudoreplay.man.in => doc/sudoreplay.man.in | 22 +- sudoreplay.pod => doc/sudoreplay.pod | 20 +- visudo.cat => doc/visudo.cat | 58 +- visudo.man.in => doc/visudo.man.in | 6 +- visudo.pod => doc/visudo.pod | 2 +- getprogname.c | 46 - gettime.c | 45 - include/Makefile.in | 82 + alloc.h => include/alloc.h | 16 +- error.h => include/error.h | 13 +- include/fileops.h | 33 + lbuf.h => include/lbuf.h | 13 +- list.h => include/list.h | 20 +- missing.h => include/missing.h | 157 +- include/sudo_plugin.h | 125 + iolog.c | 404 -- ltmain.sh | 1747 +++-- m4/libtool.m4 | 998 +-- m4/ltoptions.m4 | 13 +- m4/ltversion.m4 | 10 +- m4/lt~obsolete.m4 | 12 +- nonunix.h | 46 - pathnames.h.in | 15 + plugins/sample/Makefile.in | 123 + plugins/sample/sample_plugin.c | 511 ++ plugins/sample/sample_plugin.sym | 2 + plugins/sample_group/Makefile.in | 126 + plugins/sample_group/getgrent.c | 184 + plugins/sample_group/plugin_test.c | 210 + plugins/sample_group/sample_group.c | 142 + plugins/sample_group/sample_group.sym | 1 + plugins/sudoers/Makefile.in | 453 ++ aixcrypt.exp => plugins/sudoers/aixcrypt.exp | 0 alias.c => plugins/sudoers/alias.c | 31 +- audit.c => plugins/sudoers/audit.c | 26 +- {auth => plugins/sudoers/auth}/API | 64 +- {auth => plugins/sudoers/auth}/afs.c | 9 +- {auth => plugins/sudoers/auth}/aix_auth.c | 16 +- {auth => plugins/sudoers/auth}/bsdauth.c | 26 +- {auth => plugins/sudoers/auth}/dce.c | 15 +- {auth => plugins/sudoers/auth}/fwtk.c | 31 +- {auth => plugins/sudoers/auth}/kerb4.c | 14 +- {auth => plugins/sudoers/auth}/kerb5.c | 38 +- {auth => plugins/sudoers/auth}/pam.c | 74 +- {auth => plugins/sudoers/auth}/passwd.c | 15 +- {auth => plugins/sudoers/auth}/rfc1938.c | 16 +- {auth => plugins/sudoers/auth}/secureware.c | 14 +- {auth => plugins/sudoers/auth}/securid.c | 19 +- {auth => plugins/sudoers/auth}/securid5.c | 27 +- {auth => plugins/sudoers/auth}/sia.c | 47 +- plugins/sudoers/auth/sudo_auth.c | 339 + plugins/sudoers/auth/sudo_auth.h | 99 + boottime.c => plugins/sudoers/boottime.c | 41 +- bsm_audit.c => plugins/sudoers/bsm_audit.c | 2 +- bsm_audit.h => plugins/sudoers/bsm_audit.h | 2 +- check.c => plugins/sudoers/check.c | 163 +- def_data.c => plugins/sudoers/def_data.c | 20 +- def_data.h => plugins/sudoers/def_data.h | 52 +- def_data.in => plugins/sudoers/def_data.in | 15 +- defaults.c => plugins/sudoers/defaults.c | 167 +- defaults.h => plugins/sudoers/defaults.h | 17 +- env.c => plugins/sudoers/env.c | 289 +- find_path.c => plugins/sudoers/find_path.c | 12 +- getdate.c => plugins/sudoers/getdate.c | 6 +- getdate.y => plugins/sudoers/getdate.y | 6 +- getspwuid.c => plugins/sudoers/getspwuid.c | 9 +- goodpath.c => plugins/sudoers/goodpath.c | 8 +- gram.c => plugins/sudoers/gram.c | 216 +- gram.h => plugins/sudoers/gram.h | 0 gram.y => plugins/sudoers/gram.y | 50 +- plugins/sudoers/group_plugin.c | 222 + ins_2001.h => plugins/sudoers/ins_2001.h | 0 .../sudoers/ins_classic.h | 0 ins_csops.h => plugins/sudoers/ins_csops.h | 0 ins_goons.h => plugins/sudoers/ins_goons.h | 0 insults.h => plugins/sudoers/insults.h | 0 plugins/sudoers/interfaces.c | 114 + interfaces.h => plugins/sudoers/interfaces.h | 9 +- plugins/sudoers/iolog.c | 670 ++ plugins/sudoers/iolog_path.c | 266 + ldap.c => plugins/sudoers/ldap.c | 363 +- .../sudoers/linux_audit.c | 25 - .../sudoers/linux_audit.h | 2 - logging.c => plugins/sudoers/logging.c | 200 +- logging.h => plugins/sudoers/logging.h | 15 +- match.c => plugins/sudoers/match.c | 123 +- mkdefaults => plugins/sudoers/mkdefaults | 4 +- parse.c => plugins/sudoers/parse.c | 95 +- parse.h => plugins/sudoers/parse.h | 46 +- plugins/sudoers/plugin_error.c | 112 + pwutil.c => plugins/sudoers/pwutil.c | 83 +- redblack.c => plugins/sudoers/redblack.c | 63 +- redblack.h => plugins/sudoers/redblack.h | 19 +- .../regress/iolog_path/check_iolog_path.c | 205 + plugins/sudoers/regress/iolog_path/data | 72 + plugins/sudoers/regress/parser/check_fill.c | 187 + plugins/sudoers/regress/sudoers/test1.in | 8 + plugins/sudoers/regress/sudoers/test1.out.ok | 6 + plugins/sudoers/regress/sudoers/test1.toke.ok | 6 + plugins/sudoers/regress/sudoers/test2.in | 60 + plugins/sudoers/regress/sudoers/test2.out.ok | 42 + plugins/sudoers/regress/sudoers/test2.toke.ok | 60 + plugins/sudoers/regress/sudoers/test3.in | 6 + plugins/sudoers/regress/sudoers/test3.out.ok | 9 + plugins/sudoers/regress/sudoers/test3.toke.ok | 6 + plugins/sudoers/regress/sudoers/test4.in | 7 + plugins/sudoers/regress/sudoers/test4.out.ok | 6 + plugins/sudoers/regress/sudoers/test4.toke.ok | 5 + plugins/sudoers/regress/sudoers/test5.in | 3 + plugins/sudoers/regress/sudoers/test5.out.ok | 4 + plugins/sudoers/regress/sudoers/test5.toke.ok | 3 + plugins/sudoers/regress/sudoers/test6.in | 15 + plugins/sudoers/regress/sudoers/test6.out.ok | 14 + plugins/sudoers/regress/sudoers/test6.toke.ok | 15 + plugins/sudoers/regress/sudoers/test7.in | 7 + plugins/sudoers/regress/sudoers/test7.out.ok | 4 + plugins/sudoers/regress/sudoers/test7.toke.ok | 7 + plugins/sudoers/regress/sudoers/test8.in | 8 + plugins/sudoers/regress/sudoers/test8.out.ok | 7 + plugins/sudoers/regress/sudoers/test8.toke.ok | 7 + .../sudoers/regress/testsudoers/test1.out.ok | 8 + plugins/sudoers/regress/testsudoers/test1.sh | 10 + plugins/sudoers/set_perms.c | 972 +++ sudo_nss.c => plugins/sudoers/sudo_nss.c | 45 +- sudo_nss.h => plugins/sudoers/sudo_nss.h | 27 +- plugins/sudoers/sudoers.c | 1462 ++++ plugins/sudoers/sudoers.h | 338 + sudoers.in => plugins/sudoers/sudoers.in | 0 plugins/sudoers/sudoers.sym | 2 + sudoers2ldif => plugins/sudoers/sudoers2ldif | 0 plugins/sudoers/sudoers_version.h | 53 + sudoreplay.c => plugins/sudoers/sudoreplay.c | 372 +- .../sudoers/testsudoers.c | 178 +- timestr.c => plugins/sudoers/timestr.c | 8 +- plugins/sudoers/toke.c | 3643 ++++++++++ toke.h => plugins/sudoers/toke.h | 23 +- toke.l => plugins/sudoers/toke.l | 92 +- toke_util.c => plugins/sudoers/toke_util.c | 25 +- tsgetgrpw.c => plugins/sudoers/tsgetgrpw.c | 48 +- plugins/sudoers/tsgetgrpw.h | 72 + visudo.c => plugins/sudoers/visudo.c | 202 +- set_perms.c | 663 -- sigaction.c | 141 - src/Makefile.in | 189 + src/conversation.c | 139 + error.c => src/error.c | 53 +- exec.c => src/exec.c | 201 +- exec_pty.c => src/exec_pty.c | 316 +- get_pty.c => src/get_pty.c | 39 +- src/load_plugins.c | 232 + interfaces.c => src/net_ifs.c | 226 +- parse_args.c => src/parse_args.c | 303 +- src/preload.c | 31 + selinux.c => src/selinux.c | 62 +- sesh.c => src/sesh.c | 4 +- src/sudo.c | 1205 ++++ src/sudo.h | 233 + sudo_edit.c => src/sudo_edit.c | 210 +- sudo_exec.h => src/sudo_exec.h | 27 +- sudo_noexec.c => src/sudo_noexec.c | 32 +- src/sudo_plugin_int.h | 85 + sudo_usage.h.in => src/sudo_usage.h.in | 15 +- tgetpass.c => src/tgetpass.c | 78 +- src/ttysize.c | 67 + src/utmp.c | 356 + strcasecmp.c | 93 - strerror.c | 44 - sudo.c | 1335 ---- sudo.cat | 660 -- sudo.h | 372 - sudo.pod | 702 -- sudo.pp | 1 + toke.c | 3623 ---------- vasgroups.c | 321 - zlib/Makefile.in | 123 + 260 files changed, 32661 insertions(+), 18677 deletions(-) create mode 100644 MANIFEST delete mode 100644 PORTING delete mode 100644 auth/sudo_auth.c delete mode 100644 auth/sudo_auth.h create mode 100644 common/Makefile.in rename aix.c => common/aix.c (93%) rename alloc.c => common/alloc.c (87%) create mode 100644 common/atobool.c rename fileops.c => common/fileops.c (90%) create mode 100644 common/fmt_string.c rename lbuf.c => common/lbuf.c (79%) rename list.c => common/list.c (92%) rename term.c => common/term.c (54%) rename zero_bytes.c => common/zero_bytes.c (88%) create mode 100644 compat/Makefile.in rename {emul => compat}/charclass.h (92%) rename closefrom.c => compat/closefrom.c (96%) create mode 100644 compat/dlfcn.h create mode 100644 compat/dlopen.c rename fnmatch.c => compat/fnmatch.c (92%) rename {emul => compat}/fnmatch.h (95%) rename getcwd.c => compat/getcwd.c (99%) rename getline.c => compat/getline.c (82%) rename setsid.c => compat/getprogname.c (66%) rename glob.c => compat/glob.c (85%) rename {emul => compat}/glob.h (94%) rename isblank.c => compat/isblank.c (90%) rename memrchr.c => compat/memrchr.c (89%) rename mksiglist.c => compat/mksiglist.c (91%) rename mksiglist.h => compat/mksiglist.h (100%) rename mkstemps.c => compat/mktemp.c (75%) rename nanosleep.c => compat/nanosleep.c (89%) create mode 100644 compat/regress/fnmatch/fnm_test.c create mode 100644 compat/regress/fnmatch/fnm_test.in create mode 100644 compat/regress/glob/files create mode 100644 compat/regress/glob/globtest.c create mode 100644 compat/regress/glob/globtest.in create mode 100644 compat/setenv.c rename siglist.in => compat/siglist.in (100%) rename snprintf.c => compat/snprintf.c (93%) rename strlcat.c => compat/strlcat.c (91%) rename strlcpy.c => compat/strlcpy.c (91%) rename strsignal.c => compat/strsignal.c (93%) rename {emul => compat}/timespec.h (92%) create mode 100644 compat/unsetenv.c rename {emul => compat}/utime.h (88%) rename utimes.c => compat/utimes.c (87%) rename HISTORY => doc/HISTORY (83%) rename LICENSE => doc/LICENSE (70%) create mode 100644 doc/Makefile.in rename TROUBLESHOOTING => doc/TROUBLESHOOTING (100%) rename UPGRADE => doc/UPGRADE (85%) create mode 100644 doc/history.pod create mode 100644 doc/license.pod rename sample.pam => doc/sample.pam (100%) create mode 100644 doc/sample.sudo.conf rename sample.sudoers => doc/sample.sudoers (100%) rename sample.syslog.conf => doc/sample.syslog.conf (100%) rename schema.ActiveDirectory => doc/schema.ActiveDirectory (100%) rename schema.OpenLDAP => doc/schema.OpenLDAP (100%) rename schema.iPlanet => doc/schema.iPlanet (100%) create mode 100644 doc/sudo.cat rename sudo.man.in => doc/sudo.man.in (57%) rename sudo.man.pl => doc/sudo.man.pl (100%) create mode 100644 doc/sudo.pod create mode 100644 doc/sudo_plugin.cat create mode 100644 doc/sudo_plugin.man.in create mode 100644 doc/sudo_plugin.pod rename sudoers.cat => doc/sudoers.cat (81%) rename sudoers.ldap.cat => doc/sudoers.ldap.cat (94%) rename sudoers.ldap.man.in => doc/sudoers.ldap.man.in (99%) rename sudoers.ldap.pod => doc/sudoers.ldap.pod (100%) rename sudoers.man.in => doc/sudoers.man.in (83%) rename sudoers.man.pl => doc/sudoers.man.pl (100%) rename sudoers.pod => doc/sudoers.pod (82%) rename sudoreplay.cat => doc/sudoreplay.cat (91%) rename sudoreplay.man.in => doc/sudoreplay.man.in (94%) rename sudoreplay.pod => doc/sudoreplay.pod (92%) rename visudo.cat => doc/visudo.cat (94%) rename visudo.man.in => doc/visudo.man.in (98%) rename visudo.pod => doc/visudo.pod (99%) delete mode 100644 getprogname.c delete mode 100644 gettime.c create mode 100644 include/Makefile.in rename alloc.h => include/alloc.h (83%) rename error.h => include/error.h (78%) create mode 100644 include/fileops.h rename lbuf.h => include/lbuf.h (77%) rename list.h => include/list.h (81%) rename missing.h => include/missing.h (67%) create mode 100644 include/sudo_plugin.h delete mode 100644 iolog.c mode change 100644 => 100755 ltmain.sh delete mode 100644 nonunix.h create mode 100644 plugins/sample/Makefile.in create mode 100644 plugins/sample/sample_plugin.c create mode 100644 plugins/sample/sample_plugin.sym create mode 100644 plugins/sample_group/Makefile.in create mode 100644 plugins/sample_group/getgrent.c create mode 100644 plugins/sample_group/plugin_test.c create mode 100644 plugins/sample_group/sample_group.c create mode 100644 plugins/sample_group/sample_group.sym create mode 100644 plugins/sudoers/Makefile.in rename aixcrypt.exp => plugins/sudoers/aixcrypt.exp (100%) rename alias.c => plugins/sudoers/alias.c (90%) rename audit.c => plugins/sudoers/audit.c (76%) rename {auth => plugins/sudoers/auth}/API (65%) rename {auth => plugins/sudoers/auth}/afs.c (93%) rename {auth => plugins/sudoers/auth}/aix_auth.c (85%) rename {auth => plugins/sudoers/auth}/bsdauth.c (88%) rename {auth => plugins/sudoers/auth}/dce.c (95%) rename {auth => plugins/sudoers/auth}/fwtk.c (86%) rename {auth => plugins/sudoers/auth}/kerb4.c (91%) rename {auth => plugins/sudoers/auth}/kerb5.c (91%) rename {auth => plugins/sudoers/auth}/pam.c (86%) rename {auth => plugins/sudoers/auth}/passwd.c (91%) rename {auth => plugins/sudoers/auth}/rfc1938.c (93%) rename {auth => plugins/sudoers/auth}/secureware.c (90%) rename {auth => plugins/sudoers/auth}/securid.c (88%) rename {auth => plugins/sudoers/auth}/securid5.c (91%) rename {auth => plugins/sudoers/auth}/sia.c (77%) create mode 100644 plugins/sudoers/auth/sudo_auth.c create mode 100644 plugins/sudoers/auth/sudo_auth.h rename boottime.c => plugins/sudoers/boottime.c (83%) rename bsm_audit.c => plugins/sudoers/bsm_audit.c (98%) rename bsm_audit.h => plugins/sudoers/bsm_audit.h (93%) rename check.c => plugins/sudoers/check.c (85%) rename def_data.c => plugins/sudoers/def_data.c (95%) rename def_data.h => plugins/sudoers/def_data.h (82%) rename def_data.in => plugins/sudoers/def_data.in (95%) rename defaults.c => plugins/sudoers/defaults.c (84%) rename defaults.h => plugins/sudoers/defaults.h (89%) rename env.c => plugins/sudoers/env.c (76%) rename find_path.c => plugins/sudoers/find_path.c (91%) rename getdate.c => plugins/sudoers/getdate.c (99%) rename getdate.y => plugins/sudoers/getdate.y (99%) rename getspwuid.c => plugins/sudoers/getspwuid.c (97%) rename goodpath.c => plugins/sudoers/goodpath.c (93%) rename gram.c => plugins/sudoers/gram.c (94%) rename gram.h => plugins/sudoers/gram.h (100%) rename gram.y => plugins/sudoers/gram.y (94%) create mode 100644 plugins/sudoers/group_plugin.c rename ins_2001.h => plugins/sudoers/ins_2001.h (100%) rename ins_classic.h => plugins/sudoers/ins_classic.h (100%) rename ins_csops.h => plugins/sudoers/ins_csops.h (100%) rename ins_goons.h => plugins/sudoers/ins_goons.h (100%) rename insults.h => plugins/sudoers/insults.h (100%) create mode 100644 plugins/sudoers/interfaces.c rename interfaces.h => plugins/sudoers/interfaces.h (89%) create mode 100644 plugins/sudoers/iolog.c create mode 100644 plugins/sudoers/iolog_path.c rename ldap.c => plugins/sudoers/ldap.c (89%) rename linux_audit.c => plugins/sudoers/linux_audit.c (80%) rename linux_audit.h => plugins/sudoers/linux_audit.h (90%) rename logging.c => plugins/sudoers/logging.c (84%) rename logging.h => plugins/sudoers/logging.h (82%) rename match.c => plugins/sudoers/match.c (88%) rename mkdefaults => plugins/sudoers/mkdefaults (97%) rename parse.c => plugins/sudoers/parse.c (89%) rename parse.h => plugins/sudoers/parse.h (80%) create mode 100644 plugins/sudoers/plugin_error.c rename pwutil.c => plugins/sudoers/pwutil.c (93%) rename redblack.c => plugins/sudoers/redblack.c (90%) rename redblack.h => plugins/sudoers/redblack.h (71%) create mode 100644 plugins/sudoers/regress/iolog_path/check_iolog_path.c create mode 100644 plugins/sudoers/regress/iolog_path/data create mode 100644 plugins/sudoers/regress/parser/check_fill.c create mode 100644 plugins/sudoers/regress/sudoers/test1.in create mode 100644 plugins/sudoers/regress/sudoers/test1.out.ok create mode 100644 plugins/sudoers/regress/sudoers/test1.toke.ok create mode 100644 plugins/sudoers/regress/sudoers/test2.in create mode 100644 plugins/sudoers/regress/sudoers/test2.out.ok create mode 100644 plugins/sudoers/regress/sudoers/test2.toke.ok create mode 100644 plugins/sudoers/regress/sudoers/test3.in create mode 100644 plugins/sudoers/regress/sudoers/test3.out.ok create mode 100644 plugins/sudoers/regress/sudoers/test3.toke.ok create mode 100644 plugins/sudoers/regress/sudoers/test4.in create mode 100644 plugins/sudoers/regress/sudoers/test4.out.ok create mode 100644 plugins/sudoers/regress/sudoers/test4.toke.ok create mode 100644 plugins/sudoers/regress/sudoers/test5.in create mode 100644 plugins/sudoers/regress/sudoers/test5.out.ok create mode 100644 plugins/sudoers/regress/sudoers/test5.toke.ok create mode 100644 plugins/sudoers/regress/sudoers/test6.in create mode 100644 plugins/sudoers/regress/sudoers/test6.out.ok create mode 100644 plugins/sudoers/regress/sudoers/test6.toke.ok create mode 100644 plugins/sudoers/regress/sudoers/test7.in create mode 100644 plugins/sudoers/regress/sudoers/test7.out.ok create mode 100644 plugins/sudoers/regress/sudoers/test7.toke.ok create mode 100644 plugins/sudoers/regress/sudoers/test8.in create mode 100644 plugins/sudoers/regress/sudoers/test8.out.ok create mode 100644 plugins/sudoers/regress/sudoers/test8.toke.ok create mode 100644 plugins/sudoers/regress/testsudoers/test1.out.ok create mode 100755 plugins/sudoers/regress/testsudoers/test1.sh create mode 100644 plugins/sudoers/set_perms.c rename sudo_nss.c => plugins/sudoers/sudo_nss.c (90%) rename sudo_nss.h => plugins/sudoers/sudo_nss.h (57%) create mode 100644 plugins/sudoers/sudoers.c create mode 100644 plugins/sudoers/sudoers.h rename sudoers.in => plugins/sudoers/sudoers.in (100%) create mode 100644 plugins/sudoers/sudoers.sym rename sudoers2ldif => plugins/sudoers/sudoers2ldif (100%) create mode 100644 plugins/sudoers/sudoers_version.h rename sudoreplay.c => plugins/sudoers/sudoreplay.c (77%) rename testsudoers.c => plugins/sudoers/testsudoers.c (79%) rename timestr.c => plugins/sudoers/timestr.c (90%) create mode 100644 plugins/sudoers/toke.c rename toke.h => plugins/sudoers/toke.h (69%) rename toke.l => plugins/sudoers/toke.l (95%) rename toke_util.c => plugins/sudoers/toke_util.c (94%) rename tsgetgrpw.c => plugins/sudoers/tsgetgrpw.c (89%) create mode 100644 plugins/sudoers/tsgetgrpw.h rename visudo.c => plugins/sudoers/visudo.c (89%) delete mode 100644 set_perms.c delete mode 100644 sigaction.c create mode 100644 src/Makefile.in create mode 100644 src/conversation.c rename error.c => src/error.c (68%) rename exec.c => src/exec.c (78%) rename exec_pty.c => src/exec_pty.c (81%) rename get_pty.c => src/get_pty.c (84%) create mode 100644 src/load_plugins.c rename interfaces.c => src/net_ifs.c (62%) rename parse_args.c => src/parse_args.c (60%) create mode 100644 src/preload.c rename selinux.c => src/selinux.c (87%) rename sesh.c => src/sesh.c (94%) create mode 100644 src/sudo.c create mode 100644 src/sudo.h rename sudo_edit.c => src/sudo_edit.c (66%) rename sudo_exec.h => src/sudo_exec.h (59%) rename sudo_noexec.c => src/sudo_noexec.c (84%) create mode 100644 src/sudo_plugin_int.h rename sudo_usage.h.in => src/sudo_usage.h.in (66%) rename tgetpass.c => src/tgetpass.c (80%) create mode 100644 src/ttysize.c create mode 100644 src/utmp.c delete mode 100644 strcasecmp.c delete mode 100644 strerror.c delete mode 100644 sudo.c delete mode 100644 sudo.cat delete mode 100644 sudo.h delete mode 100644 sudo.pod delete mode 100644 toke.c delete mode 100644 vasgroups.c create mode 100644 zlib/Makefile.in diff --git a/ChangeLog b/ChangeLog index 5efe57d..5eaab26 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,874 +1,1600 @@ +2011-05-04 Todd C. Miller + + * Don't let the fnmatch/glob macros expand the function prototype. + [d449e9a8f447] <1.8> + +2011-05-03 Todd C. Miller + + * Resolve namespace collisions on HP-UX ia64 and possibly others by + adding a rpl_ prefix to our fnmatch and glob replacements and + #defining rpl_foo to foo in the header files. + [d23889375b21] <1.8> + +2011-04-29 Todd C. Miller + + * Split ALL, ROLE and TYPE into their own actions. Since you can only + have #ifdefs inside of braces, ROLE and TYPE use a naughty goto in + the non-SELinux case. This is safe because the actions are in one + big switch() statement. + [0bd9b7e37ab1] <1.8> + + * Fix regexp for matching a CIDR-style IPv4 netmask. From Marc Espie. + [8dec97b359e0] <1.8> + + * askpass moved from sudoers to sudo.conf in sudo 1.8.0 + [1001d87d82ed] <1.8> + + * Remove obsolete warning about runas_default and ordering. Move + syslog facility and priority lists into the section where the + relevant options are described. + [1286b9624021] <1.8> + +2011-04-26 Todd C. Miller + + * Fix SIA support; we no longer have access to the real argc and argv + so allocate space for a fake one and use the argv passed to the + plugin with "sudo" for argv[0]. + [7c11eeffb91c] <1.8> + + * Remove useless realloc when trying to get the buffer size right. + [58128e7f4e28] <1.8> + + * Be explicit when setting euid to 0 before call to setreuid(0, 0) + [95769a564ab8] <1.8> + +2011-04-18 Todd C. Miller + + * NEWS: + sudo 1.8.1p1 updates + [de3d688b5bb1] <1.8> + + * configure, configure.in: + Need to do checks for krb5_verify_user, krb5_init_secure_context and + krb5_get_init_creds_opt_alloc regardless of whether or + notkrb5-config is present. + [456c4a9cd5d6] <1.8> + +2011-04-15 Todd C. Miller + + * Work around weird AIX saved uid semantics on setuid() and + setreuid(). On AIX, setuid() will only set the saved uid if the euid + is already 0. + [5d0a69e9d181] <1.8> + 2011-04-14 Todd C. Miller - * sudo.pp: - update copyright year - [edf691539a65] [tip] <1.7> + * update copyright year + [fa8da6d55783] <1.8> - * toke.c, toke.l: - Treat a missing includedir like an empty one and do not return an + * Treat a missing includedir like an empty one and do not return an error. - [9c770ff2d0bc] <1.7> + [5fd9fe004728] <1.8> 2011-04-12 Todd C. Miller - * pp: - Fix ARCH setting in cross-compile Solaris packages. - [057d743bd1a2] <1.7> + * Fix ARCH setting in cross-compile Solaris packages. + [8ce40940f6c9] <1.8> - * sudo.pp: - Fix aix version setting. - [1a2621321f5c] <1.7> + * Fix aix version setting. + [02a9e25d46ba] <1.8> - * ldap.c: - Remove extraneous parens in LDAP filter when sudoers_search_filter + * Remove extraneous parens in LDAP filter when sudoers_search_filter is enabled that causes a search error. From Matthew Thomas. - [7a5a2d021d32] <1.7> + [b67be9b51ec6] <1.8> + +2011-04-11 Todd C. Miller + + * Correct sizeof() to fix test failure. + [a11b89fd13f9] <1.8> + + * "install" target should depend on "install-dirs". Fixes "make -j" + problem and closes bz #487. From Chris Coleman. + [06ab0558f848] <1.8> 2011-04-09 Todd C. Miller * .hgtags: - Added tag SUDO_1_7_6 for changeset fafbb7b0aea2 - [6f5c74a8a6ac] <1.7> + Added tag SUDO_1_8_1 for changeset 0ed6281995f0 + [543d41a163e9] <1.8> - * configure, configure.in, sudo.cat, sudo.man.in, sudoers.cat, - sudoers.ldap.cat, sudoers.ldap.man.in, sudoers.man.in, - sudoreplay.cat, sudoreplay.man.in, visudo.cat, visudo.man.in: - regen for 1.7.6 - [fafbb7b0aea2] [SUDO_1_7_6] <1.7> + * doc/sudo.cat, doc/sudo.man.in, doc/sudo_plugin.cat, + doc/sudo_plugin.man.in, doc/sudoers.cat, doc/sudoers.ldap.cat, + doc/sudoers.ldap.man.in, doc/sudoers.man.in, doc/sudoreplay.cat, + doc/sudoreplay.man.in, doc/visudo.cat, doc/visudo.man.in: + Regen man pages for 1.8.1 + [0ed6281995f0] [SUDO_1_8_1] <1.8> - * sudo.cat, sudo.man.in: - regen man pages for 1.7.6 - [94d851285f31] <1.7> +2011-04-07 Todd C. Miller + + * Add HAVE_RFC1938_SKEYCHALLENGE + [c0d7eb39799d] <1.8> 2011-04-06 Todd C. Miller + * Mention plugin loading and libgcc changes + [b74929cba37c] <1.8> + + * Load plugins after parsing arguments and potentially printing the + version. That way, an error loading or initializing a plugin + doesn't break "sudo -h" or "sudo -V". + [c1ecb5979cf0] <1.8> + + * Makefile.in: + When using a sub-shell to invoke the sub-make, exec make instead of + running it inside the shell to avoid an extra process. + [9439f016c993] <1.8> + + * Stop testing unspecified behavior in fnmatch Make glob test more + portable + [87a91d76fbff] <1.8> + + * No need to add current dir to include path and having it breaks the + test programs that expect to get the system glob.h and fnmatch.h + [3ae7f9e7b710] <1.8> + + * configure, configure.in: + Fix and document --with-plugindir; partially from Diego Elio Petteno + [0220a0c2606f] <1.8> + + * Fix fnmatch and glob tests to not use hard-coded flag values in the + input file. Link test programs with libreplace so we get our + replacement verions as needed. + [66bab80241e0] <1.8> + + * Makefile.in: + If make in a subdir fails, fail the target in the upper level + Makefile too. Adapted from a patch from Diego Elio Petteno + [bc35b7813507] <1.8> + + * configure, configure.in: + Add check for NetBSD-style 4-argument skeychallenge() as Gentoo also + has this. Adapted from a patch from Diego Elio Petteno + [bb6228f484b9] <1.8> + + * Make SUDOERS_LDFLAGS reference $(LDFLAGS) instead of using @LDFLAGS@ + directly. + [47e6d5fadc6d] <1.8> + * configure, configure.in: Fix warnings when -without-skey, --without-opie, --without-kerb4, --without-kerb5 or --without-SecurID were specified. - [83a99d369286] <1.7> + [1b75035dd129] <1.8> + + * Add plugins/sudoers/sudoers_version.h + [1d470c6033ca] <1.8> + + * configure, configure.in: + Back out the --with-libpath addition to SUDOERS_LDFLAGS since that + now include LDFLAGS in the sudoers Makefile.in. Add missing settng + of @LDFLAGS@ in plugin Makefile.in files. + [dd237f43aa12] <1.8> 2011-04-05 Todd C. Miller - * NEWS: - Mention %#gid support in User_List and Runas_List - [8ff14765d7df] <1.7> + * Mention %#gid support in User_List and Runas_List + [37e259b9181b] <1.8> - * sudoers.pod: - Merge SETENV and NOSETENV description from 1.8 - [dd44e79b53a0] <1.7> + * Keep track of sudoers grammar version and report it in the -V + output. + [0e0b891dd8a4] <1.8> + + * Add multiple inclusion guard + [ec6884f51ea8] <1.8> + + * configure, configure.in: + The --with-libpath option now adds to SUDOERS_LDFLAGS as well as + LDFLAGS. Remove old -static hack for HP-UX < 9. Add LTLDFLAGS and + set it to -Wc,-static-libgcc if not using GNU ld so we don't + have a dependency on the shared libgcc in sudoers.so. + [28d03f3eb0d2] <1.8> + + * Fix typo; from Petr Uzel + [d19b9bd92bd3] <1.8> 2011-04-01 Todd C. Miller - * testsudoers.c: - In dump-only mode, use "root" as the default username instead of + * In dump-only mode, use "root" as the default username instead of "nobody" as the latter may not be available on all systems. - [8082b8a1374c] <1.7> + [b304111616dd] <1.8> 2011-03-31 Todd C. Miller - * testsudoers.c: - Fix setting of user_args - [0669612feeb1] <1.7> + * Remove NewArgv/NewArgc, they are no longer needed. + [c0a36a42a68c] <1.8> - * toke.c, toke.l: - Add '!' token to lex tracing - [7738d002a8d0] <1.7> + * Fix setting of user_args + [529e79ea95d1] <1.8> - * toke.c, toke.l: - Avoid using pre or post increment in a parameter to a ctype(3) + * Add '!' token to lex tracing + [aef295d428e7] <1.8> + + * Use group bin in test, not wheel as most systems have the bin group + but the same is no longer true of wheel. + [350347f09c1a] <1.8> + + * Avoid using pre or post increment in a parameter to a ctype(3) function as it might be a macro that causes the increment to happen more than once. - [2d23161e06dc] <1.7> + [8a94ebdd53b8] <1.8> 2011-03-30 Todd C. Miller - * sudo.pp: - Strip off the beta or release candidate version when building AIX + * Strip off the beta or release candidate version when building AIX packages. - [246ebb79e64f] <1.7> + [00ad950764e2] <1.8> - * aix.c: - getuserattr(user, ...) will fall back to the "default" entry + * configure, configure.in: + We need to include OSDEFS in CFLAGS when doing the utmp/utmpx + structure checks for glibc which only has __e_termination visible + when _GNU_SOURCE is *not* defined. + [1d58420a4a4a] <1.8> + + * getuserattr(user, ...) will fall back to the "default" entry automatically, there's no need to check "default" manually. - [dd233ca1092a] <1.7> + [cefffa82967d] <1.8> + + * Document parser changes. + [5038238f60eb] <1.8> 2011-03-29 Todd C. Miller - * UPGRADE: - Document parser changes. - [f767c045e6c0] <1.7> + * Makefile.in: + If there is an existing sudoers file, only install if it passes a + syntax check. + [b1e4c9c56fe0] <1.8> - * testsudoers.c: - Add runasgroup support to testsudoers - [23f060665d23] <1.7> + * Add runasgroup support to testsudoers + [30838590e9de] <1.8> - * testsudoers.c: - More useful exit codes: + * For "make check", keep going even if a test fails. + [d3a72f67227e] <1.8> + + * More useful exit codes: * 0 - parsed OK and command matched. * 1 - parse error * 2 - command not matched * 3 - command denied - [bda610d9f6da] <1.7> - - * Makefile.in: - If there is an existing sudoers file, only install if it passes a - syntax check. - [189eaeea562e] <1.7> + [59301e0769cd] <1.8> - * sudoers.pod: - Document %#gid, and %:#nonunix_gid syntax. - [59e7df4c91e4] <1.7> + * Document %#gid, and %:#nonunix_gid syntax. + [39ee15af58e9] <1.8> - * pwutil.c: - Add support to user_in_group() for treating group names that begin + * Add support to user_in_group() for treating group names that begin with a '#' as gids. - [3926017fbf95] <1.7> + [0eb19980cf5f] <1.8> + + * configure, configure.in: + Add explicit check for struct utmpx.ut_exit.e_termination and struct + utmpx.ut_exit.__e_termination. HP-UX uses the latter. Only update + ut_exit if we detect one or the other. + [ab5b665fc04b] <1.8> 2011-03-28 Todd C. Miller - * aclocal.m4: - Quote first argument to AC_DEFUN(); from Elan Ruusamae - [a245e4891bab] <1.7> + * Add back missing #include of config.h + [9c82bec81018] <1.8> + + * Avoid a NULL deref on unrecognized escapes. Collapse %% -> % like + strftime() does. + [1ae630470f8a] <1.8> + + * Quote first argument to AC_DEFUN(); from Elan Ruusamae + [c467e9e3b399] <1.8> 2011-03-27 Todd C. Miller - * toke.c, toke.l: - Use bitwise AND instead of modulus to check for length being odd. A - newline in the middle of a string is an error unless a line + * add new sudoers tests + [05f2a0924acc] <1.8> + + * Add test for a newline in the middle of a string when no line continuation character is used. - [37a7f1fc54b7] <1.7> + [24b79be5822b] <1.8> - * gram.c, toke.c: - Add missing include of config.h - [b13da7baee1e] <1.7> + * Use bitwise AND instead of modulus to check for length being odd. A + newline in the middle of a string is an error unless a line + continuation character is used. + [65c468599688] <1.8> - * gram.c, gram.y, toke.c, toke.l: - Move lexer globals initialization into init_lexer. - [b7c124212d05] <1.7> + * Move lexer globals initialization into init_lexer. + [07a1171a1853] <1.8> - * toke.c, toke.l: - Fix a potential crash when a non-regular file is present in an + * Fix a potential crash when a non-regular file is present in an includedir. Fixes bz #452 - [f1209a710607] <1.7> + [5057cb9516e4] <1.8> - * pp: - On some Linux systems, "uname -p" contains detailed processor info + * On some Linux systems, "uname -p" contains detailed processor info so check "uname -m" first and then "uname -p" if needed. Recognize PLD Linux. - [83af85a391df] <1.7> + [56226c84a060] <1.8> - * toke.c, toke.l: - Make an empty group or netgroup a syntax error. - [e88aa7b31a43] <1.7> +2011-03-25 Todd C. Miller - * toke.c, toke.l: - Allow a group ID in the User_Spec. - [3e58bc732e33] <1.7> + * Don't need all sudoers.h here. + [43b6ae5999c5] <1.8> - * toke.c, toke.l: - Return an error for the empty string when a word is expected. Allow + * Print sudo version early, in case policy plugin init fails. + [620f2d0ec4b1] <1.8> + +2011-03-24 Todd C. Miller + + * Update to match change in input. + [69540f84721d] <1.8> + + * Make an empty group or netgroup a syntax error. + [4b85bddc494e] <1.8> + + * An empty group or netgroup should be a syntax error. + [6ec796972eff] <1.8> + + * Check that uids work in per-user and per-runas Defaults Check that + uids and gids work in a Command_Spec + [68cf62353420] <1.8> + + * Test empty string in User_Alias and Command_Spec + [017d487c31be] <1.8> + + * Allow a group ID in the User_Spec. + [37e0bf69c8d8] <1.8> + + * Return an error for the empty string when a word is expected. Allow an ID for per-user or per-runas Defaults. - [83bb1a9c80ad] <1.7> + [4c9020779582] <1.8> 2011-03-23 Todd C. Miller - * testsudoers.c: - Fix printing "User_Alias FOO = ALL" - [8e6e810e89ce] <1.7> + * Fix printing "User_Alias FOO = ALL" + [97c9fd7caeb7] <1.8> 2011-03-22 Todd C. Miller - * parse_args.c: - Better error message about invalid -C argument - [fc14f8dc03d2] <1.7> + * Better error message about invalid -C argument + [2301e7a3835b] <1.8> - * NEWS: - fix typo - [f789649fdeaf] <1.7> + * fix typo + [c5acde62a309] <1.8> - * sudoers.pod: - Fix placement of equal size ('=') in user specification summary. - [51861d678ac1] <1.7> + * Fix placement of equal size ('=') in user specification summary. + [4d0ffef77ae4] <1.8> 2011-03-21 Todd C. Miller - * toke.l: - If we match a rule anchored to the beginning of a line after parsing + * update to match sudoers regress + [0efb8dc9092a] <1.8> + + * Restore ability to define TRACELEXER and have trace output go to + stderr. + [441c8b372217] <1.8> + + * Restore old behavior of setting sawspace = TRUE for command line + args when a line continuation character is hit to avoid causing + problems for existing sudoers files. + [963ded6ce070] <1.8> + + * Add test for line continuation and aliases + [5703d11a3c46] <1.8> + + * Make test output line up nicely for parse vs. toke + [15321ce2d7d9] <1.8> + + * plugins/sudoers/regress/testsudoers/test1.ok, + plugins/sudoers/regress/testsudoers/test2.out, + plugins/sudoers/regress/testsudoers/test2.sh, + plugins/sudoers/regress/testsudoers/test3.ok, + plugins/sudoers/regress/testsudoers/test3.sh, + plugins/sudoers/regress/visudo/test1.ok, + plugins/sudoers/regress/visudo/test1.sh: + Move parser tests to sudoers directory and test the tokenizer output + too. + [111c1ccda334] <1.8> + + * If we match a rule anchored to the beginning of a line after parsing a line continuation character, return an ERROR token. It would be nicer to use REJECT instead but that substantially slows down the lexer. - [f31c6622aaf9] <1.7> + [67e54b14aa9d] <1.8> - * toke.c, toke.l: - Allow whitespace after the modifier in a Defaults entry. E.g. + * Move LEXTRACE macro to toke.h so we can use it in yyerror(). + [e6e04037deed] <1.8> + + * Make lex tracing settable at run-time in testsudoers via the -t + flag. Trace output goes to stderr. Will be used by regress tests + to check lexer. + [a973f43cc0c2] <1.8> + + * Allow whitespace after the modifier in a Defaults entry. E.g. "Defaults: username set_home" - [57c09139d10c] <1.7> + [bf876c9fc5bb] <1.8> 2011-03-18 Todd C. Miller - * mkpkg: - Don't set CC when cross-compiling. Use the Sun Studio C compiler on - Solaris if possible. - [b91feb0678c1] <1.7> + * Don't set CC when cross-compiling. + [d3c33dcb02f2] <1.8> - * NEWS: - Credit Matthew Thomas for the sudoers_search_filter changes. - [4b3f239e114d] <1.7> + * Credit Matthew Thomas for the sudoers_search_filter changes. + [2209b80664af] <1.8> - * NEWS: - Update for sudo 1.7.6 beta - [26cdd6578c23] <1.7> + * Add the .sym files to the MANIFEST + [bb452b28a009] <1.8> + + * Update for sudo 1.8.1 beta + [700d42d80e00] <1.8> - * exec_pty.c: - Save the controlling tty process group before suspending in pty + * user_shell -> run_shell to avoid confusion with the user's SHELL + variable. + [451b96d5f97e] <1.8> + + * Save the controlling tty process group before suspending in pty mode. Previously, we assumed that the child pgrp == child pid (which is usually, but not always, the case). - [670657004784] <1.7> + [b0841d861191] <1.8> - * ldap.c, sudoers.ldap.pod: - Add support for sudoers_search_filter setting in ldap.conf. This + * Add support for sudoers_search_filter setting in ldap.conf. This can be used to restrict the set of records returned by the LDAP query. - [c941bb5f68f2] <1.7> + [70c5f496e2b3] <1.8> 2011-03-17 Todd C. Miller * configure, configure.in: Remove the hack to disable -g in CFLAGS unless --with-devel - [933300bf3848] <1.7> + [9459839f50ba] <1.8> - * sudoers.pod: - The '@' character does not normally need to be quoted. - [7e96569aed54] <1.7> + * The '@' character does not normally need to be quoted. + [e66c4c64e514] <1.8> - * toke.c, toke.l: - We normaly transition from GOTDEFS to STARTDEFS on whitespace, but + * We normaly transition from GOTDEFS to STARTDEFS on whitespace, but if that whitespace is followed by a comma, we want to treat it as part of a list and not transition. - [6dd87c25c79c] <1.7> + [52ae2df9959d] <1.8> - * Makefile.in: - toke_util.c lives in $(srcdir) not $(devdir) - [b1b59d72f026] <1.7> + * Add check for whitespace when a User_List is used for a per-user + Defaults entry. + [44a4db95be86] <1.8> - * toke.c, toke.l: - Fix parsing of double-quoted names in Defaults and Aliases which was - broken in c2b486b12951. - [30b2fdbafdc2] <1.7> + * Expand quoted name checks to cover recent fixes. + [bd494b5c2bed] <1.8> -2011-03-16 Todd C. Miller + * Fix parsing of double-quoted names in Defaults and Aliases which was + broken in 601d97ea8792. + [dfdd58c3eb3b] <1.8> - * NEWS: - Document major changes for sudo 1.7.6 - [d474a2aeb411] <1.7> + * toke_util.c lives in $(srcdir) not $(devdir) + [94f8f024782e] <1.8> + +2011-03-16 Todd C. Miller * configure, configure.in: - Update version to 1.7.6 - [c1c80b99ed82] <1.7> + Update version to 1.8.1 + [531a7d520f18] <1.8> - * match.c: - Be careful not to deref user_stat if it is NULL. This cannot + * Document major changes in 1.8.1 and add upgrade notes. + [116821646140] <1.8> + + * Be careful not to deref user_stat if it is NULL. This cannot currently happen in sudo but might in other programs using the parser. - [0926b1653e20] <1.7> + [d72a9c7151c4] <1.8> - * mkpkg: - configure will not add -O2 to CFLAGS if it is already defined to add + * configure will not add -O2 to CFLAGS if it is already defined to add -O2 to the CFLAGS we pass in when PIE is being used. - [a4444e287bcb] <1.7> + [2c7fe82be93d] <1.8> - * sudoers.pod: - Warn about the dangers of log_input and mention iolog_dir in the - log_input and log_output descriptions. - [68c3615f7487] <1.7> + * Warn about the dangers of log_input and mention iolog_file and + iolog_dir in the log_input and log_output descriptions. + [edc6aa59aa45] <1.8> - * pp: - Back out 2b81d57de4a4 and sync with git version - [5a2443567b9c] <1.7> + * sync with git version + [b121cf739c77] <1.8> + + * It seems that h comes after i + [99ad15015f05] <1.8> - * exec.c: - Save the controlling tty process group before suspending so we can + * Move log_input and log_output to their proper, sorted, location. + Document set_utmp and utmp_runas. + [216ce8b0ae1a] <1.8> + + * Save the controlling tty process group before suspending so we can restore it when we resume. Fixes job control problems on Linux caused by the previous attemp to fix resuming a shell when I/O logging not enabled. - [3e4e26b79f59] <1.7> + [dfe038f733be] <1.8> + + * Fix printing of the remainder after a newline. Fixes "sudo -l" + output corruption that could occur in some cases. + [ab2f0a629e0d] <1.8> + + * Add support for ut_exit + [7039ec6a73fa] <1.8> + + * Add support for controlling whether utmp is updated and which user + is listed in the entry. + [1b008ce71eab] <1.8> + + * Fix typo; tupple vs. tuple + [67bb5c67ae3d] <1.8> + + * For legacy utmp, strip the /dev/ prefix before trying to determine + slot since the ttys file does not include the /dev/ prefix. + [8f597114381d] <1.8> + + * Add check for _PATH_UTMP + [fe7e2456f017] <1.8> + + * Adapt check_iolog_path to sessid changes + [3016201869b6] <1.8> + + * Redo utmp handling. If no getutent()/getutxent() is available, + assume a ttyslot-based utmp. If getttyent() is available, use that + directly instead of ttyslot() so we don't have to do the stdin dup2 + dance. + [817490c7c20e] <1.8> + + * Move utmp handling into utmp.c + [e4729d9259e9] <1.8> + + * Update copyright years. + [1065afc00233] <1.8> + +2011-03-11 Todd C. Miller + + * Add "user_shell" boolean as a way to indicate to the plugin that the + -s flag was given. + [6e8bc49b7ea7] <1.8> + + * Move sessid out of sudo_user. + [00d67d5ba894] <1.8> + + * Log the TSID even if it is not a simple session ID. + [490cf0adae29] <1.8> + + * Document noexec in sample.sudo.conf and add back noexec_file section + in sudoers with a note that it is deprecated. + [c7a2d8d0c563] <1.8> + + * Fix running commands as non-root on systems where setreuid() changes + the saved uid based on the effective uid we are changing to. + [f3b27db56ba6] <1.8> + +2011-03-10 Todd C. Miller + + * Move noexec path into sudo.conf now that sudo itself handles noexec. + Currently can be configured in sudoers too but is now undocumented + and will be removed in a future release. + [9c5f64709994] <1.8> + + * Document "Path noexec ..." in sudo.conf. No longer document + noexec_file in sudoers, it will be removed in a future release. + [959fa6b5217b] <1.8> + + * Move noexec handling to sudo front-end where it is documented as + being. + [ef6cd4a40c61] <1.8> - * exec.c: - In handle_signals(), restart the read() on EINTR to make sure we + * Add support for disabling exec via solaris privileges. Includes + preparation for moving noexec support out of sudoers and into front + end as documented. + [d9c05ba9a24f] <1.8> + + * Only export the symbols corresponding to the plugin structs. + [cb07af1d9b39] <1.8> + + * Install plugins manually instead of using libtool. This works + around a problem on AIX where libtool will install a .a file + containing the .so file instead of the .so file itself. + [1ccf5af58c05] <1.8> + + * Makefile.in: + Move check into its own rule since some versions of make will run + both targets as the default rule. + [7159f37eb552] <1.8> + + * Update to libtool 2.2.10 + [9e49773b32b7] <1.8> + + * In handle_signals(), restart the read() on EINTR to make sure we keep up with the signal pipe. Don't return -1 on EAGAIN, it just means we have emptied the pipe. - [5bcfe5a061c2] <1.7> + [dc2926097b2d] <1.8> - * lbuf.c: - Fix printing of the remainder after a newline. Fixes "sudo -l" - output corruption that could occur in some cases. - [41e5595f0559] <1.7> + * Reorder functions to quiet a compiler warning. + [5201367e5db4] <1.8> + + * Use the Sun Studio C compiler on Solaris if possible + [b8d43b423fb9] <1.8> 2011-03-08 Todd C. Miller - * mkpkg: - Fix default setting of osversion variable. - [c67d9d3bfa2b] <1.7> + * Fix default setting of osversion variable. + [e12905851be5] <1.8> + + * Make two login_class entris consistent. + [0671d7b204be] <1.8> + + * Add support for adding a utmp entry when allocating a new pty. + Requires the BSD login(3) or SYSV/POSIX getutent()/getutxent(). + Currently only creates a new entry if the existing tty has a utmp + entry. + [40ff30099e79] <1.8> + + * Avoid pulling in headers we don't need on Linux For getutx?id(), + call setutx?ent() first and always call endutx?ent(). + [b86f7a13aae9] <1.8> + + * Add some more libs to SUDOERS_LIBS instead of relying on them to be + pulled in by SUDO_LIBS. + [bcbd16ec56c6] <1.8> + + * Fix return value of "sudo -l command" when command is not allowed, + broken in [c7097ea22111]. The default return value is now TRUE and + a bad: label is used when permission is denied. Also fixed missing + permissions restoration on certain errors. On error()/errorx(), the + password and group files are now closed before returning. + [757c941a47b2] <1.8> 2011-03-07 Todd C. Miller - * mkpkg: - Add --osversion flag to specify OS instead of running "pp + * Fix passing of login class back to sudo front end. + [5e649de6b7f5] <1.8> + + * Add --osversion flag to specify OS instead of running "pp --probeonly" - [550104604d4b] <1.7> + [8a03943ac5e8] <1.8> - * sudo.pp: - Fix expr usage w/ GNU expr - [c2161988dec9] <1.7> + * Fix expr usage w/ GNU expr + [bdecfa1f54fc] <1.8> + +2011-03-06 Todd C. Miller + + * Fix exit value for validate and list mode. + [6f8b20199935] <1.8> + + * Fix non-interactive mode with sudoers plugin. + [cf5aca4fcbcf] <1.8> + +2011-03-05 Todd C. Miller + + * sudoreplay can now find IDs other than %{seq} and display the + session. + [60396b417633] <1.8> + + * Add support for replaying sessions when iolog_file is set to + something other than %{seq}. + [1cd2baa74d56] <1.8> + +2011-03-04 Todd C. Miller + + * If we are killed by a signal, display the name of the signal that + got us. + [1b38c4d42282] <1.8> + + * Move libs used for authentication from SUDO_LIBS to SUDOERS_LIBS + where they belong. + [78e97a921104] <1.8> + + * Fix bug in skey/opie check that could cause a shell warning. + [f20229a04f30] <1.8> + + * No longer need sudo_getepw() stubs. + [795631ac7db0] <1.8> + +2011-03-03 Todd C. Miller + + * Fix exit value of "sudo -l command" in sudoers module. + [4a05d6019b3d] <1.8> 2011-03-02 Todd C. Miller - * sudo.pp: - Don't use the beta or release candidate version as the rpm release. - [56f8c0b1eb46] <1.7> + * Use fgets() not fgetln() for portability. + [1f2050745096] <1.8> + + * Don't use the beta or release candidate version as the rpm release. + [a5b049477646] <1.8> 2011-02-25 Todd C. Miller + * Makefile.in: + Adjust ChangeLog rule now that 1.8 is branched + [a994ac361e44] <1.8> + * .hgtags: - Added tag SUDO_1_7_5 for changeset 9314212577c3 - [75f9d661ea03] <1.7> + Added tag SUDO_1_8_0 for changeset f6530d56f6ae + [99a2b3801419] <1.8> + +2011-02-25 Todd C. Miller * configure, configure.in: - version 1.7.5 - [9314212577c3] [SUDO_1_7_5] <1.7> + version 1.8.0 + [f6530d56f6ae] [SUDO_1_8_0] -2011-02-21 Todd C. Miller + * NEWS: + update sudo 1.8 section + [f2ee2cf95d18] + +2011-02-23 Todd C. Miller + + * plugins/sudoers/regress/testsudoers/test2.sh: + fix test description + [cd5730fa9f09] + + * plugins/sudoers/regress/testsudoers/test2.out, + plugins/sudoers/regress/testsudoers/test2.sh, + plugins/sudoers/regress/visudo/test2.out, + plugins/sudoers/regress/visudo/test2.sh: + convert test2 to use testsudoers + [b5ec3f0b69f1] + + * include/sudo_plugin.h, src/sudo_plugin_int.h: + Move struct generic_plugin to sudo_plugin_int.h + [6f7bc629329c] + + * plugins/sudoers/gram.c, plugins/sudoers/gram.y, + plugins/sudoers/parse.c, plugins/sudoers/parse.h, + plugins/sudoers/set_perms.c, plugins/sudoers/sudoers.c, + plugins/sudoers/sudoers.h: + Allow sudoers file name, mode, uid and gid to be specified in the + settings list. The sudo front end does not currently set these but + may in the future. + [22f38a0fda2a] - * configure, configure.in, sudo.cat, sudo.man.in, sudoers.cat, - sudoers.ldap.cat, sudoers.ldap.man.in, sudoers.man.in, - sudoreplay.cat, sudoreplay.man.in, visudo.cat, visudo.man.in: - 1.7.5rc1 - [216ab95b5de0] <1.7> +2011-02-21 Todd C. Miller - * parse_args.c, sudo.c, sudo.pod, sudo_usage.h.in, sudoreplay.c, - sudoreplay.pod, visudo.c, visudo.pod: + * configure, configure.in, doc/sudo.cat, doc/sudo.man.in, + doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudoers.cat, + doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in, doc/sudoers.man.in, + doc/sudoreplay.cat, doc/sudoreplay.man.in, doc/visudo.cat, + doc/visudo.man.in: + 1.8.0rc1 + [5d4588b9c057] + + * doc/sudo.pod, doc/sudoreplay.pod, doc/visudo.pod, + plugins/sudoers/sudoreplay.c, plugins/sudoers/visudo.c, + src/parse_args.c, src/sudo.h: add help text to sudo, visudo and sudoreplay for the -h option - [141d348c660b] <1.7> + [52e7378d8476] 2011-02-19 Todd C. Miller - * snprintf.c: + * compat/snprintf.c: avoid using "howmany" for a parameter name since it is a select- related macro - [6b6c2d504103] <1.7> + [a14d565401a1] - * Makefile.in: + * doc/sudoers.pod: + mention group_plugin when describing nonunix_group + [e0d1d0034b17] + + * doc/sudo_plugin.pod: + Add missing period at end of sentence + [6744d7e9056d] + + * Makefile.in, doc/Makefile.in, include/Makefile.in, + plugins/sample/Makefile.in, plugins/sample_group/Makefile.in, + plugins/sudoers/Makefile.in, src/Makefile.in: add localstatedir; closes bug 471 - [a4778228ae54] <1.7> + [7aefcab85088] - * config.h.in, configure, configure.in, exec.c, exec_pty.c, - sudoreplay.c: + * config.h.in, configure, configure.in, plugins/sudoers/sudoreplay.c, + src/exec.c, src/exec_pty.c: The howmany macro lives in sys/sysmacros.h on SVR5 systems Closes Bug 470 - [be5dff63ff5d] <1.7> + [927ed6740f32] + + * configure.in: + add missing AH_TEMPLATE for ENV_RESET + [16300010c986] - * exec.c: + * src/exec.c: SVR5 systems return non-zero for success on socketpair(), check for -1 instead. Closes Bug 469 - [13ac9d0e0934] <1.7> + [4d276494bf8e] -2011-02-17 Todd C. Miller +2011-02-16 Todd C. Miller - * auth/afs.c: - Move afs includes to be before sudo ones - [fbe0bdcf5798] <1.7> + * configure, configure.in: + 1.8.0b5 + [d611cd5d73d3] - * config.h.in, configure, configure.in: - No longer use vhangup - [9fce94512df9] <1.7> + * doc/sudo.cat, doc/sudo.man.in, doc/sudo_plugin.cat, + doc/sudo_plugin.man.in, doc/sudoers.cat, doc/sudoers.ldap.cat, + doc/sudoers.ldap.man.in, doc/sudoers.man.in, doc/sudoreplay.cat, + doc/sudoreplay.man.in, doc/visudo.cat, doc/visudo.man.in: + regen + [85e96eeaed82] + + * doc/sudo.pod: + Document that a sudo.conf file with no Pligin lines uses the default + sudoers plugins. + [88bd52da977f] + + * src/load_plugins.c: + If sudo.conf contains no Plugin lines, use the default sudoers + policy and I/O plugins. + [fd8f4cb811ab] 2011-02-14 Todd C. Miller - * sudo_nss.c: + * plugins/sudoers/sudo_nss.c: Avoid printing empty "Runas and Command-specific defaults for user" line. - [3df2925f9982] <1.7> + [2dd330fe4f8b] - * lbuf.c: + * common/lbuf.c: Truncate the buffer at buf.len before printing in the non-wordwrap case. - [23a31b8d95b8] <1.7> + [901e9833f80d] - * lbuf.c: + * common/lbuf.c: Remove extra newline when the tty width is very small or unavailable - [32fa0b3ea47a] <1.7> - -2011-02-13 Todd C. Miller - - * configure, configure.in, sudo.cat, sudo.man.in, sudoers.cat, - sudoers.ldap.cat, sudoers.ldap.man.in, sudoers.man.in, - sudoreplay.cat, sudoreplay.man.in, visudo.cat, visudo.man.in: - 1.7.5b5 - [0937b9bff020] <1.7> - - * pp: - don't remap numeric uids/gids to names; if the user specified and id - instead of a name, they probably mean it - [2b81d57de4a4] <1.7> + [245c05506c0e] 2011-02-11 Todd C. Miller - * alias.c: + * plugins/sudoers/alias.c: Remove unneeded variable. - [23329353f964] <1.7> + [2c086d30b796] 2011-02-09 Todd C. Miller * configure, configure.in: Prefer getutxid over getutid - [e89811f0e4da] <1.7> + [3f3322e9c93e] - * boottime.c: + * plugins/sudoers/boottime.c: Include utmp.h / utmpx.h before missing.h as apparently including it afterwards causes a compilation problem on GNU Hurd. - [d62781e31b27] <1.7> + [a528029ae962] 2011-02-07 Todd C. Miller - * configure, configure.in, sudo.cat, sudo.man.in, sudoers.cat, - sudoers.ldap.cat, sudoers.ldap.man.in, sudoers.man.in, - sudoreplay.cat, sudoreplay.man.in, visudo.cat, visudo.man.in: - 1.7.5b4 - [4b8a9632fe59] <1.7> + * plugins/sudoers/sudoreplay.c, plugins/sudoers/toke_util.c: + #include "foo.h", not for local includes. + [f65ec693998e] - * exec.c, missing.h, sudo.c, toke.h: - fix K&R compilation - [23ebea9c2183] <1.7> + * src/parse_args.c: + remove bogus XXX + [9136c17d53ce] - * mksiglist.c: + * compat/mksiglist.c: Fix typo - [1587615a186f] <1.7> - - * Makefile.in, toke.h, toke.l, toke_util.c: - Split tokenizer utility functions out into toke_util.c - [88148d0b9338] <1.7> + [1a3bb7b455c9] - * alloc.c, bsm_audit.c, check.c, closefrom.c, sudo_nss.c, visudo.c: - Cosmetic changes to make diffing against trunk easier. - [95bdfcc29a22] <1.7> - - * exec.c, exec_pty.c, mon_systrace.c, sudo.h, sudo_exec.h, - sudoreplay.c, tgetpass.c: - Use RETSIGTYPE for signal handlers. - [5ea1f34d1aab] <1.7> - - * sudo_exec.h: - Use special values SIGCONT_FG and SIGCONT_BG instead of SIGUSR1 and - SIGUSR2 to indicate whether the child should be continued in the - foreground or background. - [9fec5a258d57] <1.7> + * compat/glob.c, plugins/sudoers/ldap.c, plugins/sudoers/logging.c, + plugins/sudoers/match.c: + return foo not return(foo) + [5c9e0647359a] 2011-02-06 Todd C. Miller - * getspwuid.c: - Merge trunk version - [cd44ef67e57d] <1.7> - - * exec_pty.c: - Use special values SIGCONT_FG and SIGCONT_BG instead of SIGUSR1 and - SIGUSR2 to indicate whether the child should be continued in the - foreground or background. - [6305babcf6bd] <1.7> - - * exec.c: - If perform_io() fails, kill the child before exiting so it doesn't - complain about connection reset. We can get an I/O error if, for - example, and we get EIO reading from stdin. - [ca28e0a25698] <1.7> + * src/exec.c: + Remove duplicate FD_SET of signal_pipe[0] + [3096527d2215] 2011-02-05 Todd C. Miller - * error.c, fileops.c, fnmatch.c, getcwd.c, getprogname.c, gettime.c, - glob.c, isblank.c, memrchr.c, mksiglist.c, mkstemps.c, nanosleep.c, - setsid.c, sigaction.c, snprintf.c, strcasecmp.c, strerror.c, - strlcat.c, strlcpy.c, strsignal.c, sudo_noexec.c, sudoreplay.c, - utimes.c, vasgroups.c, zero_bytes.c: - Make local includes consistent; use double quotes for local includes - [ec9d52fff4b3] <1.7> + * compat/mksiglist.c: + Use "missing.h" not in generated code. + [d8e09cffbe09] 2011-02-04 Todd C. Miller - * error.c, getprogname.c, memrchr.c, sigaction.c, strcasecmp.c, - strerror.c, strlcat.c, strlcpy.c, strsignal.c, zero_bytes.c: - Must include config.h before any other headers. - [3c23ec625df0] <1.7> - * aclocal.m4, configure: fix --with-iologdir=no - [ef60ca8b3789] <1.7> + [a89699cb5f5f] * aclocal.m4, configure: fix typo that broke --with-iologdir - [fca175fdfd81] <1.7> + [91b54eb22403] 2011-02-03 Todd C. Miller - * NEWS: - sync for 1.7.5b3 - [744e2e78ef5a] <1.7> + * configure, configure.in, doc/sudo.cat, doc/sudo.man.in, + doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudoers.cat, + doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in, doc/sudoers.man.in, + doc/sudoreplay.cat, doc/sudoreplay.man.in, doc/visudo.cat, + doc/visudo.man.in: + Bump version to 1.8.0b4 + [e2b7f2cdc02e] - * configure, configure.in, sudo.cat, sudo.man.in, sudoers.cat, - sudoers.ldap.cat, sudoers.ldap.man.in, sudoers.man.in, - sudoreplay.cat, sudoreplay.man.in, visudo.cat, visudo.man.in: - 1.7.5b3 - [7a24576e35ac] <1.7> + * NEWS: + sync + [decf5a0a8a33] - * sudoers.cat, sudoers.man.in, sudoers.pod: + * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod: Attempt to clarify how users and groups interact in Runas_Specs - [9e8c2fb328d0] <1.7> + [e6fb3a2dbd77] - * exec.c, exec_pty.c: - Do not handle SIGARLM specially, just pass it through. - [944978b640b5] <1.7> + * plugins/sudoers/regress/visudo/test2.out, + plugins/sudoers/regress/visudo/test2.sh: + Add test for quoted group that contains escaped double quotes + [44596c48c629] - * exec.c, exec_pty.c: + * src/exec.c, src/exec_pty.c: Pass SIGUSR1/SIGUSR2 through to the child. - [774506c977df] <1.7> + [c3108a827b01] - * exec.c: - Made tcsetpgrp() bits conditional on HAVE_TCSETPGRP - [386f69132ad4] <1.7> + * src/exec_pty.c, src/sudo_exec.h: + Use special values SIGCONT_FG and SIGCONT_BG instead of SIGUSR1 and + SIGUSR2 to indicate whether the child should be continued in the + foreground or background. + [35ca47cc6785] - * exec.c: + * src/exec.c: Use pid_t not int and check the return value of kill() - [5f15c3304a1d] <1.7> + [36ae7d37d7f9] 2011-02-02 Todd C. Miller - * exec.c: + * src/exec_pty.c: + Remove obsolete comment + [baebef4919f6] + + * src/exec.c: In non-pty mode before continuing the child, make it the foreground pgrp if possible. Fixes resuming a shell. - [dfaadefcc6c6] <1.7> + [fef5b1d02ddb] - * exec_pty.c: + * src/exec_pty.c: If we get a signal other than SIGCHLD in the monitor, pass it directly to the child. - [7e638105bfaf] <1.7> + [b3ecb28163a0] - * exec.c, exec_pty.c, sudo.h: + * src/exec.c, src/exec_pty.c, src/sudo.h: Save signal state before changing handlers and restore before we execute the command. - [83278957e630] <1.7> + [faf7475dc4bf] 2011-02-01 Todd C. Miller - * toke.c, toke.l: - match quoted strings the same way whether in a Defaults line or as a - user/group/netgroup name. Fixes escaped double quotes in quoted - user/group/netgroup names. - [c2b486b12951] <1.7> - - * iolog.c: + * plugins/sudoers/iolog.c: Use a char array to map a number to a base36 digit. - [d626ded3312d] <1.7> + [257576c51f8b] - * sudoers.ldap.cat, sudoers.ldap.man.in, sudoers.ldap.pod: + * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in, doc/sudoers.ldap.pod: Be clear about what versions of sudo support new LDAP attributes. Fix up some formatting of attribute names. Minor other tweaks. - [f7bd586ec755] <1.7> + [39f65df71f65] 2011-01-31 Todd C. Miller - * sudoers2ldif: - Add sudoOrder attribute to each entry Parse LOG_{INPUT,OUTPUT} tags - [05a0d25b0f8d] <1.7> + * plugins/sudoers/toke.c, plugins/sudoers/toke.l: + match quoted strings the same way whether in a Defaults line or as a + user/group/netgroup name. Fixes escaped double quotes in quoted + user/group/netgroup names. + [601d97ea8792] + + * plugins/sudoers/Makefile.in: + 'make check' depends on visudo and testsudoers + [127c5a24df8f] + + * plugins/sudoers/sudoers2ldif: + Add sudoOrder attribute to each entry Parse LOG_{INPUT,OUTPUT} tags + [9029163a58c3] 2011-01-30 Todd C. Miller - * UPGRADE: + * doc/UPGRADE: Mention LDAP attribute compatibility status. - [adb74ad2331b] <1.7> + [2c3595aaec63] 2011-01-28 Todd C. Miller * README.LDAP: Mention phpQLAdmin - [5d80d6291142] <1.7> + [9304c9064fbe] - * INSTALL, NEWS, config.h.in, configure, configure.in, defaults.c, - sudoers.man.in, sudoers.pod: + * INSTALL, NEWS, config.h.in, configure, configure.in, + doc/sudoers.man.in, doc/sudoers.pod, plugins/sudoers/defaults.c: Add --disable-env-reset configure option. - [803ce2f4d85c] <1.7> + [8a753aa13a46] - * sudoers.cat, sudoers.man.in, sudoers.pod: + * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod: Document that sudoers_locale also affects logging and email. - [080dd4338374] <1.7> + [998d6ac11277] - * NEWS, config.h.in, configure, configure.in, logging.c: + * NEWS, config.h.in, configure, configure.in, + plugins/sudoers/logging.c: Do logging and email sending in the locale specified by the "sudoers_locale" setting ("C" by default). Email send by sudo includes MIME headers when the sudoers locale is not "C". - [592e5b2a3d10] <1.7> + [cb7e55408400] + +2011-01-27 Todd C. Miller + + * plugins/sudoers/check.c: + Fix indentation + [65ae7e92b9e4] 2011-01-25 Todd C. Miller - * NEWS, sudo.c: + * NEWS, src/parse_args.c, src/sudo.c: Perform command escaping for "sudo -s" and "sudo -i" after validating sudoers so the sudoers entries don't need to have all the backslashes. - [7d39ea9924e4] <1.7> + [4e168c103f4b] 2011-01-24 Todd C. Miller - * logging.c: + * plugins/sudoers/logging.c: Prepend "list " to the command logged when "sudo -l command" is used to make it clear that the command was listed, not run. - [9bcd40c1bfe9] <1.7> + [f392a6056cd6] - * parse.c: + * plugins/sudoers/parse.c: cosmetic change - [8ce3d60d910d] <1.7> - - * aix.c, alias.c, alloc.c, auth/afs.c, auth/aix_auth.c, - auth/bsdauth.c, auth/dce.c, auth/fwtk.c, auth/kerb4.c, auth/kerb5.c, - auth/pam.c, auth/passwd.c, auth/rfc1938.c, auth/secureware.c, - auth/securid.c, auth/securid5.c, auth/sia.c, bsm_audit.c, check.c, - defaults.c, env.c, exec.c, exec_pty.c, fileops.c, find_path.c, - fnmatch.c, get_pty.c, getcwd.c, getline.c, getprogname.c, - getspwuid.c, gettime.c, glob.c, goodpath.c, gram.c, gram.y, iolog.c, - isblank.c, lbuf.c, ldap.c, list.c, logging.c, match.c, memrchr.c, - mkstemps.c, mon_systrace.c, nanosleep.c, parse.c, parse_args.c, - pwutil.c, redblack.c, set_perms.c, sigaction.c, snprintf.c, - strerror.c, strlcat.c, strlcpy.c, strsignal.c, sudo.c, - sudo_noexec.c, sudo_nss.c, sudoreplay.c, term.c, testsudoers.c, - tgetpass.c, timestr.c, toke.c, toke.l, tsgetgrpw.c, utimes.c, - vasgroups.c, visudo.c: + [7c0951dbc2dd] + + * common/aix.c, common/alloc.c, common/fileops.c, common/fmt_string.c, + common/list.c, common/term.c, compat/fnmatch.c, compat/getcwd.c, + compat/glob.c, compat/isblank.c, compat/memrchr.c, compat/mktemp.c, + compat/nanosleep.c, compat/regress/glob/globtest.c, + compat/snprintf.c, compat/strlcat.c, compat/strlcpy.c, + compat/strsignal.c, compat/utimes.c, plugins/sample/sample_plugin.c, + plugins/sample_group/getgrent.c, plugins/sample_group/plugin_test.c, + plugins/sudoers/alias.c, plugins/sudoers/auth/afs.c, + plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/bsdauth.c, + plugins/sudoers/auth/dce.c, plugins/sudoers/auth/fwtk.c, + plugins/sudoers/auth/kerb4.c, plugins/sudoers/auth/kerb5.c, + plugins/sudoers/auth/pam.c, plugins/sudoers/auth/passwd.c, + plugins/sudoers/auth/rfc1938.c, plugins/sudoers/auth/secureware.c, + plugins/sudoers/auth/securid.c, plugins/sudoers/auth/securid5.c, + plugins/sudoers/auth/sia.c, plugins/sudoers/bsm_audit.c, + plugins/sudoers/check.c, plugins/sudoers/defaults.c, + plugins/sudoers/find_path.c, plugins/sudoers/goodpath.c, + plugins/sudoers/gram.c, plugins/sudoers/gram.y, + plugins/sudoers/iolog.c, plugins/sudoers/ldap.c, + plugins/sudoers/match.c, plugins/sudoers/mon_systrace.c, + plugins/sudoers/parse.c, plugins/sudoers/pwutil.c, + plugins/sudoers/redblack.c, plugins/sudoers/set_perms.c, + plugins/sudoers/sudo_nss.c, plugins/sudoers/sudoers.c, + plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c, + plugins/sudoers/timestr.c, plugins/sudoers/toke.c, + plugins/sudoers/toke.l, plugins/sudoers/toke_util.c, + plugins/sudoers/tsgetgrpw.c, plugins/sudoers/visudo.c, + src/exec_pty.c, src/get_pty.c, src/load_plugins.c, src/parse_args.c, + src/sudo_noexec.c, src/tgetpass.c: standardize on "return foo;" rather than "return(foo);" or "return (foo);" - [e05dd17dcec4] <1.7> - - * NEWS: - sync - [bedc1e1bc7f8] <1.7> + [32d76c5aaf8c] - * sudo.c: + * plugins/sudoers/sudoers.c: Do not reject sudoers file just because it is root-writable. - [26634f322b04] <1.7> + [0febc579185b] 2011-01-21 Todd C. Miller * NEWS: sync - [c69b7537a020] <1.7> - - * defaults.c: - When setting default iolog_dir, dynamically allocate the string. - [7ad2c0cbe865] <1.7> + [1ab03f8278ff] - * sudo_nss.c: + * plugins/sudoers/sudo_nss.c: For "sudo -U user -l" if user is not authorized on the host, say so. - [9eb5673f2f22] <1.7> + [289afe6dd15c] - * ldap.c: + * plugins/sudoers/ldap.c: In sudo_ldap_lookup(), always do the initial sudoers check as the invoking user. If we are listing another user's privs we will do a separate lookup using list_pw later. - [9b3ab41de717] <1.7> + [e52bc15de76d] 2011-01-20 Todd C. Miller - * sudoreplay.c: - change an error() to errorx() - [5a0409f6c52b] <1.7> - - * sudoers.ldap.man.in, sudoers.ldap.pod: + * MANIFEST: + add parser fill tests + [4f65140d3515] + + * compat/regress/glob/globtest.c, compat/regress/glob/globtest.in: + Don't test features not supported by the bundled glob() + [8ec7ace11949] + + * Makefile.in, aclocal.m4, common/Makefile.in, common/term.c, + compat/Makefile.in, configure.in, doc/LICENSE, doc/Makefile.in, + doc/sudo_plugin.man.in, doc/sudo_plugin.pod, + doc/sudoers.ldap.man.in, doc/sudoers.ldap.pod, doc/sudoers.man.in, + doc/sudoers.pod, include/Makefile.in, plugins/sample/Makefile.in, + plugins/sample_group/Makefile.in, plugins/sudoers/Makefile.in, + plugins/sudoers/check.c, plugins/sudoers/defaults.c, + plugins/sudoers/gram.c, plugins/sudoers/gram.y, + plugins/sudoers/iolog.c, plugins/sudoers/iolog_path.c, + plugins/sudoers/ldap.c, plugins/sudoers/match.c, + plugins/sudoers/pwutil.c, plugins/sudoers/sudo_nss.c, + plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h, + plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c, + plugins/sudoers/toke.c, plugins/sudoers/toke.l, + plugins/sudoers/toke_util.c, src/Makefile.in, zlib/Makefile.in: Update copyright year to 2011 - [8959c05dc270] <1.7> + [ac1b45cb1809] - * LICENSE, Makefile.in, aclocal.m4, check.c, configure.in, ldap.c, - match.c, pwutil.c, sudo_nss.c, sudoers.man.in, sudoers.pod, term.c: - Update copyright year to 2011 - [6367fb76120e] <1.7> + * plugins/sudoers/sudo_nss.c: + When listing, use separate lbufs for the defaults and the privileges + and only print something if the number of privileges is non-zero. + Fixes extraneous Defaults output for "sudo -U unauthorized_user -l". + [d0854d39f8ef] - * ldap.c: + * plugins/sudoers/ldap.c: Stash pointer to user group vector in LDAP handle and only reuse the query if it has not changed. We always allocate a new buffer when we reset the group vector so a simple pointer check is sufficient. - [c129d1acf7d6] <1.7> + [88861d4eba69] - * sudo_nss.c: - When listing, use separate lbufs for the defaults and the privileges - and only print something if the number of privileges is non-zero. - Fixes extraneous Defaults output for "sudo -U unauthorized_user -l". - [66aaa54f2865] <1.7> - - * sudo_nss.c: + * plugins/sudoers/sudo_nss.c: Check initgroups() return value. - [973a67304e3b] <1.7> + [3bdaf58408a7] + + * plugins/sudoers/Makefile.in, + plugins/sudoers/regress/parser/check_fill.c: + Add tests for the fill functions in toke_util.c + [bca587ab4956] 2011-01-19 Todd C. Miller + * plugins/sudoers/regress/iolog_path/check_iolog_path.c: + fix copyright year + [e2038cdaf055] + * NEWS: sync - [deb822cce3dd] <1.7> + [56ca5d5eaebe] 2011-01-18 Todd C. Miller - * term.c: - Clear, don't set, OPOST in c_oflag as was intended in e26055d17b72. - [eacd774c37c0] <1.7> - -2011-01-15 Todd C. Miller - - * sudo.c: - delref list_pw before exit - [0df5a53f3484] <1.7> + * common/term.c: + Clear, don't set, OPOST in c_oflag as was intended in 506ad5ae9b4e. + [b91f266624ec] 2011-01-14 Todd C. Miller * mkpkg, sudo.pp: Add Requires line for audit-libs >= 1.4 for RHEL5+ - [a1b544018f5b] <1.7> + [6c02f976171b] * pp: sync with git version - [eb187023bb73] <1.7> + [d301c32d5865] 2011-01-13 Todd C. Miller - * sudoers.cat, sudoers.man.in, sudoers.pod: + * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod: fix typo - [075e92a756a1] <1.7> + [39353f92976f] 2011-01-12 Todd C. Miller * NEWS: Update for sudo 1.7.4p5 - [11cb87598478] <1.7> + [b444da76901f] - * schema.OpenLDAP, schema.iPlanet: + * doc/schema.OpenLDAP, doc/schema.iPlanet: Add sudoNotBefore and sudoNotAfter attributes as optional attributes to the sudoRole object class. From Andreas Mueller - [73357eb1b269] <1.7> + [dacfad7e7a95] 2011-01-11 Todd C. Miller * NEWS: Mention "sudo -g group" password check fix. - [8299a2d939e8] <1.7> + [1eb8fb14e53b] - * check.c: + * plugins/sudoers/sudoers.c: + Fix "sudo -g" support in the sudoers module. + [07d1b0ce530e] + + * plugins/sudoers/check.c: If the user is running sudo as himself but as a different group we need to prompt for a password. - [fe8a94f96542] <1.7> + [caf1fcc9a117] 2011-01-10 Todd C. Miller - * NEWS, config.h.in, configure, configure.in, ldap.c, - sudoers.ldap.cat, sudoers.ldap.man.in, sudoers.ldap.pod: + * NEWS, config.h.in, configure, configure.in, doc/sudoers.ldap.cat, + doc/sudoers.ldap.man.in, doc/sudoers.ldap.pod, + plugins/sudoers/ldap.c: Add support for TIMEOUT in ldap.conf, mapping to the OpenLDAP LDAP_OPT_TIMEOUT. There is no corresponding option for mozilla- derived LDAP SDKs but we can pass the timeout parameter to ldap_search_ext_s() or ldap_search_st() when possible. - [8f9303326db7] <1.7> + [5537049991f7] - * sudoers.cat, sudoers.ldap.cat, sudoers.ldap.man.in, sudoers.man.in: + * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in: regen - [d56ad7169e67] <1.7> + [5b361c3c4324] - * NEWS, ldap.c, sudoers.ldap.pod: + * NEWS, doc/sudoers.ldap.pod, plugins/sudoers/ldap.c: Add NETWORK_TIMEOUT as an alias for BIND_TIMELIMIT for compatibility with OpenLDAP ldap.conf files. - [85e33e42c008] <1.7> + [e97843bd16fb] - * pwutil.c: + * plugins/sudoers/pwutil.c: If user has no supplementary groups, fall back on checking the group - file explicitly. - [c536ddb16bb6] <1.7> + file expliticly. + [5223ad4eb690] + +2011-01-08 Todd C. Miller + + * plugins/sudoers/toke.h, plugins/sudoers/toke_util.c: + constify + [6e132a4cca61] + + * plugins/sudoers/toke.c, plugins/sudoers/toke.h, + plugins/sudoers/toke.l: + Move fill macro to toke.h + [623d430798cf] + + * MANIFEST, plugins/sudoers/Makefile.in, plugins/sudoers/toke.c, + plugins/sudoers/toke.h, plugins/sudoers/toke.l, + plugins/sudoers/toke_util.c: + Split tokenizer utility functions out into toke_util.c + [89a97bd51618] + + * plugins/sudoers/gram.c, plugins/sudoers/gram.y, + plugins/sudoers/toke.c, plugins/sudoers/toke.l: + ANSIfy + [ca0eba1dfaa9] + +2011-01-07 Todd C. Miller + + * MANIFEST: + sync + [a43f94064bb3] + + * plugins/sudoers/Makefile.in: + Add visudo tests to check target + [8c82fb4ed40f] + + * compat/Makefile.in, compat/regress/fnmatch/fnm_test.c, + compat/regress/fnmatch/fnm_test.in, compat/regress/glob/files, + compat/regress/glob/globtest.c, compat/regress/glob/globtest.in: + Add my regress tests for fnmatch() and glob() from OpenBSD. + [6e8c1f211723] + + * plugins/sudoers/regress/testsudoers/test1.sh, + plugins/sudoers/regress/visudo/test1.ok, + plugins/sudoers/regress/visudo/test1.sh: + Add regress test for command tags using visudo -c + [18b0ef207c0f] + + * plugins/sudoers/Makefile.in, + plugins/sudoers/regress/testsudoers/test1.ok, + plugins/sudoers/regress/testsudoers/test1.sh: + Add support for regress tests using testsudoers + [1fa94bd2671b] + + * plugins/sudoers/testsudoers.c: + Need to set user_name explicitly due to internal changes made when + converting sudoers to a plugin. + [1fa54e86a364] + +2011-01-06 Todd C. Miller + + * MANIFEST, Makefile.in, common/Makefile.in, compat/Makefile.in, + doc/Makefile.in, include/Makefile.in, plugins/sample/Makefile.in, + plugins/sample_group/Makefile.in, plugins/sudoers/Makefile.in, + plugins/sudoers/regress/iolog_path/check_iolog_path.c, + plugins/sudoers/regress/iolog_path/data, src/Makefile.in, + zlib/Makefile.in: + Add regression tests for iolog_path() + [afa4b416e559] + + * Makefile.in, common/Makefile.in, compat/Makefile.in, + doc/Makefile.in, include/Makefile.in, plugins/sample/Makefile.in, + plugins/sample_group/Makefile.in, plugins/sudoers/Makefile.in, + src/Makefile.in, zlib/Makefile.in: + Add support for "make Makefile" to regenerate Makefile from + Makefile.in + [98bd2dda3294] + + * plugins/sudoers/iolog_path.c: + Quiest a bogus compiler warning. + [5ff932a7ad67] + +2011-01-05 Todd C. Miller + + * plugins/sudoers/iolog_path.c: + Protect call to setlocale() with HAVE_SETLOCALE + [2c29ee3ccc81] 2011-01-04 Todd C. Miller + * MANIFEST: + mkstemps.c was renamed mktemp.c + [ae299c3b1827] + * NEWS: - update - [9f6e0ec3142a] <1.7> + Update from 1.7 branch + [20817d79717b] * Makefile.in: Use "mv -f" when regenerating ChangeLog - [b322b5995e7f] <1.7> + [c163635206c6] - * match.c: + * plugins/sudoers/match.c: Fix NULL dereference with "sudo -g group" when the sudoers rule has no runas user or group listed. Fixes RedHat bug Bug 667103. - [c51e2be737b2] <1.7> + [41a6a1243d9e] + +2011-01-03 Todd C. Miller + + * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod: + Correct the default sudo.conf example + [4e791698cad1] + +2010-12-31 Todd C. Miller + + * plugins/sudoers/iolog_path.c: + Reset slashp if we allocate a new buffer for strftime() + [e491daa4203b] + + * plugins/sudoers/iolog_path.c, plugins/sudoers/sudoers.c, + plugins/sudoers/sudoers.h: + Add extra out parameter to expand_iolog_path() to allow the caller + to split the path into dir and file components if needed. + [88346bc5ae39] + +2010-12-30 Todd C. Miller + + * plugins/sudoers/iolog.c: + mkdir_iopath() returns size_t now that it uses strlcpy() and not + snprintf() + [3c4c64d265eb] + + * plugins/sudoers/iolog.c, plugins/sudoers/iolog_path.c: + Trim leading slashes from iolog_file and trailing slashes from + iolog_dir + [a803b51f8948] + + * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod, + plugins/sudoers/iolog.c, plugins/sudoers/iolog_path.c, + plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h: + Pass a single I/O log file name in command_details instead of + separate dir + file parameters. + [d672a3e46e80] + + * plugins/sudoers/sudoreplay.c: + change an error() to errorx() + [8013dcfdd69d] + + * plugins/sudoers/iolog.c: + Add missing cwd line to I/O log info file that got dropped when + iolog_deserialize_info() was added + [7cf84f208423] + +2010-12-29 Todd C. Miller + + * plugins/sudoers/iolog.c: + Avoid relying on globals filled in by the sudoers policy module for + the sudoers I/O log module. The I/O log open function now pulls the + bits it needs out of user_info and command_info. + [c02f6951b0cc] + + * plugins/sudoers/iolog.c, plugins/sudoers/sudoers.c, + plugins/sudoers/sudoers.h: + If no iolog file is specified by the policy plugin, use io_nextid() + to determine the next file in the sequence. + [faa1130b1020] + +2010-12-28 Todd C. Miller + + * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod: + Document iolog_compress in command_info + [58895c7d12f5] + + * plugins/sudoers/iolog.c, plugins/sudoers/sudoers.c: + Add support for the iolog_compress variable in command_info. + [36f13a2fd1c1] + + * plugins/sudoers/iolog.c, plugins/sudoers/sudoers.c: + Add sigsetjmp() calls to all plugin entry points just to be safe. + [3fa482355bc4] + + * src/sudo.c, src/sudo.h: + Don't need iolog variables in struct command_details, they are for + the I/O log plugins to handle. + [5111579ffd9d] + +2010-12-27 Todd C. Miller + + * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod: + Document use of mkdtemp() for iolog path teplates + [5db6101408a9] + + * doc/sudo.cat, doc/sudo.man.in, doc/sudo_plugin.cat, + doc/sudo_plugin.man.in, doc/sudoers.cat, doc/sudoers.ldap.cat, + doc/sudoers.ldap.man.in, doc/sudoers.man.in, doc/sudoreplay.cat, + doc/sudoreplay.man.in, doc/visudo.cat, doc/visudo.man.in: + regen + [1ee11fd6d4eb] + + * doc/sudo_plugin.pod, doc/sudoers.pod: + Document iolog_file and supported escape sequences for sudoers. + Clarify that iolog_file can contain directories. + [da611dedcbdb] + + * compat/Makefile.in, configure, configure.in: + Fix building of mkstemps/mkdtemp replacements. + [793a5e303122] + + * compat/mkstemps.c, compat/mktemp.c, config.h.in, configure, + configure.in, include/missing.h: + Provide mkdtemp() for systems without it. + [b0527dfa965c] + + * plugins/sudoers/iolog_path.c: + Fix typo + [277f6c514cba] + + * plugins/sudoers/iolog.c: + Only use mkdtemp() if the path ends in at least 6 Xs since otherwise + glibc mkdtemp() returns EINVAL. + [2e7323b05579] + + * plugins/sudoers/Makefile.in, plugins/sudoers/def_data.c, + plugins/sudoers/def_data.h, plugins/sudoers/def_data.in, + plugins/sudoers/defaults.c, plugins/sudoers/iolog.c, + plugins/sudoers/iolog_path.c, plugins/sudoers/plugin_error.c, + plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h: + Allow sudoers to specify the iolog file in addition to the iolog + dir. Add escape sequence support to iolog file and dir: sequence + number, user, group, runas_user, runas_group, hostname and + command in addition to any escape sequence recognized by + strftime(3). + [75cd32ee0435] + + * plugins/sudoers/iolog.c: + Add missing sigsetjmp() call in I/O plugin open function. Fixes a + crash when the I/O plugin calls error(), errorx() or log_error(). + [1a6718bd817d] 2010-12-21 Todd C. Miller - * term.c: + * doc/sudo_plugin.pod, plugins/sudoers/iolog.c, + plugins/sudoers/sudoers.c: + Give the policy module fine-grained control over what the I/O plugin + logs. + [d29784fd2a66] + + * common/term.c: Clear OPOST from c_oflag like we used to. Fixes screen-based editors such as vi. - [e26055d17b72] <1.7> + [506ad5ae9b4e] - * sudoers.pod: + * doc/sudoers.pod: Clarify umask option description. From Reuben Thomas. - [fb8bdcb54feb] <1.7> + [1294ac84222b] -2010-12-18 Todd C. Miller +2010-12-20 Todd C. Miller - * ldap.c, sudoers.ldap.pod: + * doc/sudoers.ldap.pod, plugins/sudoers/ldap.c: Pick last match in LDAP sudoers too - [607801b83e25] <1.7> + [fbfd8e85703b] + + * doc/sudo_plugin.pod: + Document iolog_file, iolog_dir and use_pty + [26120a59c20e] + + * plugins/sample/sample_plugin.c, plugins/sudoers/iolog.c, + plugins/sudoers/sudoers.c: + Adapt plugins to version I/O logging ABI 1.1 + [880dd64bc1e8] + + * src/exec.c, src/sudo.h: + Add use_pty command_info flag for policies to indicate that a pty + should be allocated even if no I/O logging is performed. + [e7b167f8a6e5] + + * src/sudo.c: + Add remaining plugin convenience functions + [ffeaf96da031] + + * include/sudo_plugin.h, src/sudo.c, src/sudo.h, + src/sudo_plugin_int.h: + Change I/O log API to pass in command info to the I/O log open + function. Add iolog_file and iolog_dir parameters to command info. + This allows the policy plugin to specify the I/O log pathname. Add + convenience functions for calling plugin functions that handle ABI + backwards compatibility. + [9b81dce76ce5] + + * compat/dlopen.c: + Remove useless cast + [7cecce969739] + +2010-12-17 Todd C. Miller + + * configure, configure.in: + Bump version to 1.8.0b3 + [1dc9f040aae0] + +2010-12-13 Todd C. Miller + + * configure.in: + Remove extraneous newline + [71c94551eea5] 2010-12-10 Todd C. Miller - * aclocal.m4, configure, configure.in, def_data.c, def_data.h, - def_data.in, defaults.c, iolog.c, sudoers.pod: - Make the iolog dir configurable in sudoers - [2630b2dba1b5] <1.7> + * doc/sudoers.pod, plugins/sudoers/def_data.c, + plugins/sudoers/def_data.h, plugins/sudoers/def_data.in, + plugins/sudoers/defaults.c, plugins/sudoers/iolog.c: + Make I/O log dir configurable. + [99b576667a38] + + * aclocal.m4, configure, configure.in, doc/sudoers.pod: + Rename io_logdir to iolog_dir + [0731662acc8d] 2010-12-07 Todd C. Miller * pp: Add missing '*' that prevented the generic ELF case from matching. - [b35bbb42736f] <1.7> + [be77ca26bfb2] * pp: If file(1) can't identify the ELF binary type, try readelf(1). - [8a73092d8898] <1.7> + [38a18d32a9e3] 2010-11-30 Todd C. Miller - * auth/kerb4.c, check.c, env.c, pwutil.c, sudo.c: + * plugins/sudoers/auth/kerb4.c, plugins/sudoers/check.c, + plugins/sudoers/env.c, plugins/sudoers/pwutil.c, + plugins/sudoers/sudoers.c, src/sudo.c: Use %u to print uid/gid, not %lu and adjust casts to match. - [e4eb94705a54] <1.7> - - * NEWS: - Update with latest changes - [2c4209b20e3d] <1.7> + [03c43b8749cf] - * sudoers.ldap.pod: - Clarify ordering of entries and attributes - [598748ec3804] <1.7> + * doc/sudoers.ldap.pod: + Clarify ordering of entries and attributes. + [924e2a6bb603] - * sudoers.ldap.pod: + * doc/sudoers.ldap.pod: Fix typo and editing goof. - [197a2fe65be5] <1.7> + [79dc7ccd85a8] - * ldap.c: + * doc/schema.ActiveDirectory, doc/schema.OpenLDAP, doc/schema.iPlanet, + doc/sudoers.ldap.pod: + Merge in ordered LDAP entry support from Andreas Mueller. + [ea5885989bad] + + * plugins/sudoers/ldap.c: Make sure we don't dereference a NULL handle. - [b0026541de1e] <1.7> + [1a9f9ee15371] 2010-11-24 Todd C. Miller * pp: Add support for RHEL 6 file modes that include a trailing dot on files with an SELinux security context - [fcc1daaf4df0] <1.7> + [dc09be959547] + +2010-11-23 Todd C. Miller + + * src/sudo.c: + exec_setup() does not need to setuid(0), the Ubuntu issue was in the + sudoers module. + [d6dd99fc6062] + + * plugins/sudoers/sudoers.c: + create_admin_success_flag() should use restore_perms() rather than + set_perms() to restore the uid. + [eba7a91c1f57] + + * src/sudo.c: + In exec_setup() call setuid(0) to make certain the subsequent uid + and gid changes will succeed. Fixes a problem on Ubuntu. + [c5d32abf0645] + + * src/sudo_edit.c: + Error out if we cannot change to root's uid so we catch the failure + early. + [7a2e7f8f2c80] 2010-11-22 Todd C. Miller - * sudoers.pod: + * doc/sudoers.pod: fix typo; from Michael T Hunter - [46e70e2063af] <1.7> + [a574a9d0db5b] - * match.c: + * plugins/sudoers/match.c: In sudoedit mode, assume command line arguments are paths and pass FNM_PATHNAME to fnmatch(). - [6087ba0064ff] <1.7> + [ce0abff8ce9f] 2010-11-20 Todd C. Miller @@ -876,147 +1602,189 @@ Add workaround for an error in sys/types.h on HP-UX 11.23 when large file support is enabled. Defining _XOPEN_SOURCE_EXTENDED avoids the broken bits of the header file. - [12da5b3249a3] <1.7> + [e337217f097a] * aclocal.m4: Fix SUDO_MAILDIR usage of AC_LANG_PROGRAM - [c0105d26574a] <1.7> - - * testsudoers.c, tsgetgrpw.c, tsgetgrpw.h: - Avoid conflicts with system definitions in grp.h and pwd.h - [a152522c9f13] <1.7> + [fbbcee28961f] * sudo.pp: For Tru64, strip off beta version. - [a16213ec9c27] <1.7> + [eeccd762df5e] + + * MANIFEST, plugins/sudoers/testsudoers.c, + plugins/sudoers/tsgetgrpw.c, plugins/sudoers/tsgetgrpw.h: + Avoid conflicts with system definitions in grp.h and pwd.h + [b219ffe1da09] * zlib/gzguts.h: Include stdio.h after zlib.h, not before. We need the large file defines to come first. - [389ea592d6c2] <1.7> + [21d6df39790f] + +2010-11-19 Todd C. Miller + + * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in: + regen + [3ff8750d0aac] + + * Makefile.in: + Don't clean ChangeLog + [ab0d30d289d4] + + * plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c: + Add prototype for cleanup() + [75626fd3769a] + +2010-11-18 Todd C. Miller + + * plugins/sudoers/group_plugin.c: + Avoid deferencing group_plugin if it is NULL in + group_plugin_query(). This should not happen. + [4f2933c8da7e] + + * plugins/sudoers/group_plugin.c: + group plugin init function return TRUE when successful + [198024477030] 2010-11-17 Todd C. Miller - * ldap.c: + * plugins/sudoers/ldap.c: Enlarge the array of entry wrappers int blocks of 100 entries to save on allocation time. From Andreas Mueller - [db8da143e803] <1.7> + [375c916bb03b] - * ldap.c: + * plugins/sudoers/ldap.c: Add back call to sudo_ldap_timefilter() in sudo_ldap_build_pass2() that was mistakenly dropped. - [f6f1103f9971] <1.7> + [1555f5bc132d] 2010-11-16 Todd C. Miller - * TROUBLESHOOTING: + * doc/TROUBLESHOOTING: Mention that sudo needs "ar" to build. - [eef95d0abfbe] <1.7> + [65582ace2d09] * configure, configure.in: Fail with a more useful error if "ar" is not found. - [1ef3c8501bf5] <1.7> + [d1cb83719c17] 2010-11-14 Todd C. Miller - * ldap.c: - Reorder things to avoid most of the extra prototypes. - [0541a55deb86] <1.7> + * plugins/sudoers/ldap.c: + Merge in ordered LDAP entry support from Andreas Mueller and add + local changes from the 1.7 branch. + [bca29e461618] - * ldap.c: - Inline sudo_ldap_result_get_entry(), it is always called in - situations where the bounds are already checked. - [fa65cf4eaf5e] <1.7> +2010-11-12 Todd C. Miller - * ldap.c: - Add user_matches and host_matches to struct ldap_result and set them - in sudo_ldap_result_get() which is where the user and host checks - live. When iterating through the ordered results, take the first - match. Remove allowed flag from struct ldap_entry_wrapper, we just - use first match. - [9a008cd81685] <1.7> - -2010-11-13 Todd C. Miller - - * configure, configure.in, sudo.cat, sudo.man.in, sudoers.cat, - sudoers.ldap.cat, sudoers.ldap.man.in, sudoers.man.in, - sudoreplay.cat, sudoreplay.man.in, visudo.cat, visudo.man.in: - Bump version and regen man pages - [918433185f26] <1.7> - - * ldap.c, schema.ActiveDirectory, schema.OpenLDAP, schema.iPlanet, - sudoers.ldap.pod: - Merge in ordered LDAP entry support from Andreas Mueller. - [21b8071c2f28] <1.7> + * doc/schema.ActiveDirectory, doc/schema.OpenLDAP, doc/schema.iPlanet, + doc/sudoers.ldap.pod, plugins/sudoers/ldap.c: + Add timed entry support from Andreas Mueller. + [e18d1df46a8d] -2010-11-11 Todd C. Miller + * plugins/sudoers/group_plugin.c: + Don't try to unload if group_plugin is NULL. Don't call dlclose() if + group_handle is NULL + [de2273da37d5] - * ldap.c, schema.ActiveDirectory, schema.OpenLDAP, schema.iPlanet, - sudoers.ldap.pod: - Add timed entry support from Andreas Mueller. - [10b121c46a1c] <1.7> + * plugins/sudoers/sudoers.h: + It is now plugin_cleanup(), not cleanup() + [da62a4e1a78c] - * ldap.c: - Use efree() not free() and remove malloc.h include since we never - directly call malloc() or free(). - [f2184b2a0646] <1.7> + * plugins/sudoers/logging.c, plugins/sudoers/sudoers.c: + Call plugin_cleanup(), not cleanup() + [e800ad8b33ad] -2010-11-10 Todd C. Miller +2010-11-11 Todd C. Miller - * Makefile.in, getdate.c, gram.c, toke.c: - Include config.h before any other includes to make sure we get the - right value for _FILE_OFFSET_BITS. - [5a8c12426942] <1.7> + * plugins/sudoers/ldap.c: + Use efree() not free() and remove malloc.h include since we never + directly call malloc() or free(). + [107fffd134bb] 2010-11-09 Todd C. Miller * sudo.pp: set PSTAMP for Solaris and move the backend-specific bits to their own %if [xxx] %endif blocks in %set. - [0d93cb5d009a] <1.7> + [a94ebe8920c1] * pp: sync with git repo - [e052d78dde35] <1.7> + [75ff509696b4] -2010-11-03 Todd C. Miller + * configure, configure.in: + Only substitute file zlib files when using the builtin zlib + [6c8145b2deb4] + + * common/Makefile.in, compat/Makefile.in, plugins/sample/Makefile.in, + plugins/sample_group/Makefile.in, plugins/sudoers/Makefile.in, + src/Makefile.in, zlib/Makefile.in: + Give up on using VPATH to find sources as it is implemented + inconsistenly in different versions of make. + [60517c69aaee] + + * plugins/sudoers/Makefile.in, plugins/sudoers/getdate.c, + plugins/sudoers/gram.c, plugins/sudoers/toke.c: + Include config.h before any other includes to make sure we get the + right value for _FILE_OFFSET_BITS. + [8fb007ca832e] - * Makefile.in: - remove zlib/zconf.h for distclean - [5cf14594d014] <1.7> + * MANIFEST: + Add zlib + [04a3e23dfaa9] - * sudo.cat, sudo.man.in, sudoers.cat, sudoers.ldap.cat, - sudoers.ldap.man.in, sudoers.man.in, visudo.cat, visudo.man.in: - regen man pages for 1.7.5 - [29253a721cfd] <1.7> + * zlib/Makefile.in: + Add missing targets + [40e45a177168] - * configure: - regen - [5b09c0dd9279] <1.7> + * src/Makefile.in: + g/c unused $(GENERATED) + [c8758068c1bc] - * NEWS: - Update 1.7.5 entries. - [73a7b2c01db4] <1.7> +2010-11-08 Todd C. Miller -2010-11-02 Todd C. Miller + * plugins/sudoers/group_plugin.c: + Zero out group_plugin on unload just to be safe. + [0b10f4d101ca] - * Makefile.in: - Include zlib in the tar file. - [3b7900c3f2af] <1.7> + * plugins/sudoers/group_plugin.c: + Unload group plugin if its init function fails. + [6552cdac4b7c] + + * src/sudo.c: + Only chdir to cwd if it is different from the current cwd or there + is a new root (chroot). + [b8203e875e84] + + * configure, configure.in, doc/sudo.cat, doc/sudo.man.in, + doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudoers.ldap.cat, + doc/sudoers.ldap.man.in, doc/visudo.cat, doc/visudo.man.in: + Bump version to 1.8.0b2 + [6dadeb75a878] 2010-10-28 Todd C. Miller * INSTALL: Better --enable-zlib description - [0ca9936a7271] <1.7> + [e0da54fa59a6] * mkpkg: Use system zlib on Linux Let configure decide on Solaris For all others, use builtin zlib - [58e1b4383b58] <1.7> + [3d52eddb523c] + + * zlib/zconf.h.in: + Add large file support. + [bec01215270d] + + * config.h.in: + Add large file support. + [244e95b034ec] - * LICENSE, Makefile.in, config.h.in, configure, configure.in, - license.pod, zlib/adler32.c, zlib/compress.c, zlib/crc32.c, + * Makefile.in, configure, configure.in, doc/LICENSE, doc/license.pod, + zlib/Makefile.in, zlib/adler32.c, zlib/compress.c, zlib/crc32.c, zlib/crc32.h, zlib/deflate.c, zlib/deflate.h, zlib/gzclose.c, zlib/gzguts.h, zlib/gzlib.c, zlib/gzread.c, zlib/gzwrite.c, zlib/infback.c, zlib/inffast.c, zlib/inffast.h, zlib/inffixed.h, @@ -1024,164 +1792,245 @@ zlib/trees.c, zlib/trees.h, zlib/uncompr.c, zlib/zconf.h.in, zlib/zlib.h, zlib/zutil.c, zlib/zutil.h: Add local copy of zlib for systems that lack it. - [060627a4a413] <1.7> + [7542ca465c5a] + +2010-10-15 Todd C. Miller + + * src/exec.c: + If perform_io() fails, kill the child before exiting so it doesn't + complain about connection reset. We can get an I/O error if, for + example, and we get EIO reading from stdin. + [e59a05fa729f] 2010-10-12 Todd C. Miller + * plugins/sudoers/sudoers.c, src/sudo.c: + Fix complilation on systems with set_auth_parameters() Sprinkle + volatile to quiet warnings from gcc 2.8.0 + [a34c2b924ba7] + + * compat/dlfcn.h, compat/dlopen.c: + Avoid potential namespace issues with dlopen() emulation. + [aedfababd6ca] + + * MANIFEST: + sync + [6afb97e6d308] + + * plugins/sudoers/interfaces.c: + Use INADDR_NONE instead of casting -1 to in_addr_t (which may not + exist). + [ddfca5af1a36] + * Makefile.in: - Don't overwrite ChangeLog if we can't run hg - [8cad8bfce9ee] <1.7> + Mark ChangeLog as PHONY Don't overwrite ChangeLog if we can't run hg + [e9d04bfa4505] * configure, configure.in: - HP-UX 10.20 libc has an incompatible getline() - [6ae1631c6993] <1.7> + HP-UX 10.20 libc has an incompatible getline + [2e7bc202e78d] - * visudo.c: + * plugins/sudoers/visudo.c: Quiet an HP-UX compiler warning. - [b8eb3006d68b] <1.7> + [55b9d587ac8c] + + * configure, configure.in: + Check for vi even with --with-editor specified; the sample plugin + needs it. + [94dfc3643f76] 2010-10-11 Todd C. Miller + * compat/dlopen.c: + Fix remaining syntax errors. + [9d729b5b577e] + + * src/Makefile.in: + sudo binary depends on the libtool-generated libs + [9e6148406adb] + + * plugins/sudoers/group_plugin.c, src/load_plugins.c: + Use HAVE_DLOPEN instead of HAVE_DLFCN_H when determining whether to + include the local or system dlfcn.h + [68cfe4c1089b] + * pp: Don't use run_as_superuser=false on HP-UX - [2a9ec2750082] <1.7> + [532242370b09] + + * src/net_ifs.c: + Use memset() instead of zero_bytes() since we don't include + sudoers.h + [a187c18c2472] + + * plugins/sudoers/interfaces.c: + Fix pasto; AF_INET not AF_INET6 + [2d2e9d7dc6f9] + + * compat/dlopen.c: + Actually call shl_load() + [ed8153b8a3cd] * pp: Update from git repo. Debian: version numbers now compliant with policy section 5.6.12 HP-UX: minimal changes needed to work on HP-UX 10.20 - [cfe38672e358] <1.7> - - * configure, configure.in: - Go back to checking whether the compiler is ANSI C when detecting - the HP-UX bundled C compiler. - [563ef7333662] <1.7> + [ecf2692bceeb] * configure, configure.in: - Fix syntax error - [96048f77d772] <1.7> + Fix dlopen() detection for systems where dlopen() is in a separate + library. + [fa6b175582b6] - * auth/pam.c: + * plugins/sudoers/auth/pam.c: If pam_acct_mgmt() returns PAM_AUTH_ERR print a (hopefully) more useful message and return AUTH_FATAL so sudo does not keep trying to validate the user. - [fffa5e51ac47] <1.7> + [1be8857e5291] -2010-10-07 Todd C. Miller + * src/preload.c: + sudo_preload_table is an array + [b7704e72a9da] + + * compat/dlopen.c: + Quiet a compiler warning and fix sudo_preload_table external + definition. + [8234987664cc] - * exec_pty.c: - don't need ws_col here - [049b4ef9c9ce] <1.7> + * compat/dlfcn.h: + Fix multiple inclusion guard in dlfcn.h and fix dlerror() prototype. + [8bab6a4053cc] - * check.c: + * plugins/sudoers/group_plugin.c: + Make this compile correctly when no dlopen is available. + [57643879bd2b] + +2010-10-07 Todd C. Miller + + * plugins/sudoers/check.c: Having a timestamp file defined is no longer indicative of tty tickets being enabled. Check def_tty_tickets directly. - [6c3803c239d9] <1.7> + [efcc11ad157f] - * exec_pty.c, lbuf.c: + * src/exec_pty.c, src/sudo.h, src/ttysize.c: Fix TCGETWINSZ compat. - [62233ba46ec7] <1.7> + [da3a8b17cf7a] 2010-10-02 Todd C. Miller - * exec_pty.c, lbuf.c: + * src/exec_pty.c, src/ttysize.c: Prefer newer TIOCGWINSZ ioctl to old TIOCGSIZE - [0813e3030b1a] <1.7> + [926492dd10a6] 2010-10-01 Todd C. Miller - * set_perms.c: - Sync set_project() with trunk. - [646fd9bc0537] <1.7> + * plugins/sudoers/sudoers.c, src/sudo.c: + Move set_project() from sudoers module into sudo proper. + [beabafac03b4] - * ldap.c: + * configure, configure.in: + Fix typo and regenerate + [4a3caf4234f3] + + * plugins/sudoers/ldap.c: When iterating over returned LDAP entries, keep looking at remaining matches even if we have a positive match. This catches negative matches that may exist in other entries and more closely match the sudoers file behavior. - [8dce1dedb967] <1.7> + [f47db6e609b0] * pp: Add support for multiple package instances on Solaris. - [5bcc048375db] <1.7> - - * set_perms.c, sudo.c: - Move set_project() into runas_setup(). Fixes a NULL deref when - project support is enabled and sudo's -g flag is used without the - -u flag. - [6ffd892243ab] <1.7> + [7f2a8b942545] - * exec.c: + * src/exec.c: Add missing signal_pipe[0] to fdsr for the non-pty case. - [3398af88db51] <1.7> + [79d01e11b19c] * mkpkg: Add --with-project for Solaris - [25bd2aa83884] <1.7> + [ffa4c2bb93f7] * README: Need ar and ranlib too - [d09e632d0a93] <1.7> + [5c2f679172ef] 2010-09-27 Todd C. Miller - * env.c: + * plugins/sudoers/env.c: Preserve ODMDIR environment variable by default on AIX. - [75266d18e4a7] <1.7> + [bd47cb1e804f] + +2010-09-26 Todd C. Miller + + * Makefile.in, compat/Makefile.in, compat/dlfcn.h, compat/dlopen.c, + config.h.in, configure, configure.in, plugins/sample/Makefile.in, + plugins/sample_group/Makefile.in, plugins/sudoers/Makefile.in, + plugins/sudoers/group_plugin.c, plugins/sudoers/plugin_error.c, + plugins/sudoers/sudoers.c, src/Makefile.in, src/load_plugins.c, + src/preload.c: + Add dlopen() emulation for systems without it. For HP-UX 10, emulate + using shl_load(). For others, link sudoers plugin statically and use + a lookup table to emulate dlsym(). + [e92edfb3c642] + +2010-09-24 Todd C. Miller + + * compat/fnmatch.c, compat/glob.c, compat/mksiglist.c, + compat/nanosleep.c, compat/utimes.c: + When including compat headers, use the compat dir as part of the + path so we are sure to get the correct header. + [6c2a45da6af5] 2010-09-21 Todd C. Miller - * linux_audit.c: + * plugins/sudoers/linux_audit.c: Ignore ECONNREFUSED from audit_log_user_command() which will occur if auditd is not running. - [a686884684ca] <1.7> + [d314fe4c8d03] 2010-09-17 Todd C. Miller * pp: Sync with git version - [9a328aa25c53] <1.7> + [1c0357744222] 2010-09-16 Todd C. Miller - * defaults.c, fileops.c: + * common/fileops.c, plugins/sudoers/defaults.c: Cast isblank argument to unsigned char. - [64b9f3bed954] <1.7> + [c822dbb3ca54] 2010-09-14 Todd C. Miller - * INSTALL, config.h.in, configure, configure.in, defaults.c, - sudoers.cat, sudoers.man.in, sudoers.pod: + * INSTALL, config.h.in, configure, configure.in, doc/sudoers.cat, + doc/sudoers.man.in, doc/sudoers.pod, plugins/sudoers/defaults.c: Implement --with-umask-override configure flag. - [5065008079df] <1.7> + [863e3047df22] - * env.c: + * plugins/sudoers/env.c: Take MODE_LOGIN_SHELL into account when initially setting reset_home instead of special-casing it later. - [25e6b8419dea] <1.7> + [5d6b16480fd6] - * sudo.c: + * plugins/sudoers/sudoers.c: In login mode, make a copy of the runas user's pw_shell for NewArgv[0] because 1) we modify it and 2) it will runas_pw gets freed before exec. - [4a0851a7688a] <1.7> + [1d1ccb568dfa] - * env.c: + * plugins/sudoers/env.c: Reset HOME for "sudo -i" even if HOME was listed in env_keep. - [8dc31006a428] <1.7> + [c1c1c65a2d63] - * sudo.c: + * src/sudo.c: Use SIG_SETMASK when resetting signal mask instead of SIG_UNBLOCK. - [8751ef94b18d] <1.7> + [7443454e5f88] - * sudo.c: + * src/sudo.c: Reset signal mask at sudo startup time; we need to be able to rely on normal signal delivery to control the child process. - [c986a4b6a942] <1.7> - - * sigaction.c: - Fix SIG_UNBLOCK emulation - [f14264f8a0da] <1.7> + [95800163ff94] 2010-09-13 Todd C. Miller @@ -1189,330 +2038,401 @@ Use sed instead of expr to split a flag from its argument. Fixes a problem with expr interpreting its arguments as a flag when they start with a dash. - [16372da8a286] <1.7> + [736065e14301] - * lbuf.c: - Back out rev e165f67d3127 - [e9b70079698d] <1.7> + * common/lbuf.c: + Do not need sys/time.h after all + [91f6f668ccda] - * lbuf.c: - Include sys/time.h for utimes() and struct timeval. - [e165f67d3127] <1.7> + * common/lbuf.c: + Include sys/time.h for utimes() and struct timeval. No longer need + ioctl.h or termios.h + [2d75273d3213] - * snprintf.c: + * compat/snprintf.c: Quiet bogus compiler warnings. - [176fceb8db3c] <1.7> + [fe252e1968f5] - * missing.h: + * include/missing.h: Declare innetgr() for HP-UX which is missing a declaration. Declare domainname() for HP-UX and Solaris which are missing a declaration. - [0b4c1296d4da] <1.7> + [b37c50751138] - * bsm_audit.c: + * plugins/sudoers/bsm_audit.c: Use __sun for consistency with the rest of the sources. - [8f0db6350b3a] <1.7> + [6b086b61ccb6] - * pwutil.c: + * plugins/sudoers/group_plugin.c: + Quiet a bogus compiler warning. + [ebc069842c4a] + + * plugins/sudoers/pwutil.c: Don't try to delref a NULL group. - [57e94fc5df3e] <1.7> + [f6ff0838be21] - * alloc.c, lbuf.c: + * common/alloc.c, common/lbuf.c: Include memory.h on systems that need it. - [e43d8d8a0008] <1.7> + [4e676da81c6f] 2010-09-11 Todd C. Miller - * exec.c: + * src/exec.c: Quiet gcc warnings on glibc systems that use warn_unused_result for write(2). - [f22696affc78] <1.7> + [0532da0b7cf7] + + * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod: + sudo_plugin is in section 8; from Ted Percival + [b4506a0de87e] + + * plugins/sudoers/Makefile.in: + testsudoers depends on libsudoers.la, not sudoreplay + [cdb1cc3bf06a] 2010-09-10 Todd C. Miller - * NEWS, README, configure, configure.in: - Update for sudo 1.7.5 - [62ed8c6cb7c2] <1.7> + * src/exec.c: + Read as many signals on the signal pipe as we can before returning. + [b181671da047] - * exec.c, exec_pty.c, list.c, list.h, sudo_exec.h: + * src/exec.c, src/exec_pty.c, src/sudo_exec.h: Instead of using a array to store received signals, open a pipe and have the signal handler write the signal number to one end and select() on the other end. This makes it possible to handle signals similar to I/O without race conditions. - [2d9dd09a9fce] <1.7> - - * INSTALL: - --with-iologdir not --enable-iologdir - [457471aaeda6] <1.7> + [ee84d65c16b6] 2010-09-09 Todd C. Miller - * visudo.c, visudo.pod: + * doc/visudo.pod, plugins/sudoers/visudo.c: Make "visudo -c -f -" check the standard input. - [8ed46ff3141a] <1.7> + [195a3d2a9a26] - * sudoers.pod: + * doc/sudoers.pod: set_home and always_set_home have an effect if HOME is present in the env_keep list. - [a2b26d62176d] <1.7> + [159d0b9dc5c8] - * env.c: + * plugins/sudoers/env.c: Make -H flag work when HOME is listed in env_keep. Also makes "set_home" and "always_set_home" override override HOME in env_keep. - [91d842b6adc6] <1.7> + [a3e5b966193f] 2010-09-08 Todd C. Miller - * bsm_audit.c: + * plugins/sudoers/Makefile.in, plugins/sudoers/interfaces.c, + plugins/sudoers/interfaces.h, plugins/sudoers/match.c, + plugins/sudoers/sudoers.c, plugins/sudoers/testsudoers.c, + plugins/sudoers/visudo.c, src/net_ifs.c: + Convert sudoers plugin to use interface list passed in settings. + [87d9b5f4f586] + + * doc/sudo_plugin.pod, src/Makefile.in, src/net_ifs.c, + src/parse_args.c, src/sudo.h: + Query local network interfaces in the main sudo driver and pass to + the plugin as "network_addrs" in the settings list. + [7f35bcfe77a7] + + * plugins/sudoers/bsm_audit.c: Solaris BSM audit return EINVAL when auditing is not enabled, whereas OpenBSM returns ENOSYS. - [bb9c94a8fa7d] <1.7> + [411b980ec58b] 2010-09-07 Todd C. Miller - * toke.c, toke.l: - Add missing LOG_INPUT/LOG_OUTPUT support in the lexer. - [0a5519756bf1] <1.7> + * compat/fnmatch.c: + missing.h should come before most local includes + [53921a7b8b5b] - * sudo.c: - Set NewArgv[0] to the name of the pseudo-command we are running. - Fixes a problem with "sudo -l" when auditing is enabled and the user - is not allowed to run any commands on the host. Adapted from a patch - from Daniel Kopecek. - [694ed1a75a4a] <1.7> + * plugins/sudoers/sudoreplay.c: + missing.h should come before most local includes + [e9abb0db1aac] - * sudo.c: - Update comment to reality. - [de302f39566b] <1.7> + * plugins/sudoers/sudoers.h: + Make local includes consistent; use double quotes for local includes + except for generated ones where we use angle brackets. + [09de4faa9547] - * missing.h: - Need stdio.h for FILE *, not just NULL. - [77cf303f5696] <1.7> + * plugins/sudoers/sudoers.c: + Always fill in NewArgv for audit code. + [7c3aca60519f] + + * plugins/sudoers/toke.c, plugins/sudoers/toke.l: + Add missing LOG_INPUT/LOG_OUTPUT support in the lexer. + [007cf6560f92] + + * common/alloc.c, common/atobool.c, common/fileops.c, + common/fmt_string.c, common/lbuf.c, common/list.c, common/term.c, + common/zero_bytes.c, compat/closefrom.c, compat/fnmatch.c, + compat/getcwd.c, compat/getgrouplist.c, compat/getline.c, + compat/getprogname.c, compat/glob.c, compat/isblank.c, + compat/memrchr.c, compat/mksiglist.c, compat/mkstemps.c, + compat/nanosleep.c, compat/setenv.c, compat/snprintf.c, + compat/strlcat.c, compat/strlcpy.c, compat/strsignal.c, + compat/unsetenv.c, compat/utimes.c, include/compat.h, + plugins/sample/sample_plugin.c, plugins/sample_group/getgrent.c, + plugins/sample_group/plugin_test.c, + plugins/sample_group/sample_group.c, plugins/sudoers/audit.c, + plugins/sudoers/auth/afs.c, plugins/sudoers/boottime.c, + plugins/sudoers/getdate.c, plugins/sudoers/getdate.y, + plugins/sudoers/linux_audit.c, plugins/sudoers/match.c, + plugins/sudoers/plugin_error.c, plugins/sudoers/sudoreplay.c, + plugins/sudoers/timestr.c, src/error.c, src/sesh.c, src/sudo.h, + src/sudo_noexec.c, src/ttysize.c: + Make local includes consistent; use double quotes for local includes + except for generated ones where we use angle brackets. Also g/c + unused compat.h. + [e57070dc8f04] 2010-09-06 Todd C. Miller - * match.c: + * plugins/sudoers/match.c: When matching the runas user and runas group (-u and -g command line options), keep track of runas group and runas user matches separately. Only return a positive match if we have a match for both runas user and runas group (if specified). - [68d30216c13a] <1.7> + [815219e04cc8] 2010-09-04 Todd C. Miller - * ldap.c, parse.c: - Do not return -1 on error from the display functions; the call - expects a return value >= 0. - [e50e6ae4d06d] <1.7> + * doc/sudoers.ldap.pod, plugins/sudoers/ldap.c: + Add support for multiple URI lines by joining the contents and + passing the result to ldap_initialize. + [a47cae3b72e8] - * ldap.c: - display_bound_defaults now returns a count so make the stub return - 0, not 1. - [97293ced4908] <1.7> + * plugins/sudoers/ldap.c, plugins/sudoers/parse.c: + Do not return -1 on error from the display functions; the caller + expects a return value >= 0. + [101456a7dd00] - * fnmatch.c: - Add #include of sys/types.h for .c files that include missing.h to - be sure that size_t and ssize_t are defined. - [a4f3070d0a2b] <1.7> + * plugins/sudoers/sudoers.c: + Do not set both MODE_EDIT and MODE_RUN + [8faa36694d54] 2010-09-03 Todd C. Miller - * get_pty.c: - It looks like AIX doesn't need to push STREAMS modules for ptys. - [62c281fcd4ad] <1.7> + * include/missing.h: + Move includes to the top of the file. + [a51436798e8c] 2010-08-30 Todd C. Miller - * error.c, getprogname.c, isblank.c, missing.h, mksiglist.c, - sigaction.c, strerror.c, strsignal.c, sudo_noexec.c: + * plugins/sudoers/Makefile.in: + Add missing definition of timedir + [458a749c2c5e] + + * compat/fnmatch.c, compat/getprogname.c, compat/isblank.c, + compat/mksiglist.c, compat/strsignal.c, + plugins/sudoers/plugin_error.c, src/error.c, src/sudo_noexec.c: Add #include of sys/types.h for .c files that include missing.h to be sure that size_t and ssize_t are defined. - [2ffbbb12f322] <1.7> + [08e3132dbf4f] - * Makefile.in: + * plugins/sudoers/Makefile.in: Install sudoers file from the build dir not hte src dir. - [a26afd8db531] <1.7> + [ca89e962dbf4] 2010-08-26 Todd C. Miller - * set_perms.c: + * plugins/sudoers/set_perms.c: If runas_pw changes, reset the stashed runas aux group vector. Otherwise, if runas_default is set in a per-command Defaults statement, the command runs with root's aux group vector (i.e. the one that was used when locating the command). - [24a695707b67] <1.7> + [24f9107cedd2] - * Makefile.in: + * plugins/sudoers/Makefile.in: Add target to generate sudoers file Remove generated sudoers file as part of distclean - [448627fc35b6] <1.7> + [fb7422e90f03] -2010-08-23 millert +2010-08-24 Todd C. Miller - * exec.c: + * src/exec.c: When not logging I/O install a handler for SIGCONT and deliver it to the command upon resume. Fixes bugzilla #431 - [e84690aa67bd] <1.7> + [495dce52a5aa] 2010-08-21 Todd C. Miller - * sudo.c, sudo.h: - g/c unused auth_pw global - [e30778d73c0b] <1.7> + * plugins/sudoers/sudoers.h: + g/c unused auth_pw extern definition + [40eb7477ba17] - * check.c, sudo.c: + * plugins/sudoers/check.c, plugins/sudoers/sudoers.c: Move get_auth() into check.c where it is actually used. - [3130e37787af] <1.7> - - * sudo.c: - Don't need to fork and wait when compiled with --disable-pam-session - [2ae1bbe4437a] <1.7> + [e31db0ce3a61] 2010-08-20 Todd C. Miller - * lbuf.c: + * common/lbuf.c: Convert a remaining puts() and putchar() to use the output function. - [d68c213feb0f] <1.7> + [d69e363a506b] -2010-08-18 Todd C. Miller + * plugins/sudoers/plugin_error.c: + Plug memory leak + [68895469ea8d] - * Makefile.in: - Replace sudoers with sudoers.in in DISTFILES - [616509f85d6c] <1.7> +2010-08-18 Todd C. Miller - * env.c: + * plugins/sudoers/env.c: Set dupcheck to TRUE when setting new HOME value if !env_reset but always_set_home is true. Prevents a duplicate HOME in the - environment (old value plus the new one) introduced in 9f97e4b43a4b. - [2672ae047984] <1.7> + environment (old value plus the new one) introduced in f421f8827340. + [9ca19183794f] - * configure, configure.in, sudoers, sudoers.in: + * configure, configure.in, plugins/sudoers/sudoers, + plugins/sudoers/sudoers.in: Substitute sysconfdir in the installed sudoers file to get the correct path for sudoers.d. - [ab14a68e546f] <1.7> + [86072b6cd55d] 2010-08-17 Todd C. Miller - * boottime.c, get_pty.c: - Fix typos that prevented compilation on Irix; Friedrich Haubensak - [a3e6c5a66890] <1.7> + * src/get_pty.c: + Fix typo that prevented compilation on Irix; Friedrich Haubensak + [b48be51b65fc] 2010-08-16 Todd C. Miller - * Makefile.in, aix.c, audit.c, boottime.c, compat.h, error.c, - fnmatch.c, getcwd.c, getdate.c, getdate.y, getline.c, getprogname.c, - gettime.c, glob.c, isblank.c, linux_audit.c, memrchr.c, missing.h, - mksiglist.c, nanosleep.c, sesh.c, setsid.c, sigaction.c, snprintf.c, - strcasecmp.c, strerror.c, strlcat.c, strlcpy.c, strsignal.c, sudo.h, - sudo_noexec.c, sudoreplay.c, timestr.c, utimes.c, vasgroups.c, - zero_bytes.c: + * MANIFEST, common/Makefile.in, common/aix.c, common/alloc.c, + common/atobool.c, common/fileops.c, common/fmt_string.c, + common/lbuf.c, common/list.c, common/term.c, common/zero_bytes.c, + compat/Makefile.in, compat/closefrom.c, compat/fnmatch.c, + compat/getcwd.c, compat/getgrouplist.c, compat/getline.c, + compat/getprogname.c, compat/glob.c, compat/isblank.c, + compat/memrchr.c, compat/mksiglist.c, compat/mkstemps.c, + compat/nanosleep.c, compat/setenv.c, compat/snprintf.c, + compat/strlcat.c, compat/strlcpy.c, compat/strsignal.c, + compat/unsetenv.c, compat/utimes.c, include/compat.h, + include/missing.h, plugins/sample/sample_plugin.c, + plugins/sample_group/getgrent.c, + plugins/sample_group/sample_group.c, plugins/sudoers/Makefile.in, + plugins/sudoers/audit.c, plugins/sudoers/boottime.c, + plugins/sudoers/getdate.c, plugins/sudoers/getdate.y, + plugins/sudoers/linux_audit.c, plugins/sudoers/plugin_error.c, + plugins/sudoers/sudoers.h, plugins/sudoers/sudoreplay.c, + plugins/sudoers/timestr.c, src/Makefile.in, src/error.c, src/sesh.c, + src/sudo.h, src/sudo_noexec.c, src/ttysize.c: Merge compat.h and missing.h into missing.h - [905905c7a8f0] <1.7> + [572909ae9716] 2010-08-14 Todd C. Miller - * auth/pam.c: + * plugins/sudoers/auth/pam.c: If the user hits ^C while a password is being read, error out before reading any further passwords in the pam conversation function. Otherwise, if multiple PAM auth methods are required, the user will have to hit ^C for each one. - [c8f6bc58fd86] <1.7> + [23782631748c] -2010-08-09 Todd C. Miller +2010-08-12 Todd C. Miller - * exec.c: - Fix waitpid() loop termination condition. - [97719b3259f2] <1.7> + * plugins/sudoers/check.c: + Update comment + [a5296cb3a20a] - * exec_pty.c: - Use sudo_waitpid() instead of bare waitpid() - [624a40269189] <1.7> + * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod: + Document sudo_conv_t function and sudo_printf_t return values. + [745c0017814c] + + * src/conversation.c: + Make _sudo_printf return the number of characters printed on success + like printf(3). + [8eeefe8d7e77] + +2010-08-10 Todd C. Miller + + * plugins/sudoers/sudoers.c: + sudoers.h includes sudo_plugin.h for us + [cabe68e07807] + + * common/Makefile.in, common/gettime.c, compat/mkstemps.c, + plugins/sudoers/sudoers.h, plugins/sudoers/visudo.c, src/sudo.h, + src/sudo_edit.c: + Use gettimeofday() directly instead of via the gettime() wrapper. + [7490426c99ae] + + * common/gettime.c, compat/snprintf.c, compat/strcasecmp.c, + compat/strerror.c, config.h.in, configure, configure.in, + include/compat.h, include/missing.h, plugins/sudoers/logging.c, + plugins/sudoers/sudoers.c, plugins/sudoers/visudo.c, src/sudo.c: + Remove some obsolete configure tests, ancient Unix systems are no + longer supported. + [2be6218c3a36] 2010-08-07 Todd C. Miller * sudo.pp: - Set pp_kit_version and strip off patchlevel - [814c87778567] <1.7> + Set pp_kit_version and strip off patch level + [aacfda1b676d] * sudo.pp: Better handling of versions with a patchlevel. For rpm and deb, use the patchlevel+1 as the release. For AIX, use the patchlevel as the 4th version number. For the rest, just leave the patchlevel in the version string. - [d18ef30f0a72] <1.7> + [638bd35f2346] 2010-08-06 Todd C. Miller - * auth/sudo_auth.c: + * plugins/sudoers/auth/sudo_auth.c: For non-standalone auth methods, stop reading the password if the user enters ^C at the prompt. - [59d2b1328d1e] <1.7> - - * configure, configure.in: - Don't print getspwuid as an auth method. - [d35cf4628d9a] <1.7> + [82c2911bb264] - * Makefile.in, auth/passwd.c, auth/secureware.c, auth/sudo_auth.c, - auth/sudo_auth.h, configure, configure.in, pwutil.c: + * configure, configure.in, plugins/sudoers/Makefile.in, + plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/secureware.c, + plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/auth/sudo_auth.h, + plugins/sudoers/pwutil.c: No need to look up shadow password unless we are doing password- style authentication. This moves the shadow password lookup to the auth functions that need it. - [10a85eebbf4c] <1.7> + [ba9e3eba2b72] - * check.c: + * plugins/sudoers/sudoers.c: + Retain final passwd/group refs until the policy close() function. + Note that this doesn't get called in all cases so putting this in a + cleanup function is probably better. + [bbe214cb4119] + + * plugins/sudoers/check.c: + Fix mismerge + [395115f89dd6] + + * plugins/sudoers/check.c: When removing/resetting the timestamp file ignore the tty ticket contents. - [8b285f601ec0] <1.7> - -2010-08-05 Todd C. Miller + [b709f5667a0b] - * sudo.c: + * plugins/sudoers/sudoers.c: delref sudo_user.pw, runas_pw and runas_gr immediately before we - exec. - [220be2de2f31] <1.7> - - * sudo.c: - Move calls to sudo_endgrent() and sudo_endpwent() to be after - set_perms(), which may do passwd or group lookups. - [883f0db94fd4] <1.7> + return. + [4d67d15dfd3b] 2010-08-04 Todd C. Miller - * check.c: - Make sure we don't try to delref NULL. - [19bc5a47db06] <1.7> - - * pwutil.c: - Add missing delref in user_in_group() - [fafb278f47a6] <1.7> - - * sudo.c: - delref the old runas group in set_runasgr() - [0a7dd113cb1f] <1.7> - - * match.c: - Repair usergr_matches() return value broken in last checkin. - [460b7b6ca2ce] <1.7> - - * check.c, get_pty.c, glob.c, ldap.c, match.c, pwutil.c, sudo.c, - sudo.h: + * plugins/sudoers/check.c, plugins/sudoers/ldap.c, + plugins/sudoers/match.c, plugins/sudoers/pwutil.c, + plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h: Reference count cached passwd and group structs. The cache holds one reference itself and another is added by sudo_getgr{gid,nam} and sudo_getpw{uid,nam}. The final ref on the runas and user passwd and group structs are persistent for now. - [e414c67e11fd] <1.7> + [e544685523c3] - * UPGRADE: - Fix typo - [0f443aa22e96] <1.7> + * doc/UPGRADE: + fix typo + [e32f2d35e6c9] 2010-08-03 Todd C. Miller - * check.c: + * plugins/sudoers/check.c: Do not produce a warning for "sudo -k" if the ticket file does not exist. - [eeaaa73d7f5b] <1.7> + [1598f6061b75] - * pwutil.c: + * plugins/sudoers/pwutil.c: Instead of caching struct passwd and struct group in the red-black tree, store a struct cache_item which includes both the key and datum. This allows us to user the actual name that was looked up as @@ -1524,1465 +2444,3443 @@ like set_perms() and the logging functions. Fixing this would require making a copy of the structs for user and runas or adding a reference count (better). - [2c1d8ec4fa5f] <1.7> + [225d4a22f60e] - * check.c, exec_pty.c, get_pty.c, logging.c, sudoreplay.c, tgetpass.c, - visudo.c: + * plugins/sudoers/Makefile.in: + Fix path to mkinstalldirs + [b4968379b12d] + + * plugins/sudoers/check.c, plugins/sudoers/logging.c, + plugins/sudoers/sudoreplay.c, plugins/sudoers/visudo.c, + src/exec_pty.c, src/get_pty.c, src/tgetpass.c: Quiet gcc warnings on glibc systems that use warn_unused_result for write(2) and others. - [5faf88695c66] <1.7> + [c99f138960e0] 2010-08-02 Todd C. Miller - * toke.c, toke.l: + * plugins/sudoers/toke.c, plugins/sudoers/toke.l: Add %option noinput - [8a5e05d6f71f] <1.7> + [72b9cd49b4f1] - * aclocal.m4, configure: - Add cross-compile defaults for remaining AC_TRY_RUN usage. - [fb88d22eabc6] <1.7> + * aclocal.m4, configure, configure.in: + Add cross-compile defaults for remaining AC_TRY_RUN usage. Also add + back getgroups() check since AC_FUNC_GETGROUPS defaults to "no" when + cross-compiling. + [e385c176d0ee] 2010-07-31 Todd C. Miller - * aclocal.m4, config.h.in, configure, configure.in, snprintf.c: + * aclocal.m4, compat/snprintf.c, config.h.in, configure, configure.in: Use AC_CHECK_MEMBER in SUDO_SOCK_SA_LEN Use AC_TYPE_LONG_LONG_INT and AC_CHECK_SIZEOF([long int]) instead of rolling our own. - [5e7cc557a46e] <1.7> - -2010-07-30 Todd C. Miller - - * .hgtags: - Added tag SUDO_1_7_4 for changeset 2920a3b9d568 - [e929004d5102] <1.7> - - * pp: - Debian: Remove dots from decoded release number AIX: looser matching - of file command output for AIX 5.1 - [2920a3b9d568] [SUDO_1_7_4] <1.7> - - * .hgtags: - Added tag SUDO_1_7_4 for changeset 0d844aa34c1d - [cf65ddcec602] <1.7> + [cf3e60d9c440] 2010-07-29 Todd C. Miller - * exec_pty.c: - exec_monitor is static - [0d844aa34c1d] <1.7> - * pp: Update to latest version - [7b8a00defbd6] <1.7> + [32f93be33961] 2010-07-28 Todd C. Miller * sudo.pp: Let pp determine pp_aix_version itself. - [c5ee7944af03] <1.7> + [7cf0245d84ed] - * INSTALL, config.h.in, configure, configure.in, mkpkg, sudo.c: + * INSTALL, config.h.in, configure, configure.in, mkpkg, + plugins/sudoers/sudoers.c: Add support for Ubuntu admin flag file and enable it when building Ubuntu packages. - [2d97501cda0c] <1.7> + [00e27cff2dfb] - * sudo.pp, sudoers: + * plugins/sudoers/sudoers, sudo.pp: Add commented out SuSE-like targetpw settings - [f4ad331ace46] <1.7> + [4605d47b7413] * configure, configure.in: - Only try to use +DAportable for non-GCC on hppa Check the value of - $pic_flag insteaf of whether the compiler is ANSI C when detecting - the HP-UX bundled C compiler. - [654da0091c16] <1.7> + Only try to use +DAportable for non-GCC on hppa + [75d0f284ccf7] * configure, configure.in: Prevent configure from adding the -g flag unless in devel mode - [e3c11f228c56] <1.7> + [b1fd3f8d45c0] 2010-07-27 Todd C. Miller * sudo.pp: Go back to sudo-flavor to match existing packages and only use an underscore for those that need it. - [1f78ecf3b990] <1.7> + [d737069d1e1c] * sudo.pp: Use sudo_$flavor instead of sudo-$flavor since that causes the least amount of trouble for the various package managers. - [7e1e07115788] <1.7> + [71f547af35fc] * mkpkg: Fix handling of the ldap flavor Remove destdir unless --debug was specified Make distclean before running configure if there is a Makefile present - [2bde3925346d] <1.7> + [6316f08de7d3] - * configure, configure.in: - Back out version change in 5baf2187a138 - [bbc3a81afbba] <1.7> + * sudo.pp: + Add back include file. + [195627bf68b8] * mkpkg: Pass extra args on to configure on HP-UX, if we don't have the HP C compiler, disable zlib to prevent gcc from finding it in /usr/local/lib. - [87201c7f1116] <1.7> + [473efa0e2bac] - * configure, configure.in, mkpkg: + * mkpkg: Use the HP ANSI C compiler on HP-UX if possible - [5baf2187a138] <1.7> + [fb249b6b175d] - * sudoreplay.c: + * plugins/sudoers/sudoreplay.c: Some getline() implementations (FreeBSD 8.0) do not ignore the length pointer when the line pointer is NULL as they should. - [8652300785ed] <1.7> + [2410a1a3543c] - * sudoreplay.c: + * plugins/sudoers/sudoreplay.c: Don't need to check for *cp being non-zero, isdigit() will do that. - [107301a99b6a] <1.7> + [7df11ea8a487] - * sudoreplay.c: + * plugins/sudoers/sudoreplay.c: Add setlocale() so the command line arguments that use floating point work in different locales. Since sudo now logs the timing data in the C locale we must Parse the seconds in the timing file manually instead of using strtod(). Furthermore, sudo 1.7.3 logged the number of seconds with the user's locale so if the decimal point is not '.' try using the locale-specific version. - [2b8ed181e37c] <1.7> + [4d385765f23b] - * exec.c: + * src/exec.c: Do I/O logging in the C locale so the floating point numbers in the timing file are not locale-dependent. - [18abbca14078] <1.7> + [5961cec044ec] - * sudoreplay.c: + * plugins/sudoers/sudoreplay.c: Use errorx() not error() for thingsthat don't set errno. - [a2e7c6793d26] <1.7> + [0fe5e692af84] 2010-07-26 Todd C. Miller - * sudo.pp: - Add Tru64 kit support - [40e2d21aa17f] <1.7> - * pp: Better support for 1.2.3 style versions in Tru64 kits - [f7133199a711] <1.7> + [997c549bb777] + + * sudo.pp: + Add Tru64 kit support + [e273a954f981] * pp: Remove apparently unnecessary use of sudo - [a667a69eeab0] <1.7> + [be8840d85125] - * Makefile.in: + * Makefile.in, plugins/sudoers/Makefile.in: Create timedir as part of install-dirs target. - [a2e394d694dd] <1.7> + [c736bc2fb14f] - * exec_pty.c: + * src/exec_pty.c: Handle ENXIO from read/write which can occur when reading/writing a - pty that has gone away. Fixes bugzilla 422 - [142f4c2efa17] <1.7> + pty that has gone away. + [fa2e8059879f] - * pwutil.c: + * plugins/sudoers/pwutil.c: sudo_pwdup() was not expanding an empty pw_shell to _PATH_BSHELL - [82e5e46bf458] <1.7> + [3a045475d5ee] * mkpkg: platform is a pp flag not a variable - [9d0ab9b9bf0c] <1.7> + [12eba39a47c1] * Makefile.in, mkpkg, sudo.pp: Add simple arg parsing for mkpkg so we can set debug, flavor or platform. - [8142ab01ccd9] <1.7> + [ada839fe252d] * pp: Make rpm backend work on AIX 5.x - [2467a79d0b4d] <1.7> + [549a76d11393] 2010-07-25 Todd C. Miller - * sudoers: + * plugins/sudoers/sudoers: Add commented out Defaults entry for log_output - [b3fe97e59ae0] <1.7> + [7e67d7588900] 2010-07-23 Todd C. Miller - * Makefile.in: + * doc/Makefile.in: + Remove sudo docdir completely + [dce8e82878ef] + + * doc/sample.sudo.conf: + Add sample sudo.conf + [aafdba3fc411] + +2010-07-22 Todd C. Miller + + * plugins/sudoers/Makefile.in: + Add PACKAGE_TARNAME for docdir + [930c92b8f8f0] + +2010-07-23 Todd C. Miller + + * src/Makefile.in: + Pass install-sh -b~ here too. + [c3f5eb446c38] + + * plugins/sample/Makefile.in, plugins/sample_group/Makefile.in, + plugins/sudoers/Makefile.in, src/Makefile.in: Install binary files with -b~ to make a backup. Fixes "text file busy" error on HP-UX during install. - [3563e3e0163a] <1.7> + [81f306f54f8c] * install-sh: "mv -f" on HP-UX doesn't unlink the destination first so add an explicit rm before moving the temporary into place. - [3994af813c88] <1.7> + [fb719a79582d] * configure, configure.in: Some more ${foo} -> $(foo) conversion for consistent Makefiles. - [c214d50c32ec] <1.7> + [0aa098770074] + + * doc/Makefile.in, plugins/sudoers/Makefile.in: + Install sudoers2ldif in the doc dir + [33ac3b53d7f5] 2010-07-22 Todd C. Miller * pathnames.h.in: Add missing include of maillock.h for Solaris - [343f04b7a581] <1.7> + [5a58883be23a] - * NEWS, TROUBLESHOOTING, UPGRADE, configure, configure.in, - sample.syslog.conf, sudoers.cat: + * NEWS, configure, configure.in, doc/TROUBLESHOOTING, doc/UPGRADE, + doc/sample.syslog.conf, doc/sudoers.cat: Change the default syslog facility from local2 to authpriv (or auth if the operating system doesn't support authpriv). - [949f39cf4a59] <1.7> + [3b70ba514f49] - * Makefile.in, configure, configure.in, sudo.pp: + * Makefile.in, sudo.pp: Install sudoers as /etc/sudoers on RPM and debian systems where the package manager will not replace a user-modified configuration file. This fixes upgrades from the vendor sudo packages. - [74c7ff01e880] <1.7> + [d886b6d60b5b] * pp: RPM: use %config(noreplace) instead of %config for volatile This results in the new file being installed with a .rpmnew suffix instead of the file being replaced and the old one renamed with a .rpmsave suffix. - [166133a4fb9e] <1.7> + [58be2119f8e8] 2010-07-21 Todd C. Miller - * boottime.c, mkstemps.c: - Include time.h for struct timeval. - [50446e0b8398] <1.7> + * compat/mkstemps.c, plugins/sudoers/boottime.c: + Include time.h for struct timeval + [ddf8b04f0276] - * exec_pty.c: + * src/exec_pty.c: The return value of strsignal() may be const and should be treated as const regardless. - [c035b17b50e3] <1.7> + [620074ae1e77] - * sudoers.cat, sudoers.man.in, sudoers.pod: + * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod: Mention that 127.0.0.1 will not match, nor will localhost unless that is the actual host name. - [e9977ec7ac4f] <1.7> - - * Makefile.in: - fix typo - [f216d653404d] <1.7> + [8b574122eb8f] - * Makefile.in, NEWS, README, UPGRADE, WHATSNEW: + * MANIFEST, NEWS, README, WHATSNEW, doc/Makefile.in, doc/UPGRADE: Rename WHATSNEW -> NEWS - [f3ce0a462ca0] <1.7> + [d1a2c8c47d89] * pp: Updated pp with latest patches - [cded68af5ba0] <1.7> + [98e16b9b8f62] - * WHATSNEW, exec.c, exec_pty.c, set_perms.c, sudo.c, sudo.h: - If pam is in use, wait until the process has finished before calling - pam_close_session(). - [fb3d7de50a05] <1.7> - - * sudoers.cat, sudoers.man.in: - regen sudoers manual - [7498a058eeb1] <1.7> + * WHATSNEW: + Sync with 1.7.4 + [65ac4dafeef7] - * UPGRADE, sudoers, sudoers.pod: + * doc/UPGRADE, doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod, + plugins/sudoers/sudoers: Add commented out line to add HOME to env_keep and add a warning to the note about the HOME change in UPGRADE. - [0f7e08f09b9f] <1.7> + [0d6a775bb6c8] 2010-07-20 Todd C. Miller - * sudoreplay.c: + * plugins/sudoers/sudoreplay.c: Add LINE_MAX define for those without it. - [6248dd44573c] <1.7> + [446d9dbe7859] - * WHATSNEW: - Mention that tty_tickets is now the default. - [4cf26eaee5ba] <1.7> - - * INSTALL, UPGRADE, config.h.in, configure, configure.in, defaults.c, - sudoers.cat, sudoers.man.in, sudoers.pod: + * INSTALL, WHATSNEW, config.h.in, configure, configure.in, + doc/UPGRADE, doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod, + plugins/sudoers/defaults.c: The tty_tickets option is now on by default. - [73dd2b82a3a9] <1.7> + [a01c48206d80] * WHATSNEW: Mention that AIX authdb support has been fixed. - [9331829dc276] <1.7> + [87bd7f4eba6a] - * aix.c: + * common/aix.c: setauthdb() only sets the "old" registry if it was set by a previous call to setauthdb(). To restore the original value, passing NULL (or an empty string) to setauthdb() is sufficient. - [d956fd763521] <1.7> + [470da190a254] 2010-07-19 Todd C. Miller - * sudoers.cat, sudoers.man.in, sudoers.pod: - Mention new handling of HOME in always_set_home and set_home - descriptions. - [a69c9bed3164] <1.7> - - * sudo.cat, sudo.man.in, sudo.pod: - fix typo - [9b90bb3e9187] <1.7> - - * UPGRADE, WHATSNEW, env.c, sudo.cat, sudo.man.in, sudo.pod: + * WHATSNEW, doc/UPGRADE, doc/sudo.cat, doc/sudo.man.in, doc/sudo.pod, + doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod, + plugins/sudoers/env.c: Reset HOME when env_reset is enabled unless it is in env_keep - [18223dfd1ac3] <1.7> + [f421f8827340] - * sudoers.cat, sudoers.man.in, sudoers.pod: + * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod: The default for set_logname has been "true" for some time now. - [9f97e4b43a4b] <1.7> - - * sudoers.cat, sudoers.man.in, sudoers.pod: - Document that MAIL it set in env_reset mode. - [dcf9ad98079e] <1.7> + [f489da5674c3] - * boottime.c: + * plugins/sudoers/boottime.c: Add missing include of time.h - [57bee414982d] <1.7> + [624d7014932f] - * defaults.c, sudo.c: - Check return value of setdefs() but don't stop setting defaults if - we hit an unknown one. - [a42cb2d6b7ed] <1.7> - - * logging.c: + * plugins/sudoers/logging.c: Fix check for dup2() return value. - [916cd7fdeba7] <1.7> + [140ea2d50d20] - * visudo.c: - Treat an unknown defaults entry as a parse error. - [1f94675835d9] <1.7> + * plugins/sudoers/env.c: + Add PYTHONUSERBASE to initial_badenv_table + [3149aae5b12c] - * env.c: - Check KEPT_MAIL not DID_MAIL when determining whether to set MAIL in - -i and env_reset mode. - [aa6657ccfe01] <1.7> + * plugins/sudoers/visudo.c: + Treat an unknown defaults entry as a parse error. + [b3ebad73efb2] - * env.c: - Add PYTHONUSERBASE to initial_badenv_table - [93058374f0d9] <1.7> + * plugins/sudoers/defaults.c, plugins/sudoers/sudoers.c: + Check return value of setdefs() but don't stop setting defaults if + we hit an unknown one. + [945e752239ab] - * WHATSNEW, aclocal.m4, config.h.in, configure, configure.in, env.c, - pathnames.h.in, sudo.cat, sudo.man.in, sudo.pod: + * WHATSNEW, aclocal.m4, config.h.in, configure, configure.in, + doc/sudo.cat, doc/sudo.man.in, doc/sudo.pod, doc/sudoers.cat, + doc/sudoers.man.in, doc/sudoers.pod, pathnames.h.in, + plugins/sudoers/env.c: If env_reset is enabled, set the MAIL environment variable based on the target user unless MAIL is explicitly preserved in sudoers. - [d903c904dcd4] <1.7> + [a1b03e2e0e96] 2010-07-17 Todd C. Miller * pp: decode debian code names - [2df0ecbc23b4] <1.7> + [8741280d9960] * WHATSNEW: fix typo - [b66a95fa1869] <1.7> + [a8a19451110b] 2010-07-16 Todd C. Miller * WHATSNEW: - Add entry about SuSE bash script fix. - [04af78fa281c] <1.7> + Merge with 1.7.4 + [9348fa7e15b8] - * sudo.c: + * src/sudo.c: Restore RLIMIT_NPROC after the uid switch if it appears that runas_setup() did not do it for us. Fixes a bash script problem on SuSE with RLIMIT_NPROC set to RLIM_INFINITY. - [bb14802d48b1] <1.7> + [786fb272e5fd] 2010-07-15 Todd C. Miller * mkpkg, pp, sudo.pp: Restore the dot removal in the os version reported by polypkg. Adapt mkpkg and sudo.pp to the change. - [83c7870130fe] <1.7> + [dcafdd53b88f] 2010-07-16 Todd C. Miller - * WHATSNEW: - Mention polypkg - [c5f6e40bbb58] <1.7> - - * README, WHATSNEW: - Update for sudo 1.7.4 - [0c688f1f8160] <1.7> - * INSTALL: document --with-pam-login - [33ca3f6308ae] <1.7> + [ea93e4c6873c] - * sudoers.cat, sudoers.man.in, sudoers.pod: + * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod: The tag is NOSETENV, not UNSETENV. From Petr Uzel. - [95f37e63ca15] <1.7> + [2ac90d8de36e] 2010-07-15 Todd C. Miller * sudo.pp: Include flavor in solaris package name - [b6d56ccf367e] <1.7> + [e605f6364c9f] * mkpkg: Older shells don't support IFS= so set explictly to space, tab, newline. - [336925525e17] <1.7> + [7773960bc8a0] * mkpkg: Use '=' not '==' in test - [98c692271cfd] <1.7> + [c99d42bc48e6] * mkpkg: Fix typo that prevented debian from matching - [af4deec35e37] <1.7> + [84421078fcb7] * mkpkg: Add missing prefix setting for debian - [d0c1941cb6ec] <1.7> - - * sudo.pp: - Use tab indents to reduce the chance of problem with <<- Uncomment - some env_keep lines for RHEL, SLES and Debian to more closely match - the vendor sudoers files. - [74ba26566cdc] <1.7> + [6466f23de4aa] * sudo.pp: - Fix indentation Fix the debian %set section, pp does not set - pp_deb_distro Uncomment %sudo line in sudoers for debian Add pam.d - to %files for debian Remove the /etc/sudo-ldap.conf symlink on + Use tab indents to reduce the chance of problem with <<- Fix the + debian %set section, pp does not set pp_deb_distro Uncomment %sudo + line in sudoers for debian Uncomment some env_keep lines for RHEL, + SLES and debian to more closely match the vendor sudoers files. + Add /etc/pam.d to %files Remove the /etc/sudo-ldap.conf symlink on debian for ldap flavor - [f15ff41b5afd] <1.7> + [c5b49feb1a0c] - * sudoers: + * plugins/sudoers/sudoers: Add commented out env_keep entries, sample Aliases and a %sudo line for debian. - [8264e4ed42dc] <1.7> + [387719e52d0f] * configure, configure.in: - Remove check for egrep; configure has its own - [27b3d85ebf4f] <1.7> + Move zlib check later on in the script to avoid a strange shell + problem on SLES11. + [1a3153bb1291] * configure.in: - Use enable_zlib instead of enableval for consistency - [4a15cfd43d3e] <1.7> + Remove check for egrep; configure has its own + [a3b9d98cb5d2] 2010-07-14 Todd C. Miller * mkpkg: Enable zlib for linux distros - [fcab91448bb0] <1.7> + [8fa51a1405a4] * mkpkg: Add ldap flavor to default build - [e35a577c8994] <1.7> + [97644f5a555f] * mkpkg, sudo.pp: Simplify rpm linux distro settings - [f30547765636] <1.7> + [b9dcf10cdf20] - * UPGRADE, aclocal.m4, configure, configure.in, sudo.cat, sudo.man.in, - sudoers.cat: + * aclocal.m4, configure, configure.in, doc/UPGRADE, doc/sudoers.cat: Move time stamp files from /var/run/sudo to /var/{db,lib,adm}/sudo. - [8c9440423d98] <1.7> + [2c549c1acde9] - * Makefile.in, mkpkg, sudo.pp: + * Makefile.in: + Fix ChangeLog creation from build dir + [3d0c7904f173] + + * plugins/sudoers/sudoers.c: + Handle getcwd() failure. + [aef7bef87394] + + * doc/Makefile.in, mkpkg, sudo.pp: Add ldap "flavor" for debian, controlled by the SUDO_FLAVOR environment variable. - [9f418defc08a] <1.7> + [be6ed611b7a8] * sudo.pp: Create sudo group on debian - [4b0cc7b8b0b5] <1.7> + [6ed6c032042e] * mkpkg, sudo.pp: Add debian 4/5/6 and use the dot when doing version matches - [d5184f0a1efc] <1.7> - - * sudoers.cat, sudoers.man.in, sudoers.pod: - Remove spurious "and"; from debian - [8b9f2a5937bc] <1.7> + [6bcb664d1f4f] * aclocal.m4, configure: Use a loop when searching for mv, sendmail and sh - [a1c7d19721a4] <1.7> + [d5e9369f8d13] - * aclocal.m4, configure, configure.in, sudoers.cat, sudoers.man.in, - sudoers.pod, visudo.cat, visudo.man.in, visudo.pod: + * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod: + Remove spurious "and"; from debian + [a21e6f7c5b99] + + * aclocal.m4, configure, configure.in, doc/sudoers.cat, + doc/sudoers.man.in, doc/sudoers.pod, doc/visudo.cat, + doc/visudo.man.in, doc/visudo.pod: Substitute the value of EDITOR into the sudoers and visudo manuals. - [f00dc9343f94] <1.7> + [cd79e587dd7f] 2010-07-13 Todd C. Miller * mkpkg, pp, sudo.pp: - Initial debian 4.0 support - [6d73c000723f] <1.7> + Initial support for debian 4.0 + [ac6707915fa8] * mkpkg: Some platforms need -fPIE instead of -fpie - [8533a29633e8] <1.7> - - * Makefile.in: - Add packaging bits to DISTFILES - [dea9f374f28b] <1.7> + [fd6be19e5bc2] - * auth/pam.c: + * plugins/sudoers/auth/pam.c: Only set PAM_RHOST for Solaris, where it is needed to avoid a bug. On Linux it causes a DNS lookup via libaudit. - [22e04d2f5f0f] <1.7> + [1e10105ade5b] + + * MANIFEST: + Update MANIFEST to match packaging changes + [ef86ee557b5b] * sudo.psf: We now use pp to generate HP-UX packages - [6c9f8ae6bc11] <1.7> - -2010-07-12 Todd C. Miller + [f7aa8da7844e] - * auth/pam.c: - Fix indentation - [e52e9e6338d5] <1.7> - - * INSTALL, Makefile.in: - isntall-man -> install-doc - [02cc8198ea7a] <1.7> + * INSTALL.binary, plugins/sudoers/Makefile.binary.in: + Remove vestiges of old binary package bits. + [afffd005452f] - * configure, configure.in, sudo.cat, sudo.man.in, sudoers.cat, - sudoers.ldap.cat, sudoers.ldap.man.in, sudoers.man.in, - sudoreplay.cat, sudoreplay.man.in, visudo.cat, visudo.man.in: - Bump version to 1.7.4 - [df6ce4ea908a] <1.7> - - * INSTALL.binary, Makefile.binary.in, Makefile.in: - Remove remaining bits of the old binary package - [8d4f82c23c22] <1.7> - - * sudo.pp: - Use http://rc.quest.com/topics/polypkg/ for packaging - [d71793085629] <1.7> + * INSTALL, Makefile.in, common/Makefile.in, compat/Makefile.in, + doc/Makefile.in, include/Makefile.in, plugins/sample/Makefile.in, + plugins/sample_group/Makefile.in, plugins/sudoers/Makefile.in, + src/Makefile.in: + install-man -> install-doc + [99b5fa05567c] - * Makefile.in, mkpkg, pp: + * Makefile.in, doc/Makefile.in, include/Makefile.in, mkpkg, + plugins/sudoers/Makefile.in, pp, src/Makefile.in, sudo.pp: Use http://rc.quest.com/topics/polypkg/ for packaging - [675e505758c5] <1.7> + [5ca8eb75b223] * install-sh: Just ignore the -c option, it is the default Add support for -d option - [2adfb3a63231] <1.7> + [a8b6b0a131e8] - * env.c, logging.c, pathnames.h.in: +2010-07-12 Todd C. Miller + + * pathnames.h.in, plugins/sudoers/env.c, plugins/sudoers/logging.c: Use _PATH_STDPATH instead of _PATH_DEFPATH - [2c22d54a1f02] <1.7> + [137fa911908e] - * Makefile.in: + * plugins/sudoers/Makefile.in, src/Makefile.in: Do not strip binaries. - [bc84682b372c] <1.7> + [20166e287176] * INSTALL, configure, configure.in: Add --insults=disabled configure option to allow people to build in insult support but have the insults disabled unless explicitly enabled in sudoers. - [6d9f40db9cca] <1.7> - -2010-07-10 Todd C. Miller + [523b8c552e90] - * env.c, sudoreplay.c: - Fix K&R compilation - [e44d3be7ab85] <1.7> + * compat/mkstemps.c: + Add prototype for gettime() + [275eee40473b] -2010-07-09 Todd C. Miller - - * auth/pam.c, config.h.in, configure, configure.in, env.c, sudo.c, - sudo.h: + * config.h.in, configure, configure.in, plugins/sudoers/auth/pam.c, + plugins/sudoers/env.c, plugins/sudoers/sudoers.c, + plugins/sudoers/sudoers.h: Add support for a sudo-i pam.d file to be used for "sudo -i". Adapted from a RedHat patch. - [2984c3831d88] <1.7> + [06d34f16520b] - * Makefile.in: - Fix installation of sudo_noexec.so - [d1f7ca8331b6] <1.7> +2010-07-09 Todd C. Miller + + * include/missing.h: + Fix mkstemps() prototype + [2421841e815b] - * Makefile.in, config.h.in, configure, configure.in, missing.h, - mkstemp.c, mkstemps.c, sudo_edit.c: + * MANIFEST, compat/Makefile.in, compat/mkstemp.c, compat/mkstemps.c, + config.h.in, configure, configure.in, include/missing.h, + src/sudo_edit.c: Use mkstemps() instead of mkstemp() in sudoedit. This allows sudoedit to preserve the file extension (if any) which may be used by the editor (like emacs) to choose the editing mode. - [46399679d9ae] <1.7> + [d33172d2c086] 2010-07-08 Todd C. Miller - * ldap.c, sudoers.ldap.cat, sudoers.ldap.man.in, sudoers.ldap.pod: + * doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in, doc/sudoers.ldap.pod, + plugins/sudoers/ldap.c: TLS_CACERT is now an alias for TLS_CACERTFILE. OpenLDAP uses TLS_CACERT, not TLS_CACERTFILE in its ldap.conf. Other LDAP client code, such as nss_ldap, uses TLS_CACERTFILE. Also document why you should avoid disabling TLS_CHECKPEER is possible. - [1d626a5cf8c0] <1.7> + [196622436212] 2010-07-07 Todd C. Miller - * toke.c, toke.l: + * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod: + Make sudo_plugin format a bit more like a man page + [048d596e32da] + + * plugins/sudoers/toke.c, plugins/sudoers/toke.l: Add suport for negated user/host/command lists in a Defaults entry. E.g. Defaults:!baduser noexec - [24f07a805dce] <1.7> + [d41112cf0342] + + * Makefile.in, common/Makefile.in, compat/Makefile.in, + doc/Makefile.in, include/Makefile.in, plugins/sample/Makefile.in, + plugins/sample_group/Makefile.in, plugins/sudoers/Makefile.in, + src/Makefile.in: + Add uninstall target + [fea66ebf136a] + + * common/Makefile.in, compat/Makefile.in: + Remove unused AR, SED and RANLIB variables + [2ff9928bfdb3] + + * Makefile.in: + Do not install sample plugins + [5443b87bd1c3] + +2010-07-06 Todd C. Miller + + * MANIFEST, aclocal.m4, compat/setenv.c, compat/unsetenv.c, configure, + configure.in, plugins/sudoers/env.c: + Now that sudoers is a dynamically loaded module we cannot override + the libc environment functions because the symbols may already have + been resolved via libc. Remove getenv/putenv/setenv/unsetenv + replacements from sudoers and add replacements for setenv/unsetenv + for systems that lack them. + [3f2b43cb8851] + + * configure, configure.in, plugins/sudoers/Makefile.in: + Link testsudoers with -ldl when needed + [f79606f9fcd7] + + * plugins/sample_group/plugin_test.c: + Remove unused time.h and add limits.h for PATH_MAX + [3f5d0074d621] + + * doc/sudoers.ldap.pod: + Fix typo. + [bc855fd57397] + +2010-07-05 Todd C. Miller + + * plugins/sample_group/plugin_test.c: + Do not depend on strlcpy/strlcat + [6e7e2b5af051] + + * plugins/sample_group/plugin_test.c: + Standalone test driver for sudoers group plugin. + [eb1235fc3b8e] + +2010-07-02 Todd C. Miller + + * plugins/sudoers/group_plugin.c, src/load_plugins.c: + Use RTLD_LAZY instead of RTLD_NOW; was using RTLD_NOW as a debugging + aid. + [2a34e616229b] + + * plugins/sample_group/sample_group.c: + Fix style nit in function declarations + [ab87c7c76bf9] + + * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod: + Document group_plugin syntax. + [ed1faf72ddcb] + + * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod: + Document the sudoers group plugin. + [f19a62dc8cfc] + + * INSTALL, MANIFEST, Makefile.in, config.h.in, configure, + configure.in, doc/LICENSE, doc/license.pod, include/sudo_plugin.h, + plugins/sample_group/Makefile.in, plugins/sample_group/getgrent.c, + plugins/sample_group/sample_group.c, plugins/sudoers/Makefile.in, + plugins/sudoers/def_data.c, plugins/sudoers/def_data.h, + plugins/sudoers/def_data.in, plugins/sudoers/group_plugin.c, + plugins/sudoers/match.c, plugins/sudoers/nonunix.h, + plugins/sudoers/set_perms.c, plugins/sudoers/sudoers.c, + plugins/sudoers/sudoers.h, plugins/sudoers/testsudoers.c, + plugins/sudoers/vasgroups.c, plugins/sudoers/visudo.c, src/sudo.c: + Replace built-in non-unix group support with a sudoers group plugin. + Include a sample plugin that can read Unix-format group files. + [8fc58ce0b1a8] + + * configure, configure.in, src/load_plugins.c: + Add a trailing slash to _PATH_SUDO_PLUGIN_DIR to simplify usage. + [5c491dddb8ef] 2010-07-01 Todd C. Miller - * sudoers.ldap.pod: - fix typo. - [d5f2922cecf2] <1.7> + * doc/sudo.cat, doc/sudo.man.in, doc/sudo.pod, doc/sudoers.cat, + doc/sudoers.man.in, doc/sudoers.pod: + Move sudoers-specific bits out of sudo(8) and into sudoers(5) + [e8a5a5830cfe] -2010-06-29 Todd C. Miller + * aclocal.m4, configure, configure.in: + Substitute @io_logdir@ for the sudoers I/O log directory. + [21a75ca7b0ab] - * .hgtags: - Added tag SUDO_1_7_3 for changeset 72fd1f510a08 - [cc8b2277e17e] <1.7> +2010-06-29 Todd C. Miller - * configure, configure.in, sudo.cat, sudo.man.in, sudoers.cat, - sudoers.ldap.cat, sudoers.ldap.man.in, sudoers.man.in, - sudoreplay.cat, sudoreplay.man.in, visudo.cat, visudo.man.in: - Sudo 1.7.3 GA - [72fd1f510a08] [SUDO_1_7_3] <1.7> + * MANIFEST, common/Makefile.in, common/aix.c, common/alloc.c, + common/atobool.c, common/fileops.c, common/fmt_string.c, + common/lbuf.c, common/term.c, compat/fnmatch.c, compat/getcwd.c, + compat/getgrouplist.c, compat/getline.c, compat/glob.c, + compat/snprintf.c, config.h.in, configure, configure.in, + include/fileops.h, plugins/sample/sample_plugin.c, + plugins/sudoers/alias.c, plugins/sudoers/auth/afs.c, + plugins/sudoers/auth/aix_auth.c, plugins/sudoers/auth/bsdauth.c, + plugins/sudoers/auth/dce.c, plugins/sudoers/auth/fwtk.c, + plugins/sudoers/auth/kerb4.c, plugins/sudoers/auth/kerb5.c, + plugins/sudoers/auth/pam.c, plugins/sudoers/auth/passwd.c, + plugins/sudoers/auth/rfc1938.c, plugins/sudoers/auth/secureware.c, + plugins/sudoers/auth/securid.c, plugins/sudoers/auth/securid5.c, + plugins/sudoers/auth/sia.c, plugins/sudoers/auth/sudo_auth.c, + plugins/sudoers/boottime.c, plugins/sudoers/check.c, + plugins/sudoers/defaults.c, plugins/sudoers/env.c, + plugins/sudoers/find_path.c, plugins/sudoers/getdate.c, + plugins/sudoers/getdate.y, plugins/sudoers/getspwuid.c, + plugins/sudoers/goodpath.c, plugins/sudoers/gram.c, + plugins/sudoers/gram.y, plugins/sudoers/interfaces.c, + plugins/sudoers/iolog.c, plugins/sudoers/ldap.c, + plugins/sudoers/logging.c, plugins/sudoers/match.c, + plugins/sudoers/parse.c, plugins/sudoers/pwutil.c, + plugins/sudoers/set_perms.c, plugins/sudoers/sudo_nss.c, + plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h, + plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c, + plugins/sudoers/toke.c, plugins/sudoers/toke.l, + plugins/sudoers/tsgetgrpw.c, plugins/sudoers/visudo.c, + src/Makefile.in, src/aix.c, src/conversation.c, src/exec.c, + src/exec_pty.c, src/get_pty.c, src/load_plugins.c, src/parse_args.c, + src/sudo.c, src/sudo.h, src/sudo_edit.c, src/tgetpass.c: + Set usrinfo for AIX Set adminstrative domain for the process when + looking up user's password or group info and when preparing for + execve(). Include strings.h even if string.h exists since they may + define different things. Fixes warnings on AIX and others. + [cf8b93e872c9] - * alias.c, alloc.c, auth/afs.c, auth/aix_auth.c, auth/bsdauth.c, - auth/dce.c, auth/fwtk.c, auth/kerb4.c, auth/kerb5.c, auth/pam.c, - auth/passwd.c, auth/rfc1938.c, auth/secureware.c, auth/securid.c, - auth/securid5.c, auth/sia.c, auth/sudo_auth.c, boottime.c, check.c, - defaults.c, env.c, exec.c, exec_pty.c, fileops.c, find_path.c, - fnmatch.c, get_pty.c, getcwd.c, getdate.c, getdate.y, getline.c, - getspwuid.c, glob.c, goodpath.c, gram.c, gram.y, interfaces.c, - iolog.c, lbuf.c, ldap.c, logging.c, match.c, parse.c, parse_args.c, - pwutil.c, set_perms.c, snprintf.c, sudo.c, sudo_edit.c, sudo_nss.c, - sudoreplay.c, term.c, testsudoers.c, tgetpass.c, toke.c, toke.l, - tsgetgrpw.c, visudo.c: - Include strings.h even if string.h exists since they may define - different things. Fixes warnings on AIX and others. - [7c6de7fb5dba] <1.7> + * Makefile.in: + Add a separate all target for AIX make which was using the entire + LHS (not just the first entry) of the first target as the implicit + target. + [a45b980a01ef] - * env.c: + * plugins/sudoers/env.c: Do not rely on env.env_len when unsetting a variable, just use the NULL terminator. - [faf088613ce5] <1.7> + [ca6eb239c829] - * env.c: + * plugins/sudoers/env.c: In unsetenv() check for NULL or empty name as per POSIX 1003.1-2008 - [47f8dfcc7a48] <1.7> - -2010-06-28 Todd C. Miller - - * sudoers.ldap.cat, sudoers.ldap.man.in, sudoers.ldap.pod: - Mention that multiple URI lines are merged into a single one. - [1dc0ac5929bf] <1.7> - - * WHATSNEW: - Document AIX fixes - [be36e8a6dddd] <1.7> - -2010-06-26 Todd C. Miller - - * env.c, sudo.c, sudo.h: - For env_init() just use environ not the envp from main(). - [d4f3e374caeb] <1.7> + [7046ba7caa4e] 2010-06-25 Todd C. Miller - * configure, configure.in, sudo.cat, sudo.man.in, sudoers.cat, - sudoers.ldap.cat, sudoers.ldap.man.in, sudoers.man.in, - sudoreplay.cat, sudoreplay.man.in, visudo.cat, visudo.man.in: - Update version to 1.7.3rc1 - [fe43fe79070d] <1.7> - - * TODO: - fqdn issue is resolved - [f35cb63eb74b] <1.7> - - * env.c: - In unsetenv(), assign ep in the for loop instead of doing it - earlier. This version of the code does not change env.envp in - between when ep is assigned and when it is used but older versions - (e.g. 1.7.2) do. - [a4cd29c862c9] <1.7> - - * aix.c: - Use S_REGISTRY instead of S_AUTHSYSTEM as the argument to - getuserattr() when fetching the administrative domain to be used by - setauthdb(). This was suggested by AIX support and is consistent - with what OpenSSH does. - [d3109706ec85] <1.7> - - * vasgroups.c: + * plugins/sudoers/vasgroups.c: Use warningx() instead of log_error() since the latter is not available to visudo or testsudoers. This does mean that they don't end up in syslog. - [0174e89f983b] <1.7> + [152b7c50f426] - * sudo.c: + * plugins/sudoers/sudoers.c: Defer call to sudo_nonunix_groupcheck_cleanup() until after we have closed the sudoers sources. From Quest sudo. - [c1b33e3e0f9e] <1.7> + [c1cd573bab94] - * pwutil.c: + * plugins/sudoers/pwutil.c: Ignore case when matching user/group names in the cache. From Quest sudo. - [72df368a8a0e] <1.7> + [2aa4ecc7d7f5] 2010-06-24 Todd C. Miller - * config.h.in, configure, configure.in, selinux.c: + * config.h.in, configure, configure.in, src/selinux.c: Add check for setkeycreatecon() when --with-selinux is specified. - [24144c52c0cc] <1.7> + [affae247b4e0] * configure, configure.in: - Bump version to 1.7.3b5 Error out if libaudit.h is missing or - ununable when --with-linux-audit was specified - [215c7653d9bc] <1.7> - - * aix.c: - K&R function declaration for aix_setauthdb() - [82da12d222a6] <1.7> - - * env.c, sudo.c, sudo.h: - If env_init() was called implicitly via getenv(), setenv() or - putenv() just use the specified envp instead of mallocing a new - copy. This prevents an infinite loop on OpenBSD which calls - getenv() from malloc() to get MALLOC_OPTIONS. - [8e82ce63f774] <1.7> - - * ldap.c: - Add support for multiple URI lines by joining the contents and - passing the result to ldap_initialize. - [b4e10b2ffdb1] <1.7> - -2010-06-23 Todd C. Miller - - * pwutil.c, set_perms.c, sudo_nss.c: - Bracket initgroups with calls to aix_setauthdb() and - aix_restoreauthdb() - [363dbe449f1c] <1.7> - - * aix.c: - Include compat.h before alloc.h to get __P - [819a2667ffd7] <1.7> - - * auth/aix_auth.c: - Include usersec.h for authenticate() prototype - [2b8dd2b67131] <1.7> + Error out if libaudit.h is missing or ununable when --with-linux- + audit was specified + [d82e743fac04] - * aix.c: - Add missing includes Add missing trailing NUL in userinfo string - [8deaedf44943] <1.7> + * doc/HISTORY, doc/history.pod: + Add =head3 entries, mostly for the html version + [ee93112d0308] 2010-06-22 Todd C. Miller - * HISTORY, history.pod: - Mention when LDAP was incorporated. - [4e6c8ec4f67c] <1.7> + * doc/HISTORY, doc/history.pod: + Mention when LDAP was incorporate. + [2923dc17f79c] 2010-06-21 Todd C. Miller - * configure: - Define _LINUX_SOURCE_COMPAT on AIX for strsignal() prototype, it is - not covered by _ALL_SOURCE. - [3657f1b181b9] <1.7> - - * pwutil.c: - Include usersec.h on AIX to get IDtouser() prototype. - [11483bbe15c7] <1.7> - - * configure.in: + * configure, configure.in: Define _LINUX_SOURCE_COMPAT on AIX for strsignal() prototype, it is not covered by _ALL_SOURCE. - [fd48e6e2136b] <1.7> + [c92fd69809d0] 2010-06-18 Todd C. Miller - * iolog.c: + * plugins/sudoers/iolog.c: Add a cast to quiet a compiler warning. - [51e9d419bd83] <1.7> + [a200e07ee1bc] - * boottime.c: - Use memset() instead of zero_bytes() since we don't include sudo.h - [f310b2123ba9] <1.7> - - * Makefile.in: - getline.o is already in LIB_OBJS, do not need it in COMMON_OBJS - [c8750c2d75ab] <1.7> - - * getdate.c, getdate.y: + * plugins/sudoers/getdate.c, plugins/sudoers/getdate.y: Quiet a compiler warning. - [9f231be15958] <1.7> + [c9acfc927cea] - * defaults.c, sudo.c: + * plugins/sudoers/defaults.c, plugins/sudoers/sudoers.c: Call set_fqdn() after sudoers has parsed instead of inline as a callback. - [26d413ddb6dd] <1.7> + [5f4e5d075f2d] - * WHATSNEW: + * WHATSNEW, plugins/sudoers/sudoers.c: Do not call set_fqdn() until sudoers parses (where is gets run as a callback). - [582453a993a1] <1.7> - - * sudo.c: - Do not call set_fqdn() until sudoers parses (where is gets run as a - callback). Otherwise, if sudo is built --with-fqdn the fqdn will be - set even if !fqdn is set in sudoers. - [aa01e867d1bb] <1.7> - - * configure, configure.in, sudo.cat, sudo.man.in, sudoers.cat, - sudoers.ldap.cat, sudoers.ldap.man.in, sudoers.man.in, - sudoreplay.cat, sudoreplay.man.in, visudo.cat, visudo.man.in: - Bump version to 1.7.3b4 - [c1c5a73766b6] <1.7> + [09040fca6d40] * WHATSNEW: mention the change in tty ticket behavior when there is no tty - [93ddde63e453] <1.7> - - * TODO: - remove done items - [9601b2e8dcef] <1.7> - - * aix.c: - Remove comment; NAME in usrinfo should be user name. - [eb46f1e8ea08] <1.7> + [575a1fd98f05] - * check.c: + * plugins/sudoers/check.c: Do not update tty ticket if there is no tty. - [e64e8c8f2286] <1.7> - - * sudo.cat, sudo.man.in, sudo.pod: - No longer need to use -- with the -s flag - [e45c18dd79dc] <1.7> + [63f9c33ce6a7] - * Makefile.in: - Add missing $(srcdir) to sudo.man.in target - [2bd89f6ca9f3] <1.7> + * doc/LICENSE, doc/license.pod: + Update copyright year + [0722ab5d404b] - * Makefile.in: + * doc/Makefile.in: Do not rely on BSD make's $> - [cb328b82cb92] <1.7> + [936a86398bd9] * configure, configure.in: Set timedir to /var/db/sudo for darwin to match Apple sudo's location - [860c7f1b001f] <1.7> + [d5b9b03096f1] 2010-06-16 Todd C. Miller - * Makefile.in, configure, configure.in: - Move aix.o from SUDO_OBJS to COMMON_OBJS - [f8a9bdf346c1] <1.7> + * plugins/sudoers/sudoers.h: + Add stub declarations for struct stat and struct timeval + [f6d90551a4fd] - * config.h.in, configure, configure.in, defaults.c, iolog.c, - sudoreplay.c: + * MANIFEST: + Remove compat/sigaction.c + [d0ed6d9a770e] + + * config.h.in, configure, configure.in, plugins/sudoers/defaults.c, + plugins/sudoers/iolog.c, plugins/sudoers/sudoreplay.c: Check for zlib.h in addition to libz. - [fb77e44d5196] <1.7> + [6e191b4a6065] - * Makefile.in, exec.c, exec_pty.c, sudo.h, sudo_exec.h: + * MANIFEST, src/Makefile.in, src/exec.c, src/exec_pty.c, src/sudo.h, + src/sudo_exec.h: Move functions and symbols shared between exec.c and exec_pty.c into sudo_exec.h. - [e798d945424e] <1.7> - - * sudo.h: - Add missing prototypes for aix_setauthdb and aix_restoreauthdb - [8bc2af6d4e17] <1.7> + [14ae63403544] - * Makefile.in: + * doc/Makefile.in: Comment out rules to build .man.in and .cat files unless --with- devel - [81d6726a19ab] <1.7> + [3cf7e5606a85] - * aix.c, pwutil.c, set_perms.c, sudo.h: - Fix AIX compilation problems. - [7d95f73eca42] <1.7> - - * sudo.c: - Cast isalnum() arg to unsigned char. - [5fff9a81af00] <1.7> - - * WHATSNEW: - Add Linux audit support. - [e59e0670ba79] <1.7> + * doc/Makefile.in: + Comment out rules to build .man.in and .cat files unless --with- + devel + [d30495b0e29e] - * sudo.c: + * src/parse_args.c: Quote any non-alphanumeric characters other than '_' or '-' when passing a command to be run via the shell for the -s and -i options. - [d35a3f4cb3c0] <1.7> + [d633f74fe2d9] - * sudo.c: - Add missing braces that broke -i mode. - [7fe124b078ec] <1.7> + * doc/Makefile.in: + Add back .man suffix + [6e63b60a2739] - * linux_audit.c: - Fix linux_audit_command() return value - [0c582476181c] <1.7> + * INSTALL, MANIFEST, WHATSNEW, config.h.in, configure, configure.in, + plugins/sudoers/Makefile.in, plugins/sudoers/audit.c, + plugins/sudoers/bsm_audit.c, plugins/sudoers/linux_audit.c, + plugins/sudoers/linux_audit.h, plugins/sudoers/logging.h, + src/selinux.c: + Add Linux audit support. + [5a2f445e0bd4] 2010-06-15 Todd C. Miller - * Makefile.in, linux_audit.c, linux_audit.h: - Add Linux audit support. - [b207dc9960de] <1.7> + * plugins/sudoers/iolog.c: + Remove an XXX + [a170cbe651d1] + + * doc/sudoreplay.cat, doc/sudoreplay.man.in, doc/sudoreplay.pod, + plugins/sudoers/sudoreplay.c: + Add -f (filter) option to sudoreplay to allow certain streams to be + replayed and others ignored. + [62e51b432ea1] + + * src/load_plugins.c, src/parse_args.c, src/sudo.c, src/sudo.h, + src/tgetpass.c: + Fix -A flag when askpass is specified in sudo.conf or if sudo + doesn't need to read a password. + [2e401e4a00e3] + + * src/exec.c, src/exec_pty.c, src/parse_args.c, src/sudo.c, + src/sudo.h, src/sudo_edit.c, src/tgetpass.c: + Clean up some XXXs + [689f0b002d3d] + + * WHATSNEW, doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in, + doc/sudoers.ldap.pod, plugins/sudoers/ldap.c: + Add support for multiple sudoers_base entries in ldap.conf. From + Joachim Henke + [e3e4a3c2bd5b] -2010-06-16 Todd C. Miller + * config.h.in, configure, configure.in, plugins/sudoers/logging.c, + src/exec_pty.c: + remove setsid check, we require a POSIX system + [cc73cb9e22c0] - * INSTALL, audit.c, bsm_audit.c, config.h.in, configure, configure.in, - logging.h, selinux.c: - Add Linux audit support. - [26ae31d7ff93] <1.7> + * plugins/sudoers/logging.c, src/exec_pty.c, src/selinux.c, + src/sudo.c, src/tgetpass.c: + Check for dup2() failure. + [5d46d66794f5] -2010-06-15 Todd C. Miller - - * sudoreplay.c, sudoreplay.cat, sudoreplay.man.in, sudoreplay.pod: - Sync sudoreplay with trunk - [65b780cccfa5] <1.7> - - * exec_pty.c: - Remove an XXX - [8304ac649241] <1.7> - - * aix.c, configure, configure.in, pwutil.c, set_perms.c, sudo.h: - Set usrinfo for AIX Set adminstrative domain for the process when - looking up user's password info and when preparing for execve(). - [52b48cbe97fd] <1.7> - - * ldap.c, parse.c: - Better prefix determination now that we can't rely on len==0 to tell - the beginning on an entry. - [32f1875d9605] <1.7> - - * WHATSNEW, ldap.c, sudoers.ldap.cat, sudoers.ldap.man.in, - sudoers.ldap.pod: - Add support for multiple sudoers_base entries in ldap.conf. From - Joachim Henke - [3c0b59fce7b4] <1.7> - - * configure, configure.in: - Remove duplicate setsid check - [7712d6d52da1] <1.7> - - * Makefile.in, config.h.in, configure, configure.in, exec_pty.c, - logging.c, missing.h, setsid.c: - Move setsid emulation into setsid.c - [f24743c9e4e9] <1.7> - - * exec_pty.c, logging.c, selinux.c, sudo.c, tgetpass.c: - Check for dup2() failure. - [b1b6ba761b61] <1.7> - - * config.h.in, configure, configure.in: - Remove dup2 check, it is not optional. - [cfbe5f3b5956] <1.7> + * config.h.in, configure, configure.in: + Remove dup2() check, it is not optional. + [5f1d56de4384] 2010-06-14 Todd C. Miller * WHATSNEW: - Add mbr_check_membership support and SELinux fixes - [af1936a7cf2f] <1.7> + sync with sudo 1.7.3 + [88e5c0bd6d59] - * Makefile.in: - Sync SRCS and DISTFILES with reality - [0971b5dcb1be] <1.7> + * INSTALL: + SunOS does not ship with an ANSI compiler + [f13c85c67069] * INSTALL: Update OS specific notes. Delete some really ancient ones and move older ones to the end of the list. - [872dd8b437a8] <1.7> + [59ce592c4c52] * README: - Bump for sudo 1.7.3 Merge some changes from trunk - [a3088c75bf22] <1.7> + Sudo can be downloaded from the web site too Mention "OS dependent + notes" section in INSTALL + [191871538984] - * selinux.c, sudo.c: + * src/exec_pty.c, src/selinux.c: Call selinux_restore_tty() as part of cleanup() so it gets called from error()/errorx() - [0197c07d4c1e] <1.7> + [bb017da6b6da] - * compat.h: - No longer use SA_NOCLDSTOP - [73ca654cd3f8] <1.7> + * MANIFEST, doc/PORTING: + Remove obsolete porting guide + [321e35591344] - * interfaces.h, match.c: + * plugins/sudoers/interfaces.h, plugins/sudoers/match.c: Move union sudo_in_addr_un into interfaces.h - [c84bda7c332a] <1.7> - - * pathnames.h.in: + [b2c8b19ee094] + + * doc/Makefile.in: + Remove useless circular dependencies + [5682181b59cf] + + * plugins/sudoers/auth/afs.c, plugins/sudoers/auth/aix_auth.c, + plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/dce.c, + plugins/sudoers/auth/fwtk.c, plugins/sudoers/auth/kerb4.c, + plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/pam.c, + plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/rfc1938.c, + plugins/sudoers/auth/secureware.c, plugins/sudoers/auth/securid.c, + plugins/sudoers/auth/securid5.c, plugins/sudoers/auth/sia.c: + Convert to ANSI C function declarations + [a4f76927d034] + + * common/alloc.c, common/fileops.c, common/gettime.c, common/list.c, + common/zero_bytes.c, compat/charclass.h, compat/closefrom.c, + compat/fnmatch.c, compat/glob.c, compat/isblank.c, compat/memrchr.c, + compat/mkstemp.c, compat/nanosleep.c, compat/snprintf.c, + compat/strcasecmp.c, compat/strerror.c, compat/strlcat.c, + compat/strlcpy.c, compat/timespec.h, compat/utime.h, + compat/utimes.c, doc/HISTORY, doc/history.pod, doc/license.pod, + include/alloc.h, include/error.h, include/lbuf.h, include/list.h, + include/missing.h, pathnames.h.in, plugins/sudoers/alias.c, + plugins/sudoers/audit.c, plugins/sudoers/auth/sudo_auth.h, + plugins/sudoers/boottime.c, plugins/sudoers/bsm_audit.c, + plugins/sudoers/bsm_audit.h, plugins/sudoers/defaults.c, + plugins/sudoers/defaults.h, plugins/sudoers/find_path.c, + plugins/sudoers/getspwuid.c, plugins/sudoers/goodpath.c, + plugins/sudoers/gram.y, plugins/sudoers/interfaces.c, + plugins/sudoers/interfaces.h, plugins/sudoers/logging.c, + plugins/sudoers/logging.h, plugins/sudoers/match.c, + plugins/sudoers/parse.h, plugins/sudoers/plugin_error.c, + plugins/sudoers/pwutil.c, plugins/sudoers/redblack.c, + plugins/sudoers/redblack.h, plugins/sudoers/sudo_nss.h, + plugins/sudoers/sudoers.h, plugins/sudoers/sudoreplay.c, + plugins/sudoers/testsudoers.c, plugins/sudoers/timestr.c, + plugins/sudoers/toke.l, plugins/sudoers/visudo.c, src/aix.c, + src/conversation.c, src/error.c, src/load_plugins.c, + src/parse_args.c, src/sesh.c, src/sudo.h, src/sudo_noexec.c, + src/sudo_plugin_int.h, src/sudo_usage.h.in, src/tgetpass.c: Update copyright year - [94871f44206b] <1.7> + [26ac7991f7d8] - * HISTORY, LICENSE, aix.c, alias.c, alloc.h, boottime.c, bsm_audit.h, - compat.h, defaults.c, defaults.h, env.c, fileops.c, find_path.c, - gettime.c, gram.y, history.pod, lbuf.h, license.pod, logging.c, - match.c, missing.h, nanosleep.c, parse.h, set_perms.c, - sudoers.ldap.cat, sudoers.ldap.man.in, sudoers.ldap.pod, - sudoreplay.c, term.c, tgetpass.c, toke.l, visudo.c, visudo.cat, - visudo.man.in, visudo.pod: - Update copyright year - [4cfb47c799b8] <1.7> + * doc/Makefile.in: + Fix commented DEVDOCS when not in devel mode. + [e0a97eaf3793] - * Makefile.in: - Remove varsub as part of clean - [61f04a21b0bb] <1.7> - - * match.c: + * plugins/sudoers/match.c: Quiet a compiler warning. - [06d8cfe916c8] <1.7> + [b2a17ebd5d38] - * getdate.c, getdate.y: + * plugins/sudoers/getdate.c, plugins/sudoers/getdate.y: Quiet a compiler warning. - [473d2b7d44a1] <1.7> + [687843bc593d] - * ldap.c, sudo.h: - Make the remaining functions in ldap.c static - [ba555565b30a] <1.7> + * plugins/sudoers/ldap.c, plugins/sudoers/sudoers.h: + Make all functions in ldap.c static + [b2111e89eeba] - * ldap.c: - Make private functions static. Diff from Joachim Henke - [1603035b1863] <1.7> - - * schema.ActiveDirectory: + * doc/schema.ActiveDirectory: Updates from Alain Roy to provide better examples for importing the schema and to fix problems caused by Windows validating attributes which have not yet been added before committing the changes. - [83f11ae00f19] <1.7> + [69f4c5ccaf89] -2010-06-12 Todd C. Miller +2010-06-11 Todd C. Miller - * Makefile.in, configure, configure.in, sudo.cat, sudoers.cat: - Generate .cat files directly from .man.in instead of .man using - default values in configure.in - [0a92b41c5ce5] <1.7> + * configure, configure.in, doc/Makefile.in, doc/sudo.cat, + doc/sudo.man.in, doc/sudo_plugin.cat, doc/sudo_plugin.man.in, + doc/sudoers.cat, doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in, + doc/sudoers.man.in, doc/sudoreplay.cat, doc/sudoreplay.man.in, + doc/visudo.cat, doc/visudo.man.in: + Leave rules to build .man.in and .cat files uncommented but only + make them part of the "all" rule in devel mode. Generate .cat files + directly from .man.in instead of .man using default values in + configure.in + [c3054a44f6a5] -2010-06-11 Todd C. Miller + * configure, configure.in: + Bump sudo version to 1.8.0b1 + [8f79c85135e1] - * configure, configure.in, sudo.c, sudo_usage.h.in: + * configure, configure.in, src/sudo.c, src/sudo_usage.h.in: Print configure args with verbose version information. - [ca4a5fcf0af8] <1.7> + [1ce690660ed2] - * visudo.c: + * TODO, plugins/sudoers/visudo.c: Remove tfd from struct sudoersfile; it is not used. Add prev pointer to struct sudoersfile. Declare list of sudoersfile using TQ_DECLARE. Use tq_append to append sudoers entries to the tail queue. - [344c631d0d43] <1.7> + [1743f9a286e4] 2010-06-10 Todd C. Miller * WHATSNEW: Describe tty timestamp improvements - [136b0f832903] <1.7> + [e214e863a313] - * toke.c, toke.l: + * plugins/sudoers/toke.c, plugins/sudoers/toke.l: A comment character may not be part of a command line argument unless it is quoted with a backslash. Fixes parsing of: testuser ALL=NOPASSWD: /usr/bin/wl #comment foo bar closes bz #441 - [2a0c82ffedde] <1.7> - - * sudo.cat, sudo.man.in, sudoers.cat, sudoers.man.in: - regen - [c9fddd23c7e1] <1.7> + [ea2e990f85ed] - * sudoers.pod: + * doc/sudoers.pod: Make this read a little bit better when passwd_timeout is 0. - [51644950823f] <1.7> + [39d362757f31] - * Makefile.in: - Use the --file argument to config.status instead of setting - CONFIG_FILES - [fc2b42c60b5d] <1.7> - - * sudo.man.pl, sudo.pod: + * doc/sudo.man.in, doc/sudo.man.pl, doc/sudo.pod: Attempt to handle a default password prompt timeout of zero more gracefully. - [478b8e720993] <1.7> + [ea47d43acf5b] - * toke.c, toke.l: + * plugins/sudoers/toke.c, plugins/sudoers/toke.l: Do not override value of keepopen global, instead restore it to the value we pushed onto the stack when popping. - [dc370d57a668] <1.7> + [fe282e5a3402] + + * plugins/sudoers/Makefile.in: + Add dependency for utility programs on libreplace and libcommon + [2339aba64928] - * exec.c, exec_pty.c, logging.c, mon_systrace.c, tgetpass.c: - Use SA_INTERRUPT in sa_flags - [3845c6637361] <1.7> + * compat/sigaction.c, config.h.in, configure.in, include/compat.h, + plugins/sudoers/logging.c, plugins/sudoers/mon_systrace.c, + src/exec.c, src/exec_pty.c, src/tgetpass.c: + Remove sigaction emulation Use SA_INTERRUPT in sa_flags + [7dd61f1bd8d2] - * getdate.c, getdate.y, ldap.c, sudoreplay.c: + * MANIFEST, config.h.in, configure, configure.in, include/missing.h: + We don't use getgrouplist() at the moment so there's no need to + provide a compat version. + [1597536fbada] + + * TODO: + sync with reality + [9e1a874e7885] + + * include/sudo_plugin.h, plugins/sudoers/auth/sudo_auth.c, + src/conversation.c, src/sudo.h, src/tgetpass.c: + Fix visiblepw sudoers option; the plugin API portion still needs + documenting + [60b6933ef5e0] + + * src/sudo.c: + Print sudo version as well. + [987ed459b459] + + * plugins/sudoers/iolog.c, plugins/sudoers/sudoers.c: + Use sudo_printf for I/O log version Clarify policy plugin version + string + [5a58b7e8c80b] + + * plugins/sudoers/getdate.c, plugins/sudoers/getdate.y, + plugins/sudoers/ldap.c, plugins/sudoers/sudoreplay.c: Silence some compiler warnings - [112ac65afd0c] <1.7> + [afb1eba90915] + + * src/load_plugins.c, src/tgetpass.c: + Store askpass path in a global instead of uses setenv() which many + systems lack. + [b440bcc0e660] 2010-06-09 Todd C. Miller - * exec.c, exec_pty.c, sudo.c, sudo.h: + * doc/sudo.cat, doc/sudo.man.in, doc/sudo.pod, doc/sudo_plugin.cat, + doc/sudo_plugin.man.in, doc/sudo_plugin.pod, + plugins/sudoers/check.c, plugins/sudoers/def_data.c, + plugins/sudoers/def_data.h, plugins/sudoers/def_data.in, + plugins/sudoers/defaults.c, plugins/sudoers/sudoers.c, + plugins/sudoers/sudoers.h, src/load_plugins.c, src/parse_args.c, + src/tgetpass.c: + Move askpass path specification from sudoers to sudo.conf. + [5507ab867c26] + + * src/exec.c, src/exec_pty.c, src/sudo.c, src/sudo.h: + Use a flag bit in struct command_details for selinux instead of a + separate field. + [c59ca4acded9] + + * src/exec.c, src/exec_pty.c, src/sudo.c, src/sudo.h: Implement background mode. If I/O logging we use pipes instead of a pty. - [8d448eaf2aaa] <1.7> + [c07a4b356cbd] - * compat.h, exec.c, exec_pty.c, mksiglist.c, strsignal.c, tgetpass.c: + * compat/mksiglist.c, compat/strsignal.c, include/compat.h, + src/exec.c, src/exec_pty.c, src/tgetpass.c: Move compat definition of NSIG to compat.h - [cae72a4c9dec] <1.7> + [ab0385467f25] - * tgetpass.c: - Ignore SIGPIPE for "sudo -S" - [c6595c8527c4] <1.7> + * doc/sudo.cat, doc/sudo.man.in, doc/sudo.pod, doc/sudo_plugin.cat, + doc/sudo_plugin.man.in, doc/sudo_plugin.pod: + Mention plugins in the sudo manual and add some missing path + substitution in the sudo_plugin manual. + [570f831f47a3] - * tgetpass.c: - Properly handle TGP_ECHO again. Print a newline if the user - interrupted password input. - [15acbe4fb535] <1.7> + * src/Makefile.in: + Set _PATH_SUDO_CONF based on $(sysconfdir) + [fde51869cf07] - * exec_pty.c: + * common/lbuf.c, common/term.c, config.h.in, configure, configure.in, + src/exec.c, src/exec_pty.c, src/ttysize.c: + Require POSIX termios to build sudo + [9ec6b41f3f95] + + * src/tgetpass.c: + Ignore SIGPIPE for "sudo -S" + [7ad27fde0c06] + + * src/tgetpass.c: + Fix uninitialized variable in TGP_ECHO case and print a newline if + the user interrupted password input. + [ce19204d8dd4] + + * src/tgetpass.c: + Make TGP_ECHO override TGP_MASK and don't try to restore the + terminal if we didn't modify it. + [a7e11abfe7e4] + + * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod, + include/sudo_plugin.h, plugins/sudoers/auth/sudo_auth.c, + src/conversation.c, src/sudo.h, src/tgetpass.c: + Add SUDO_CONV_PROMPT_MASK define which corresponds to the + "pwfeedback" sudoers option. Do not disable echo if TGP_ECHO is + set. + [e0550590cabe] + + * src/exec_pty.c: Use POSIX tcgetpgrp() instead of BSD TIOCGPGRP ioctl - [dd041fc9554c] <1.7> + [762448182fe3] 2010-06-08 Todd C. Miller - * exec.c, exec_pty.c, selinux.c, sudo.c, sudo.h: - Return an error from selinux_setup() instead of exiting. Call - selinux_setup() from exec_setup(). - [b518225cafba] <1.7> + * src/exec.c, src/exec_pty.c, src/selinux.c, src/sudo.c, src/sudo.h: + Add selinux_enabled flag into struct command_details and set it in + command_info_to_details(). Return an error from selinux_setup() + instead of exiting. Call selinux_setup() from exec_setup(). + [011bea23a5a0] - * compat.h: - Add definition of WCOREDUMP for systems without it. This is known - to work on AIX and SunOS 4, but may be incorrect on other systems - that lack WCOREDUMP. - [365e56db7cd5] <1.7> +2010-06-09 Todd C. Miller + + * src/exec_pty.c: + Remove commented out copy of old sudo_execve() function. + [9c5e21380472] + +2010-06-08 Todd C. Miller - * check.c, compat.h, config.h.in, configure, configure.in, iolog.c, - nanosleep.c, sudo_edit.c, visudo.c: + * plugins/sudoers/sudoers.c: + Fix setting selinux type on command line. + [814b20a0b3be] + + * plugins/sudoers/iolog.c: + In sudoers_io_close(), skip NULL io_fds[] elements. + [4011ff7d4daf] + + * include/compat.h: + No longer need NGROUPS_MAX define + [cae4c49d7077] + + * compat/nanosleep.c, config.h.in, configure, configure.in, + include/compat.h, plugins/sudoers/check.c, plugins/sudoers/iolog.c, + plugins/sudoers/visudo.c, src/sudo_edit.c: Replace timerfoo macros with timevalfoo since the timer macros are known to be busted on some systems. - [4bb5228606c5] <1.7> + [4f97d79f2d41] - * toke.c, toke.l: + * src/exec_pty.c: + Remove duplicate call to selinux_setup(). + [82bd52764e21] + + * plugins/sudoers/auth/pam.c: + If pam_open_session() fails, pass its status to pam_end. + [1d8de4cf8ff3] + + * plugins/sudoers/toke.c, plugins/sudoers/toke.l: If a file in a #includedir has improper permissions or owner just skip it. This prevents packages that incorrectly install a file into /etc/sudoers.d from breaking sudo so easily. Syntax errors in #includedir files still result in a parse error (for now). - [b7fb75eddb77] <1.7> + [ade99a4549a4] - * TODO, auth/pam.c, exec.c, exec_pty.c, set_perms.c, sudo.c, sudo.h: - Defer call to pam_close_session() until after the command finishes - if there is a monitor process. - [0a39c8e6a81b] <1.7> - - * WHATSNEW, def_data.c, def_data.h, def_data.in, exec.c, sudoers.cat, - sudoers.man.in, sudoers.pod: + * WHATSNEW, doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod, + plugins/sudoers/def_data.c, plugins/sudoers/def_data.h, + plugins/sudoers/def_data.in, plugins/sudoers/iolog.c: Add use_pty sudoers option to force use of a pty even when not logging I/O. - [aea971f1456a] <1.7> + [b280a8972a79] - * env.c, sudo.c, sudo.h: - Instead of trying to keep the global environment in sync with our - private copy, provide our own getenv() that returns values from the - private environment and use env_get() to pass the environment in to - run_command(). - [58c85c5695dc] <1.7> + * plugins/sudoers/env.c, plugins/sudoers/sudoers.h: + Make env_init() void as it never fails. + [d3890e55daa7] - * set_perms.c: - Fix typo - [0f677fcdde04] <1.7> + * plugins/sudoers/env.c: + No longer use _NSGetEnviron so don't need crt_externs.h + [9b4e0e139881] -2010-06-07 Todd C. Miller + * plugins/sudoers/env.c: + Remove unused VNULL define + [a42cacb263e3] - * sudo.h: - Rename pty.c -> get_pty.c - [39137dcc4420] <1.7> +2010-06-07 Todd C. Miller - * iolog.c: + * plugins/sudoers/iolog.c: Add #define for maximum session id - [2a487437f013] <1.7> + [9e18c17a28c2] - * Makefile.in, configure, configure.in, exec.c, exec_pty.c, iolog.c, - selinux.c, sudo.c, sudo.h, sudo_edit.c: - Split exec.c into exec.c and exec_pty.c Pass a flag in to - sudo_execve to indicate whether we need to wait for the command - to finish (fork + execve vs. execve). - [b197515585db] <1.7> + * MANIFEST, src/Makefile.in, src/exec.c, src/exec_pty.c, src/sudo.h: + Split exec.c into exec.c and exec_pty.c + [d52376327332] - * Makefile.in, configure, configure.in, get_pty.c, pty.c: - Rename pty.c -> get_pty.c - [c0e5270bb28a] <1.7> + * MANIFEST: + Sync with source file moves. + [4a62c6c9e846] - * aclocal.m4, configure, configure.in: - Fix --without-iologdir - [dcd6c5907b10] <1.7> + * src/Makefile.in, src/get_pty.c, src/pty.c: + Rename pty.c -> get_pty.c + [5696a12bd29b] 2010-06-06 Todd C. Miller - * iolog.c: + * plugins/sudoers/iolog.c: Only use I/O input log file if def_log_input is set and output file if def_log_output is set. - [96cdd49be996] <1.7> + [d866992f1681] -2010-06-05 Todd C. Miller +2010-06-04 Todd C. Miller - * parse_args.c, sudo.c: - Include sudo_usage.h after sudo.h now that it has function - prototypes to guarantee that __P is defined. - [c67b77f8d6b1] <1.7> + * compat/strsignal.c: + Update copyright year + [a96f2593fd4e] -2010-06-04 Todd C. Miller + * src/pty.c: + uid -> ttyuid + [c3454d74ebcb] - * tgetpass.c: - Do signal setup after turning off echo, not before. If we are using - a tty but are not the foreground pgrp this will generate SIGTTOU so - we want the default action to be taken (suspend process). Use an - array for signals received instead of a single variable so we don't - lose any when there are multiple different signals. - [de356064ea01] <1.7> + * plugins/sudoers/sudoers.c: + For sudoedit, make a local copy of editor string si become part of + argv. If no editor environment variable, split def_editor on ':' + since it may be a colon-delimited path. + [2ee298506a6e] - * defaults.h, lbuf.h, sudo.h: - Reorg function prototypes a bit - [5c40f58bb28e] <1.7> + * src/sudo_edit.c: + Remove unneeded endpwent()/endgrent() + [623f6743d101] - * Makefile.in, parse_args.c, sudo.c, sudo.h, sudo_usage.h.in: - Move argument parsing into parse_args.c - [fad7b8737c12] <1.7> + * doc/Makefile.in: + Use value of nroff from configure + [b2ce649125ab] - * Makefile.in, config.h.in, configure, configure.in, missing.h, - mksiglist.c, mksiglist.h, siglist.in, strsignal.c: - Build our own sys_siglist for systems that lack it. - [3b5f671936dc] <1.7> + * src/exec.c: + Add missing const to I/O log action function + [d764a3955e04] - * exec.c, iolog.c, missing.h, sudo_edit.c: - K&R fixes - [dad62986f2fe] <1.7> + * plugins/sudoers/check.c: + Update copyright year and fix whitespace + [e648c35b16be] - * exec.c, pty.c, sudo.c, sudo.h, sudo_edit.c: - Log sudoedit sessions as well; adapted from trunk - [2c5d9695022b] <1.7> + * configure, configure.in: + Fix typo + [8e0bdfc47da4] - * configure: - regen - [9b319e89a6c4] <1.7> - - * INSTALL, Makefile.in, WHATSNEW, aclocal.m4, configure, configure.in, - def_data.c, def_data.h, def_data.in, defaults.c, exec.c, gram.c, - gram.h, gram.y, iolog.c, parse.c, parse.h, pathnames.h.in, pty.c, - script.c, selinux.c, sudo.c, sudo.h, sudoers.cat, sudoers.man.in, - sudoers.pod, sudoreplay.c, sudoreplay.cat, sudoreplay.man.in, - sudoreplay.pod, term.c: - Merge I/O logging changes from trunk. Disabling I/O log support at - compile time does not currently work. Sudoedit is not yet hooked up - to I/O logging. - [968c2c74c69b] <1.7> + * plugins/sudoers/iolog.c: + Remove redundant tty signal blocking in log function. + [f17f575dabd4] 2010-06-03 Todd C. Miller + * plugins/sudoers/iolog.c: + Place static keyword where it belongs + [b01aec7c86b4] + + * plugins/sudoers/logging.c: + Always use a printf format string for send_mail() + [13b1ada644c9] + + * common/atobool.c, plugins/sudoers/ldap.c: + Extend atobool() so we can use it in the LDAP code. + [73f8e6807044] + + * doc/sudo.cat, doc/sudo.man.in, doc/sudo.pod: + Sudo now stashes tty ctime for tty_tickets on Solaris too. + [e82df13ad3fd] + + * plugins/sudoers/boottime.c: + Fix dummy version of get_boottime() + [01d69c06013b] + +2010-06-02 Todd C. Miller + + * plugins/sudoers/check.c: + Enable tty_is_devpts() support for Solaris with the "devices" + filesystem. + [237c6b25fa84] + + * src/exec.c: + Unbreak the non-io logging case. + [4822b9f709fb] + + * src/conversation.c, src/sudo.c, src/sudo_plugin_int.h: + Fix symbol name conflict with sudo_printf. + [0d44eab0a8f6] + + * plugins/sudoers/auth/pam.c: + Fix OpenPAM detection for newer versions. + [1b2abed232d8] + + * plugins/sudoers/vasgroups.c: + Sync with Quest sudo git repo + [f1d98b3cba02] + + * aclocal.m4, configure, configure.in: + HP-UX ld uses +b instead or -R or -rpath Fix typo in libvas check + Add missing template for ENV_DEBUG Adapted from Quest sudo + [695dbd7b28f4] + + * README.LDAP: + Fix typos; from Quest Sudo + [4eba9da33b8e] + +2010-06-01 Todd C. Miller + + * plugins/sudoers/Makefile.in: + Add back -I$(top_srcdir); we need it for including compat/foo.h + since we cannot rely on "foo.h" being found relative to the source + file when the cwd is different. + [bbf24695f325] + + * src/exec.c: + Fix a bug where we could treat EAGAIN as a permanent error. Also set + cstat if perform_io() returns an error. + [200475c4326f] + + * common/alloc.c, plugins/sudoers/boottime.c, + plugins/sudoers/sudoers.c: + Add casts to quiet compiler warnings. + [85eb1c336697] + + * plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c, + plugins/sudoers/visudo.c: + Fix typo in ternary operator usage. + [6492ac1450e2] + +2010-05-30 Todd C. Miller + * INSTALL, configure, configure.in: - Add --enable-warnings configure option - [19cf967c36d1] <1.7> + Add --enable-warnings and fix typo in SUDO_IO_LOGDIR + [92121d693b30] + + * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod, + doc/sudoreplay.cat, doc/sudoreplay.man.in, doc/sudoreplay.pod: + Update docs to match sudoers I/O logging changes + [18d651989e49] + + * INSTALL, WHATSNEW, aclocal.m4, configure, configure.in, + pathnames.h.in, plugins/sudoers/def_data.c, + plugins/sudoers/def_data.h, plugins/sudoers/def_data.in, + plugins/sudoers/defaults.c, plugins/sudoers/gram.c, + plugins/sudoers/gram.h, plugins/sudoers/gram.y, + plugins/sudoers/iolog.c, plugins/sudoers/parse.c, + plugins/sudoers/parse.h, plugins/sudoers/sudoers.c, + plugins/sudoers/sudoreplay.c: + Break sudoers transcript feature up into log_input and log_output. + [db3c1248d2ad] + + * plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c, + plugins/sudoers/visudo.c: + Use setprogname() as needed. + [6beee63a4553] + + * plugins/sudoers/iolog.c, plugins/sudoers/sudoreplay.c: + Adapt sudoreplay to iolog changes. + [581f52c05f0f] + +2010-05-29 Todd C. Miller + + * plugins/sudoers/iolog.c: + Log all input and output into separate files and store a number on + each timing file line to indicate which file the data is in. + [fb460c5273dd] + + * plugins/sudoers/iolog.c, plugins/sudoers/sudoers.c, + plugins/sudoers/sudoers.h: + Make sudoers_io functions static to iolog.c + [b2df3cc3eecb] - * check.c, lbuf.h, script.c, sudo.c, sudo_nss.c: - Fix K&R compilation issues on HP-UX. - [c01a547cdcf8] <1.7> +2010-05-28 Todd C. Miller - * lbuf.c, lbuf.h, ldap.c, parse.c, sudo.c, sudo_nss.c: - Pass in output function to lbuf_init() instead of writing to stdout. - A side effect is that the usage info can now go to stderr as it - should. Add support for embedded newlines in lbuf and use that - instead of multiple calls to lbuf_print. - [596a427ff873] <1.7> + * doc/sudo.cat, doc/sudo.man.in, doc/sudo.pod, src/parse_args.c, + src/sudo_usage.h.in: + Completely remove the -L flag from the sudo front end. + [3d220030b720] + + * plugins/sudoers/sudoreplay.c: + Fix EAGAIN handling when writing to stdout. + [4766d77cea49] + + * plugins/sudoers/sudoers.c: + Eliminate unused variables + [83bd711e79c4] + + * plugins/sudoers/sudoers.c, src/exec.c, src/sudo.c: + Re-enable cleanup functions in sudoers plugin and sudo driver for + error()/errorx(). + [43093f937dd8] + + * plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/defaults.c, + plugins/sudoers/interfaces.c, plugins/sudoers/iolog.c, + plugins/sudoers/parse.c, plugins/sudoers/sudoers.c, + plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c: + Use sudo_printf to display verbose version information. + [435cc9f8d4a2] + + * common/Makefile.in, compat/Makefile.in, plugins/sample/Makefile.in, + plugins/sudoers/Makefile.in, src/Makefile.in: + Minor Makefile cleanup: fix a typo, change the removal order in the + clean targets, and remove a superfluous include path for the sudoers + plugin. + [6e3b2d6b4437] + + * plugins/sudoers/env.c: + Handle duplicate variables in the environment. For unsetenv(), keep + looking even after remove the first instance. For sudo_putenv(), + check for and remove dupes after we replace an existing value. + [c1bbb88d0435] + +2010-05-27 Todd C. Miller + + * plugins/sudoers/Makefile.in: + Use explicit path to source file instead of $< for files that live + in devdir and top_srcdir. + [358ab7f6cc64] + + * plugins/sudoers/Makefile.in: + Add explicit rules to compile gram.c and toke.c for HP-UX Pevent + ending LIBSUDOERS_OBJS with a backslash + [481a5c96d47e] + + * plugins/sudoers/Makefile.in, src/Makefile.in: + Link libcommon before libreplace since libcommon may use functions + only present in libreplace. + [1847c496ff5b] + + * common/Makefile.in: + Move code common to sudo and the sudoers plugin to a convenience + library, libcommon. Removes the need to make links in the sudoers + plugin dir and reduces re-compilation of duplicate object files. + [4c8986352937] + + * Makefile.in, common/alloc.c, common/atobool.c, common/fileops.c, + common/fmt_string.c, common/gettime.c, common/lbuf.c, common/list.c, + common/term.c, common/zero_bytes.c, configure, configure.in, + plugins/sample/Makefile.in, plugins/sudoers/Makefile.in, + src/Makefile.in, src/alloc.c, src/atobool.c, src/fileops.c, + src/fmt_string.c, src/gettime.c, src/lbuf.c, src/list.c, src/term.c, + src/zero_bytes.c: + Move code common to sudo and the sudoers plugin to a convenience + library, libcommon. Removes the need to make links in the sudoers + plugin dir and reduces re-compilation of duplicate object files. + [1d1d98bd55b9] + + * src/exec.c, src/sudo.c, src/sudo.h: + Rename script_execve to sudo_execve and rename script_foo in exec.c + [a35ec80de96a] + + * MANIFEST, src/Makefile.in, src/exec.c, src/script.c: + rename script.c exec.c and fix up the MANIFEST file + [36bc3bff9578] + + * src/script.c, src/sudo.c, src/sudo.h: + Rename script_setup() to pty_setup() and call from script_execve() + directly. + [899b0fb2a14d] + + * configure, configure.in: + bump version to 1.8.0a2 + [0b1c1ca9d4e5] + + * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod: + Document init_session + [b5324785a406] + + * plugins/sudoers/auth/API, plugins/sudoers/auth/sudo_auth.c, + plugins/sudoers/auth/sudo_auth.h: + Clean up the sudoers auth API a bit and update the docs. + [c40fd4cb6e68] + + * include/sudo_plugin.h, plugins/sudoers/auth/pam.c, + plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/sudoers.c, + plugins/sudoers/sudoers.h, src/script.c, src/sudo.c: + Add init_session function to struct policy_plugin that gets called + before the uid/gid/etc changes. A struct passwd pointer is passed + in,which may be NULL if the user does not exist in the passwd + database.The sudoers module uses init_session to open the pam + session as needed. + [d71723320ee8] + +2010-05-26 Todd C. Miller + + * plugins/sudoers/auth/pam.c, plugins/sudoers/auth/sudo_auth.c, + plugins/sudoers/auth/sudo_auth.h, plugins/sudoers/set_perms.c, + plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h: + Add open/close session to sudo auth, only used by PAM. This allows + us to open (and close) the PAM session from sudoers. + [2665e2920d0d] + + * plugins/sudoers/Makefile.in: + Add explicit rule to build getdate.o for HP-UX make. + [7f049e989956] + + * plugins/sudoers/Makefile.in: + Back out most of change 45e406ebdea2. Create dummy .l.c and .y.c + rules as an alternate way to prevent HP-UX make (and others) from + trying to rebuild the parser in non-dev mode. + [f84badad98c5] + + * plugins/sudoers/sudoers.c: + Re-enable PATH_MAX check for command + [40d8a50da136] + + * Makefile.in: + For distclean, clean the main directory last since the subdirs need + to be able to run libtool to clean things. + [8949a9861634] + + * compat/Makefile.in: + Fix generation of mksiglist.h + [b7cdc9b36650] + + * src/script.c: + Now that we defer sending cstat until the end of script_child() we + cannot reuse cstat when reading command status from parent. + [25c882643466] - * configure, configure.in, sudo.man.pl, sudoers.man.pl: +2010-05-25 Todd C. Miller + + * configure, configure.in, doc/sudo.man.in, doc/sudo.man.pl, + doc/sudoers.cat, doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in, + doc/sudoers.man.in, doc/sudoers.man.pl, doc/sudoreplay.cat, + doc/sudoreplay.man.in, doc/visudo.cat, doc/visudo.man.in: Use numeric registers to handle conditionals instead of trying to do it all with text processing. - [31570c372e0e] <1.7> + [478079c3fd4b] - * sudoers.pod: + * doc/sudoers.pod: Document per-command SELinux settings - [bbce5acad1be] <1.7> + [13840d566805] - * sudo.pod: - timestamp -> time stamp - [d7335ce6286f] <1.7> + * plugins/sudoers/sudoers.c: + Repair "sudo -l -U username" + [10a0dcdf2ddf] - * tsgetgrpw.c: - Set close on exec flag in private versions of setpwent() and - setgrent(). - [954814bdbd56] <1.7> + * plugins/sudoers/sudoers.c: + Set selinux role and type in command details. + [8ae6d35a126d] - * logging.c: - Make send_mail() take a printf-style argument list - [0783ad585062] <1.7> + * src/script.c, src/selinux.c, src/sudo.h: + Rework SELinux support. + [83279cc94bf2] - * Makefile.binary.in, Makefile.in, aclocal.m4, acsite.m4, - config.guess, config.h.in, config.sub, configure, configure.in, - ltmain.sh, m4/libtool.m4, m4/ltoptions.m4, m4/ltsugar.m4, - m4/ltversion.m4, m4/lt~obsolete.m4: - Update to autoconf 2.65 and libtool 2.2.6b - [3544dd2f1a94] <1.7> +2010-05-24 Todd C. Miller - * boottime.c: - Don't use TRUE/FALSE which may not be defined. - [8649bf22b3b2] <1.7> + * src/script.c, src/selinux.c, src/sudo.h: + Make SELinux support compile again. Needs more work to be complete. + [3d3addebcf82] - * sudo.cat, sudo.man.in, sudo.pod: - Document new tty_ticket behavior - [0663e0390338] <1.7> + * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod, + plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h, + src/parse_args.c, src/script.c, src/selinux.c, src/sudo.c, + src/sudo.h: + Bring back closefrom settings. + [b1c6257d4bbb] + + * plugins/sudoers/iolog.c, plugins/sudoers/sudoers.c, + plugins/sudoers/sudoers.h: + If running a command or sudoedit in transcript mode, call + io_nextid() before log_allowed() so the session id is logged. + [c42f3ae40150] + + * configure, configure.in: + Use mandoc(1) if nroff(1) is not present. + [daad4bbd04af] - * find_path.c, sudo.c, sudo.h, visudo.c: + * doc/Makefile.in: + Use the --file argument to config.status instead of setting + CONFIG_FILES in the environment. + [c89411a8bf70] + + * plugins/sudoers/Makefile.in: + We cannot conditionally update gram.h or the dependency ordering + gets messed up in devel mode. + [c938953231d9] + +2010-05-21 Todd C. Miller + + * Makefile.in, compat/Makefile.in, configure, configure.in, + doc/Makefile.in, include/Makefile.in, plugins/sample/Makefile.in, + plugins/sudoers/Makefile.in, src/Makefile.in: + Substitute @SHELL@ into Makefiles + [36aa6a095335] + + * config.sub: + Fix typo + [16d294d26b58] + + * config.guess, config.sub, configure, configure.in: + Update to autoconf 2.65 + [4fa6ea8caea3] + + * Makefile.in: + Fix libtool target (space vs. tabs) + [755cf3892618] + + * config.h.in, plugins/sudoers/logging.h, plugins/sudoers/visudo.c: + Remove use of RETSIGTYPE; all modern systems have signal handlers + that return void. + [42b4e3aee668] + + * Makefile.in, aclocal.m4, acsite.m4, configure, configure.in, + ltmain.sh, m4/libtool.m4, m4/ltoptions.m4, m4/ltsugar.m4, + m4/ltversion.m4, m4/lt~obsolete.m4, plugins/sample/Makefile.in, + plugins/sudoers/Makefile.in, src/Makefile.in: + Update to libtool-2.2.6b. I haven't made any local modifications + this time, which should be OK since we install sudo_noexec.so by + hand now. + [6f79ced593bb] + + * compat/Makefile.in, plugins/sample/Makefile.in, + plugins/sudoers/Makefile.in, src/Makefile.in: + Use libtool to clean objects + [1581057d6472] + + * include/Makefile.in: + Install sudo_plugin.h as part of "make install" and make other + install targets callable from the top-level Makefile + [aaaeb027d774] + + * configure, configure.in: + regen with autoupdate to eliminate AC_TRY_LINK + [5d5541c230f5] + + * Makefile.in, compat/Makefile.in, configure, configure.in, + doc/Makefile.in, plugins/sample/Makefile.in, + plugins/sudoers/Makefile.in, src/Makefile.in: + Install sudo_plugin.h as part of "make install" and make other + install targets callable from the top-level Makefile + [b258b8401b1c] + + * plugins/sample/sample_plugin.c: + The sample plugin doesn't support being run with no args so return a + usage error in this case. + [473b3cf965be] + + * plugins/sudoers/iolog.c: + Set close on exec flag for descriptors used for I/O logging so they + are not present in the command being run. + [2c7e8708df76] + + * plugins/sudoers/tsgetgrpw.c: + Set close on exec flag in private versions of setpwent() and + setgrent(). + [64fef78cb833] + + * src/script.c: + Close the I/O pipes aftering dup2()ing them to std{in,out,err}. + Fixes extra fds being present in the command when it is part of a + pipeline. + [060451617713] + + * plugins/sudoers/sudoers.c: + Set user_tty to "unknown" if there is no tty, like sudo 1.7 does (it + is used when logging). Note that user_ttypath will still be NULL if + there is no tty. + [31b69a6ecda7] + + * src/script.c, src/sudo.h: + Cosmetic changes: add comments, remove orphaned prototype and + make a global static. + [f7851af0143e] + +2010-05-20 Todd C. Miller + + * src/script.c: + Move check for maxfd == -1 to flush_output where it belongs. + [b826a95b4491] + + * src/script.c: + Break out of select loop if all the fds we want to select on are -1. + [f5b387024238] + + * src/sudo.c: + Avoid possible malloc(0) if plugin returns an empty groups list. + [9765a8fe5ce7] + + * src/sudo.c: + Add debugging info when calling plugin close function + [95a273c7ff66] + + * src/script.c: + Avoid closing stdin/stdout/stderr when we are piping output. + [330e76423caf] + + * src/script.c: + When execve() of the command fails, it is possible to receive + SIGCHLD before we've read the error status from the pipe. Re-order + things such that we send the final status at the very end and prefer + error status over wait status. + [b0dcf825244f] + +2010-05-19 Todd C. Miller + + * plugins/sudoers/auth/sudo_auth.c: + Fix compilation for non PAM/BSD auth/AIX auth + [e382b39d2e4f] + +2010-05-18 Todd C. Miller + + * src/script.c: + Additional checks to make sure we don't close /dev/tty by mistake. + When flushing, sleep in select as long as we have buffers that need + to be written out. + [8139cbd3dd54] + + * src/script.c: + Now that we can use pipes for stdin/stdout/stderr there is no longer + a need to error out when there is no tty. We just need to make sure + we don't try to use the tty fd if it is -1. + [666621635d26] + +2010-05-17 Todd C. Miller + + * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod, + include/sudo_plugin.h, plugins/sample/sample_plugin.c, + plugins/sudoers/iolog.c, plugins/sudoers/sudoers.h, src/sudo.c: + Add argc and argv to I/O logger open function. + [0d7faa007d27] + + * doc/sudo_plugin.man.in, doc/sudo_plugin.pod, include/sudo_plugin.h, + plugins/sample/sample_plugin.c, plugins/sudoers/sudoers.c, + src/parse_args.c, src/sudo.c, src/sudo_edit.c: + Remove check_sudoedit function pointer in struct sudo_policy. + Instead, sudo will set sudoedit=true in the settings array. The + plugin should check for this and modify argv_out as appropriate in + check_policy. + [c0328e3276b8] + +2010-05-16 Todd C. Miller + + * plugins/sample/sample_plugin.c, src/sudo.c, src/sudo.h, + src/sudo_edit.c: + If plugin sets "sudoedit=true" in the command info, enable sudoedit + mode even if not invoked as sudoedit. This allows a plugin to + enable sudoedit when the user runs an editor. + [96d67b99e42e] + +2010-05-15 Todd C. Miller + + * plugins/sudoers/Makefile.in: + gram.h must not depend on gram.y if we want to avoid unnecessary + rebuilding of targets dependent on gram.h when gram.y changes. + [9db4b767fdca] + + * plugins/sample/sample_plugin.c: + Refactor common bits of check_policy and check_edit + [ac4d366a04cf] + + * plugins/sample/sample_plugin.c: + Add sudoedit support + [a1a6cc4c0cef] + +2010-05-14 Todd C. Miller + + * plugins/sudoers/Makefile.in: + Rely more on VPATH; fixes a dependency issue with the parser. + [45e406ebdea2] + + * include/compat.h: + Fix typo introduced in last commit + [3ccb0f853d11] + + * include/compat.h: + Emulate seteuid using setreuid() or setresuid() as needed. There are + still a few places that call seteuid() directly. + [36e8efa3a99d] + + * src/parse_args.c, src/sudo_edit.c: + Attempt to fix building on systems that only have setuid. + [8e9ba4083318] + + * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod: + Clarify sudoedit a tad. + [d39dfaa14ade] + +2010-05-13 Todd C. Miller + + * src/sudo_edit.c: + Fix compilation on HP-UX + [f6e47843d139] + + * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod: + Document sudoedit + [4cbf5196d993] + + * plugins/sudoers/sudoers.c, src/sudo.c, src/sudo.h, src/sudo_edit.c: + Change how we handle the sudoedit argv. We now require that there + be a "--" in argv to separate the editor and any command line + arguments from the files to be edited. + [20623d549a3c] + + * include/sudo_plugin.h, plugins/sample/sample_plugin.c, + plugins/sudoers/Makefile.in, plugins/sudoers/gettime.c, + plugins/sudoers/set_perms.c, plugins/sudoers/sudoers.c, + src/Makefile.in, src/gettime.c, src/parse_args.c, src/sudo.c, + src/sudo.h, src/sudo_edit.c: + Work in progress support for sudoedit. The actual interface used by + the plugin for sudoedit is likely to change. + [c31262a31997] + + * plugins/sudoers/find_path.c, plugins/sudoers/sudoers.c, + plugins/sudoers/sudoers.h, plugins/sudoers/visudo.c: Make find_path() a little more generic by not checking def_foo variables inside it. Instead, pass in ignore_dot as a function argument. - [16c3f27cd9b9] <1.7> + [9c23101a094d] - * check.c: - Store info from stat(2)ing the tty in the tty ticket when tty - tickets are in use. If the tty lives on a devpts (Linux) or devices - (Solaris) filesystem, stash the ctime in the tty ticket file, as it - is not updated when the tty is written to. This helps us determine - when a tty has been reused without the user authenticating again - with sudo. - [f9aec9ab9054] <1.7> - - * boottime.c, check.c, sudo.h: - get_boottime() now fills in a timeval struct - [dbd2003659c0] <1.7> + * plugins/sudoers/env.c: + Add version of getenv(3) that uses our own environ pointer. + [0e3783e63534] -2010-06-02 Todd C. Miller +2010-05-12 Todd C. Miller - * check.c, compat.h, config.h.in, configure, configure.in, fileops.c, - gettime.c, sudo.h, sudo_edit.c, visudo.c: - Use timeval directly instead of converting to timespec when dealing - with file times and time of day. - [c85bf3e41839] <1.7> + * src/script.c: + Avoid a potential race condition if SIGCHLD is received immediately + before we call select(). + [99adc5ea7f0a] - * auth/pam.c: - Fix OpenPAM detection for newer versions. - [67f29a0703d0] <1.7> + * plugins/sudoers/sudoers.c: + Call env_init() before we open the sudoers sources as those may call + our setenv() replacement. + [5f82601f5ab0] - * vasgroups.c: - Sync with Quest sudo git repo - [2680ad9762c2] <1.7> + * plugins/sudoers/env.c: + Initialize env_len in env_init() + [7ae02b3029b5] - * aclocal.m4, configure, configure.in: - HP-UX ld uses +b instead or -R or -rpath Fix typo in libvas check - libvas may need libdl for dlopen() Add missing template for - ENV_DEBUG Adapted from Quest sudo - [6c886eb9070a] <1.7> +2010-05-11 Todd C. Miller - * README.LDAP: - Fix typos; from Quest Sudo - [cf258fc69f1a] <1.7> + * doc/sudo.cat, doc/sudo.man.in, doc/sudo.pod: + Document time stamp shortcomings under SECURITY NOTES Use "time + stamp" instead of timestamp. + [2b86120815b2] - * Makefile.in, configure.in: - Use value of SHELL from configure in Makefile - [08aaf12221d6] <1.7> + * doc/Makefile.in: + Make sed substitution of mansectsu and mansectform global. + [94588632dba0] -2010-05-28 Todd C. Miller + * plugins/sudoers/check.c: + If the tty lives on a devpts filesystem, stash the ctime in the tty + ticket file, as it is not updated when the tty is written to. This + helps us determine when a tty has been reused without the user + authenticating again with sudo. + [0e62a31bceb0] - * env.c: - Handle duplicate variables in the environment. For unsetenv(), keep - looking even after remove the first instance. For sudo_putenv(), - check for and remove dupes after we replace an existing value. - [086c6397d8cd] <1.7> + * src/tgetpass.c: + Fix pasto in mulitple signal fix and use _NSIG not NSIG since that + is what our compat checks set. + [df50f0a040c9] + + * configure, configure.in: + Add check for whether sudo need to link with -ldl to get dlopen(). + This is a bit of a hack that will get reworked when libtool is + updated. + [63bdcf579533] + + * plugins/sudoers/check.c: + Fix timestamp removal with -k/-K + [6b4639fef973] + + * plugins/sudoers/Makefile.in: + audit.c is now private to the sudoers plugin + [1974f342ae0b] + + * configure, configure.in: + Link with -lpthread on HP-UX since a plugin may be linked with + -lpthread and dlopen() will fail if the shared object has a + dependency on -lpthread but the main program is not linked with it. + [d42139391263] + + * config.h.in, configure, configure.in, plugins/sudoers/set_perms.c: + Add separate test for getresuid() since HP-UX has setresuid() but no + getresuid(). + [910fe727a374] + + * doc/Makefile.in: + Remove errant backslash + [dd5464257c69] + + * src/script.c: + Fix SIGPIPE handling. Now that we use may use pipes for + stdin/stdout we need to pass any SIGPIPE we receive to the running + command. + [3f6b1991f4fd] + + * src/script.c: + Also start the command in the background if stdin is not a tty. + [d93bc33a3740] + +2010-05-10 Todd C. Miller + + * plugins/sudoers/sudoreplay.c, src/script.c, src/sudo.h, src/term.c: + No need to use pseudo-cbreak mode now that we use pipes when stdout + is not a tty. Instead, check whether stdin is a tty and if not, + delay setting the tty to raw mode until the command tries to access + it itself (and receives SIGTTIN or SIGTTOU). + [e68315cf8c6b] + + * src/tgetpass.c: + Use an array for signals received instead of a single variable so we + don't lose any when there are multiple different signals. + [2ac726dac864] + + * src/tgetpass.c: + Do signal setup after turning off echo, not before. If we are using + a tty but are not the foreground pgrp this will generate SIGTTOU so + we want the default action to be taken (suspend process). + [bebb6209c795] + +2010-05-07 Todd C. Miller + + * src/script.c: + Flush the iobufs on suspend or child exit using the same logic as + the main event loop. + [c627feee1035] + + * src/script.c: + Free memory after we are done with it. + [8db9b611b45a] + +2010-05-06 Todd C. Miller + + * doc/HISTORY: + Quest now sponsors Sudo development + [6cc490083bc7] + +2010-05-05 Todd C. Miller + + * doc/Makefile.in: + Install sudo_plugin man page. + [c253729790b2] + + * src/script.c: + Go back to reseting io_buffer offset and length (and now also the + EOF handling) in the loop we do the FD_SET, not after we drain the + buffer after write() since we don't know what order reads and writes + will occur in. + [5f38bfa8497f] + + * MANIFEST: + audit files moved to sudoers plugin directory + [b1ead182428e] + + * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod: + Document plugin_printf and new logging functions. + [fe9430b60ab5] + + * src/script.c: + Add support for logging stdin when it is not a tty. There is still a + bug where "cat | sudo cat" has problems because both cat and sudo + are trying to read from the tty. + [04c9c59fcfba] + + * include/sudo_plugin.h, plugins/sample/sample_plugin.c, + plugins/sudoers/sudoers.c, src/script.c: + Add separate I/O logging functions for tty in/out and + stdin/stdout/stderr. NOTE: stdin logging does not currently work and + is disabled for now. + [a36dfd4ca935] + +2010-05-04 Todd C. Miller + + * include/sudo_plugin.h, plugins/sample/sample_plugin.c, + plugins/sudoers/iolog.c, plugins/sudoers/ldap.c, + plugins/sudoers/logging.c, plugins/sudoers/plugin_error.c, + plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h, + src/conversation.c, src/sudo.c, src/sudo_plugin_int.h: + Add pointer to a printf like function to plugin open functon. This + can be used instead of the conversation function to display info and + error messages. + [98734eea8ef1] + + * Makefile.in: + Stop if make in a subdir fails + [228bb3ad2dbc] + + * src/script.c: + Only set user's tty to blocking mode when doing the final flush. + Flush pipes as well as pty master when the process is done. + [20ff67218666] + +2010-05-03 Todd C. Miller + + * plugins/sudoers/ldap.c: + Use print_error() when displaying ldap config info in debugging + mode. + [d142e0cacb22] + + * compat/Makefile.in, compat/strdup.c, compat/strndup.c: + No longer need strdup() or strndup() replacements. + [df53697174ec] + + * plugins/sudoers/logging.c, plugins/sudoers/plugin_error.c, + plugins/sudoers/sudoers.h: + Add print_error() function that uses the conversation function to + print a variable number of error strings and use it in log_error(). + [b1fa2861b575] + + * src/script.c, src/sudo.h, src/term.c: + Do not need the opost flag to term_copy() now that we use pipes for + stdout/stderr when they are not a tty. + [f42811f70a19] + + * src/script.c: + Use pipes to the sudo process if stdout or stderr is not a tty. + Still needs some polishing and a decision as to whether it is + desirable to add additonal entry points for logging + stdout/stderr/stdin when they are not ttys. That would allow a + replay program to keep things separate and to know whether the + terminal needs to be in raw mode at replay time. + [1a945e0ab2da] + +2010-04-30 Todd C. Miller + + * plugins/sudoers/Makefile.in, plugins/sudoers/audit.c, + plugins/sudoers/bsm_audit.c, plugins/sudoers/bsm_audit.h, + src/audit.c, src/bsm_audit.c, src/bsm_audit.h: + Move audit sources into the sudoers plugin dir; the driver does not + use them. + [50ec36422cd0] + + * compat/getline.c, compat/mksiglist.c, compat/nanosleep.c, + compat/strdup.c, compat/strndup.c, plugins/sample/sample_plugin.c, + plugins/sudoers/boottime.c, plugins/sudoers/getdate.c, + plugins/sudoers/match.c, plugins/sudoers/sudoreplay.c, + plugins/sudoers/timestr.c, plugins/sudoers/vasgroups.c, src/alloc.c, + src/atobool.c, src/audit.c, src/lbuf.c, src/list.c, src/sesh.c, + src/term.c, src/ttysize.c: + Use angle brackets when including headers that can only be found + when an -I flag is specified. The files in the compat dir could get + away with double quotes here but I've converted all the source files + to use angle brackets for consistency. + [9e30a8fc6d4b] + + * plugins/sudoers/Makefile.in: + Add missing -I$(top_srcdir) to CPPFLAGS so includes in the compat + dir can be found when building outside the source tree. + [1150934b79dd] + + * plugins/sudoers/Makefile.in: + Clean up links in distclean + [78595028be8b] + + * plugins/sudoers/Makefile.in: + Hack around VPATH semantic differences by symlinking files we need + from ../../src into the current directory and build those. A better + fix would be to either make a .a or .la file with those files in it + or simply use a single, flat, Makefile instead of per-subdirs + Makefiles. + [892c332d3f05] + + * plugins/sudoers/Makefile.in, src/Makefile.in, src/fmt_string.c: + fmt_string is used by the sudoers plugin too so do not include + sudo.h (which is not really needed here anyway) + [231c35e3941f] + + * compat/Makefile.in, plugins/sample/Makefile.in, + plugins/sudoers/Makefile.in, src/Makefile.in: + Fix building with non-BSD versions of make such as GNU make. + Requires VPATH support, which should be in any non-neolithic make. + [dc174f135919] + + * configure, configure.in, plugins/sudoers/Makefile.in, + plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/sudoers.c, + src/Makefile.in: + Re-enable bsm audit. Currently auditing is done within the sudoers + plugin itself. If possible, this should really be done in the main + driver but we don't presently have the needed data to do that. This + will be re-evaluated when Linux audit support is added. + [1d05a3236bfe] + + * compat/Makefile.in, plugins/sample/Makefile.in, + plugins/sudoers/Makefile.in, src/Makefile.in: + Remove extraneous $srcdir and use more .c.lo and .c.o rules instead + of explicit rules in the dependency. + [88f80efd25f0] + + * plugins/sudoers/visudo.c: + Fix mismerge; alias_remove_recursive() now returns int + [6257a4849641] 2010-04-29 Todd C. Miller - * visudo.c: + * plugins/sudoers/visudo.c: Fix a crash when checking a sudoers file that has aliases that reference themselves. Based on a diff from David Wood. - [5efc702a3b35] <1.7> + [545d194484a7] + + * src/script.c: + Print signal info after restoring the tty mode, not before. + [a68618e67435] + + * src/script.c: + Defer call to alarm() until after we fork the child. Pass correct + pid to terminate_child() If the command exits due to signal, set + alive to false like we do when it exits normally. Add missing + check for errpipe[0] != -1 before using it in FD_ISSET + [22f0a1549391] + +2010-04-28 Todd C. Miller + + * plugins/sudoers/boottime.c: + Use 1/0 instead of TRUE/FALSE so we don't need sudoers.h + [0e627170c6e8] + +2010-04-27 Todd C. Miller + + * src/Makefile.in: + Simplify dependencies by using .c.o and .c.lo rules. + [6abcaef5d1ac] + + * configure, configure.in, plugins/sudoers/Makefile.in, + src/Makefile.in: + Substitute in @PROGS@ into src/Makefile to add sesh + [cc46d3b6208f] + +2010-04-26 Todd C. Miller + + * plugins/sudoers/sudoers.c: + Add back calls to log_denial() if sudoers does not allow the + command. + [9783316207f0] + + * plugins/sudoers/sudoers.c: + Pass in correct pwflag for list and validate. + [973dd56d4b81] + + * plugins/sudoers/env.c: + Add missing check for NULL in validate_env_vars + [1d6eb6957824] + + * src/Makefile.in: + Add sudo_noexec.la to "all" target, otherwise it only gets built at + install time. + [644a9694d2ef] + + * plugins/sudoers/sudoers.c: + Only set sudo_user.env_vars if the env_add list is empty. + [fccdf6f0e0e2] + + * plugins/sudoers/sudoers.c: + Set sudo_user.env_vars so that environment variables specified on + the command line get logged correctly. + [9b51012c491e] + + * plugins/sudoers/env.c, plugins/sudoers/logging.c, + plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h: + Re-enable environment files and setting environment variables on the + command line. + [5662d5645dbd] + +2010-04-24 Todd C. Miller + + * plugins/sudoers/check.c: + Fix typo in last commit (ifndef vs ifdef) Make sure we pass ctime() + a pointer to time_t as tv_sec in struct timeval may be long. + [4de0c46e788e] + + * plugins/sudoers/check.c: + Don't stash ctime in on-disk tty ticket info for now; on many + (most?) systems the ctime is updated when the tty is written to. + Once I have a better idea of what systems do not update ctime on + ttys (and have a way to test for this) the ctime stash will be + conditionally re-enabled. + [a90eeec0f648] + +2010-04-23 Todd C. Miller + + * MANIFEST, Makefile.in: + Add back "dist" target, this time using a MANIFEST file + [29277c05499f] + + * Makefile.in: + Remove Makefile in distclean target + [83d695f4f450] + + * Makefile.in, src/Makefile.in: + Update clean and cleandir targets + [ad7b2afeb9c1] + + * include/fileops.h, plugins/sudoers/sudoers.h, src/fileops.c, + src/sudo.h: + Move fileops.c defines and prototypes to filesops.h + [4545e9b6892d] + + * plugins/sudoers/check.c: + Lock the tty timestamp when writing. We shouldn't have to lock when + reading since the file is updated via a single write system call. + [0c7276f02696] + +2010-04-22 Todd C. Miller + + * plugins/sudoers/alias.c, plugins/sudoers/check.c, + plugins/sudoers/defaults.c, plugins/sudoers/find_path.c, + plugins/sudoers/getspwuid.c, plugins/sudoers/gettime.c, + plugins/sudoers/goodpath.c, plugins/sudoers/interfaces.c, + plugins/sudoers/iolog.c, plugins/sudoers/ldap.c, + plugins/sudoers/logging.c, plugins/sudoers/match.c, + plugins/sudoers/nonunix.h, plugins/sudoers/parse.c, + plugins/sudoers/pwutil.c, plugins/sudoers/redblack.c, + plugins/sudoers/sudo_nss.c, plugins/sudoers/sudoers.c, + plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c, + plugins/sudoers/timestr.c, plugins/sudoers/tsgetgrpw.c, + plugins/sudoers/vasgroups.c, plugins/sudoers/visudo.c: + Convert to ANSI C function declarations + [9c45def57cf7] + + * plugins/sudoers/sudoers.h: + Remove extraneous bits and classify by source file. + [e8ea9f109ebb] + + * include/compat.h: + Add timercmp macro for systems without it + [d3bf87b1d08e] + + * plugins/sudoers/boottime.c, plugins/sudoers/check.c, + plugins/sudoers/sudoers.h: + get_boottime() now fills in a timeval struct + [3573c3f44e11] + + * plugins/sudoers/check.c: + Store info from stat(2)ing the tty in the tty ticket when tty + tickets are in use. On most systems, this closes the loophole + whereby a user can log out of a tty, log back in and still have the + timestamp be valid. + [53380f9f5242] + + * config.h.in, configure.in: + Add timespec2timeval and use it when getting ctime/mtime + [4cb7f7caec2c] + +2010-04-20 Todd C. Miller + + * plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/set_perms.c, + plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h, + plugins/sudoers/testsudoers.c: + Convert perm setting to push/pop model; still needs some work Use + the stashed runas groups instead of using getgrouplist() Reset perms + to the initial value on error + [09c072ebde8b] + + * config.h.in, configure.in: + fix ctim_get and mtim_get macros + [58773dc1e360] + + * config.h.in, configure, configure.in, include/compat.h, + plugins/sudoers/check.c, plugins/sudoers/gettime.c, + plugins/sudoers/sudoers.h, plugins/sudoers/visudo.c, src/fileops.c: + Use timeval directly instead of converting to timespec when dealing + with file times and time of day. + [a0ce1ae00a67] + + * plugins/sudoers/Makefile.in: + Don't like sudoreplay with libsudoers.la due to a yacc symbol + conflict. + [f1a59cc63a15] + +2010-04-18 Todd C. Miller + + * configure, configure.in: + Darwin >= 9.x has real setreuid(2) + [7ec942a64275] + +2010-04-17 Todd C. Miller + + * plugins/sudoers/env.c, plugins/sudoers/sudoers.h: + Ansify env.c + [f58551bad10a] + + * plugins/sudoers/env.c, plugins/sudoers/sudoers.c, + plugins/sudoers/sudoers.h: + Remove remaining references to the environ pointer. + [96faa530816a] + +2010-04-16 Todd C. Miller + + * config.h.in, configure, configure.in, plugins/sudoers/env.c: + Don't change the environ directly in the sudoers plugin + [6db48ed3f7e0] 2010-04-15 Todd C. Miller - * alias.c: + * plugins/sudoers/sudoers.c: + Fix typo + [4aa452b07f8f] + + * plugins/sudoers/alias.c: Fix use after free in error message when a duplicate alias exists. - [9eaac49bd22b] <1.7> + [ce1d2812ee34] 2010-04-14 Todd C. Miller - * visudo.c: + * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod, + src/parse_args.c: + Add a "noninteractive" boolean to the settings passed in to the + plugin's open function that is set when the user specifies the -n + flag. + [68f8d9d6d4d0] + + * config.h.in, configure, configure.in, plugins/sudoers/env.c: + Add workaround for the lack of the environ pointer on Mac OS X in + dlopen()ed modules. Use of environ in the sudoers plugin should + ultimately be removed but this will do for the moment. + [80c61647434f] + + * plugins/sudoers/visudo.c: Set errorfile to the sudoers path if we set parse_error manually. This prevents a NULL dereference in printf() when checking a sudoers file in strict mode when alias errors are present. - [b4eed2f0615d] <1.7> + [45e249ca99f7] + + * plugins/sudoers/sudoers.c: + Main sudo no longer print "unable to execute" on exec failure so do + it here. + [50aaf62b43b5] + +2010-04-13 Todd C. Miller + + * src/script.c: + Use a pipe to pass back errno to the parent if execve() fails. If we + get an error in script_child(), kill the command and exit. + [dc3bf870f91b] + + * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod, + src/parse_args.c, src/sudo.c: + Handle plugin's open function returning -2 (usage error). + [aadf900c1de8] + + * src/script.c: + If execve() fails, leave it to the plugin to print an error string. + [e25748f2d5b9] + + * src/script.c: + If execve fails in logging mode, pass the errno directly to the + grandparent on the backchannel and exit. The immediate parent will + get SIGCHLD and try to report that status but its parent will no + longer be listening. It would probably be cleaner to pass this over + a pipe in script_child(). + [cb122acc81a8] + + * plugins/sudoers/sudoers.c: + Don't override rval with results of check_user() unless it failed. + [46fb7e87ac7d] 2010-04-12 Todd C. Miller - * TODO, sudoers.cat, sudoers.man.in, sudoers.pod: + * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod: Fix typo - [57198cae9cf5] <1.7> + [ccd0b693f3da] + + * src/parse_args.c: + NULL-terminate env_add + [2c534368a0c3] + +2010-04-11 Todd C. Miller + + * src/sudo.c: + Call the I/O log open function before the I/O version function. + [e88bf898990b] + + * plugins/sudoers/iolog.c: + Remove io_conv and just use sudo_conv + [a280052468eb] + + * plugins/sudoers/set_perms.c: + Fix set/restore perms for systems w/o setresuid + [4160517f6666] + +2010-04-10 Todd C. Miller + + * plugins/sudoers/check.c, plugins/sudoers/logging.c, + plugins/sudoers/parse.c, plugins/sudoers/set_perms.c, + plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h: + Primitive set/restore permissions. Will be replaced by a push/pop + model. + [aae102290866] + + * src/script.c: + Only need to take action on SIGCHLD in parent if no I/O logger. If + there is an I/O logger we will receive ECONNRESET or EPIPE when we + try to read from the socketpair. + [e1e4560401f6] 2010-04-09 Todd C. Miller - * find_path.c: - Qualify the command even if it is in the current working directory, - e.g. "./foo" instead of just returning "foo". This removes an - ambiguity between real commands and possible pseudo-commands in - command matching. - [fb4d571495fa] <1.7> + * compat/memrchr.c, doc/sudoers.cat, doc/sudoers.man.in, + doc/sudoers.pod, plugins/sudoers/find_path.c: + Merge fb4d571495fa from the 1.7 branch to trunk. + [c8fb424ad4d2] + +2010-04-08 Todd C. Miller + + * src/script.c: + Don't set SA_RESTART when registering SIGALRM handler. Do set + SA_RESTART when registering SIGWINCH handler. + [173472b76525] + + * doc/Makefile.in: + Add dev targets for *.man.in and *.cat that don't specfify the + $(srcdir) prefix. + [b62f425da2e4] + + * src/script.c: + If log_input or log_output returns false, terminate the command. + [074f4c0c34a0] + + * src/script.c: + Better signal handling. Instead of using a single variable to store + the received signal, use an array so we can't lose a signal when + multiple are sent. Fix process termination by SIGALRM in non-I/O + logger mode. Fix relaying terminal signals to the child in non-I/O + logger mode. + [7a4723aca99d] + + * src/script.c: + Fix a race between when we get the child pid in the parent and when + the child process exits. The problem exhibited as a hang after a + short-lived process, e.g. "sudo id" when no IO logger was enabled. + [80bcc0aca70b] 2010-04-07 Todd C. Miller - * sudoers.cat, sudoers.man.in, sudoers.pod: + * doc/sudoers.cat, doc/sudoers.man.in, doc/sudoers.pod: Add a note about the security implications of the fast_glob option. - [84f8097553d9] <1.7> + [c37a92ab7c93] - * memrchr.c: - Remove duplicate includes - [3e8d90f4c30f] <1.7> +2010-04-06 Todd C. Miller + + * config.h.in, configure, configure.in: + Fix up some AC_DEFINE descriptions and regen config.h.in + [f4655adc0db3] + +2010-04-05 Todd C. Miller + + * include/missing.h: + No longer check for strdup or strndup for LIBOBJ replacement. + [fdc764ee8109] + + * src/script.c: + Avoid installing signal handlers that are io-logger specific. Fixes + job control when no io logger is enabled. + [0853dd0906d4] + + * doc/Makefile.in: + Only regen man pages from pod when configured with --with-devel + [ab1995f8103d] + +2010-04-04 Todd C. Miller + + * Makefile, Makefile.in, configure, configure.in: + Top-level Makefile.in. Nothing is currently substituted but this is + needed for separate build dirs. + [e80873cbd201] + + * compat/Makefile.in, doc/Makefile.in, plugins/sample/Makefile.in, + plugins/sudoers/Makefile.in, src/Makefile.in: + Fix out-of-tree builds + [59a35bef07b8] + + * Merge + [386b848047e9] + + * doc/Makefile.in: + We always install sudoreplay in 1.8 + [ce52ba6617c9] + +2010-04-03 Todd C. Miller + + * compat/siglist.in: + SIGPOLL is sometimes the same as SIGIO (like on HP-UX) + [6d69e1b05faf] + +2010-04-02 Todd C. Miller + + * configure, configure.in: + No need to provide strdup() or strndup(), sudo uses estrdup() and + estrndup() + [57ec23b72958] + +2010-04-04 Todd C. Miller + + * plugins/sudoers/iolog.c, plugins/sudoers/sudoers.c: + Free str after using it in the version method. Use sudo_conv, not + io_conv since we don't have the IO conversation function pointer in + the I/O version method anymore now that io_open is delayed. + [f2ed132adeb0] + +2010-04-02 Todd C. Miller + + * compat/Makefile.in, compat/mksiglist.c, compat/mksiglist.h, + compat/siglist.in: + Add license to mksiglist.c and note that the bits from pdksh are + public domain + [d8121a2467e8] + + * compat/Makefile.in: + Fix LIBOBJDIR vs. srcdir wrt the siglist bits + [164160148421] + + * plugins/sudoers/Makefile.in: + Add sudoreplay testsudoers and visudo to clean target + [138a17e51c0c] + + * compat/Makefile.in, compat/mksiglist.c, compat/mksiglist.h, + compat/siglist.in, compat/strsignal.c, configure, configure.in, + include/missing.h, src/script.c: + Create our own sys_siglist for systems without it for use by + strsignal() + [2e5da011ebc3] + + * compat/Makefile.in: + Remove duplicate $(LIBOBJDIR) + [adf9abc9432f] + +2010-04-01 Todd C. Miller + + * plugins/sudoers/sudoers.c, src/sudo.c, src/sudo_edit.c: + Main sudo should not block signals; the plugin should do this in + check_policy. + [3f3736a7c5ed] + +2010-03-31 Todd C. Miller + + * src/script.c: + Fix a sizeof(ptr) vs. sizeof(*ptr) + [aa1bcf5afcce] + + * src/script.c: + Unlike most operating systems, HP-UX select() is not interrupted by + SIGCHLD when the signal is registered with SA_RESTART. If we clear + SA_RESTART when calling sigaction() for SIGCHLD we get the expected + behavior and the code in the select() loops already handles EINTR + correctly. + [9eba0115e35a] + + * compat/getprogname.c: + progname should be const + [130228f062b7] + + * plugins/sudoers/Makefile.in: + Move --tag=disable-static to when we link sudoers.la, not when we + install. + [ceb5e6c3b78b] + + * src/load_plugins.c: + Load the sudoers I/O plugin by default too now that it is hooked up. + [ea38befd0742] + +2010-03-30 Todd C. Miller + + * src/pty.c: + It looks like AIX doesn't need to push STREAMS modules for ptys. + [22da618ba0a1] + +2010-03-28 Todd C. Miller + + * src/parse_args.c, src/sudo.c: + Delay calling the I/O plugin open function until the policy plugin + returns success. + [f3297c325b48] + +2010-03-27 Todd C. Miller + + * plugins/sudoers/Makefile.in, plugins/sudoers/iolog.c, + plugins/sudoers/set_perms.c, plugins/sudoers/sudoers.c, + plugins/sudoers/sudoers.h: + Add back io logging (transcript) support. Currently, the open + function runs too early and it is not possible to use the io module + independently of the policy module. + [9bd932f66226] + + * plugins/sudoers/set_perms.c: + Comment out dead code; will be removed when set_perms is rewritten. + [af7a995284f8] + +2010-03-23 Todd C. Miller + + * plugins/sudoers/sudoers.c: + Fix off by one error when allocating user_groups. + [6281fcf9c3bb] 2010-03-22 Todd C. Miller + * configure, configure.in, plugins/sudoers/Makefile.in: + Add REPLAY_LIBS for sudoreplay and add -lrt to it on Solaris. + [fbce3e9eda3a] + + * plugins/sudoers/sudoers.c: + Fix typo in preserve groups case + [1fd72024fb5a] + + * plugins/sudoers/sudoers.c: + In command_info it is "runas_groups" not "groups". + [5c64dce4f285] + + * src/sudo.c: + Fix iteration over runas_groups list. + [b3c45a0cd643] + + * configure, configure.in, plugins/sudoers/env.c, + plugins/sudoers/match.c, src/script.c: + Merge 5177a284b9ff 549f8f7c2463 88f3181692fe from 1.7 branch. + [a8108a0776c2] + + * compat/getgrouplist.c: + getgrouplist(3) for those without it + [4ab4d21e3b16] + + * plugins/sudoers/sudoers.c: + Set preserve_groups or groups list in command_info + [1266119ad654] + + * src/sudo.c: + Fix setting of groups list + [e75315e40bd4] + + * config.h.in, configure, configure.in, include/compat.h, + include/missing.h: + Add checks for getgrset and getgrouplist and use replacement + getgrouplist if the system doesn't support it. + [a62b8ba50863] + + * src/parse_args.c: + Pass in preserve_groups when the -P flag is specified as per the + design + [7420c5d15474] + + * plugins/sudoers/sudoers.c: + Check preserve_groups and ignore_ticket args with atobool instead of + assuming they are true if present. + [71c905702697] + +2010-03-21 Todd C. Miller + + * plugins/sudoers/Makefile.in, plugins/sudoers/error.c, + plugins/sudoers/plugin_error.c: + Rename plugin-specific error.c to plugin_error.c Wire up visudo, + sudoreplay and testsudoers in the build + [9d581d5fa4d4] + + * src/Makefile.in, src/term.c: + term.c does not needto include sudo.h + [f6683cdcd2dd] + + * TODO, doc/sudo_plugin.cat, doc/sudo_plugin.man.in, + doc/sudo_plugin.pod: + Document the -2 return in the check_policy section too + [e9cb4c34bbcf] + + * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod, + plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h, + src/parse_args.c, src/sudo.c, src/sudo.h: + Fix the -s and -i flags and add support for the "implied_shell" + option. If the user does not specify a command, sudo will now pass + in the path to the user's shell and set impied_shell=true. The + plugin can them either check the command normally or return -2 to + cause sudo to print a usage message and exit. + [bf889c38f229] + +2010-03-19 Todd C. Miller + + * config.h.in, configure, configure.in, src/load_plugins.c: + Bring back SUDOERS_PLUGIN but add .dylib -> .so conversion for + Darwin where libraries end in .dylib but modules end in .so + [2c56aaa38e21] + + * plugins/sudoers/parse.c: + Better prefix determination now that we can't rely on len==0 to tell + the beginning on an entry. + [622bf18179e9] + + * plugins/sudoers/ldap.c: + display_bound_defaults() stub should return 0, not 1 since it is a + count, not a boolean. + [0327a6c3d55d] + + * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod: + Document progname in settings + [42031d56a2e3] + + * compat/getprogname.c, include/compat.h, + plugins/sample/sample_plugin.c, plugins/sudoers/sudoers.c, + src/parse_args.c, src/sudo.c: + Rewrite compat/getprogname.c and add setprogname(). The progname is + now passed to the plugin via the settings array. + [25d8663e6006] + + * configure, configure.in, plugins/sudoers/Makefile.in: + Fix --with-ldap + [b64b633f426d] + + * plugins/sudoers/sudo_nss.c: + Add missing whitespace for Runas and Command-specific defaults + [65f4ddf5545e] + + * plugins/sudoers/ldap.c, plugins/sudoers/parse.c, + plugins/sudoers/sudo_nss.c: + Use embedded newlines in lbuf instead of multiple calls to + lbuf_print. + [eed3af9cc3e1] + + * src/lbuf.c: + Add support for embedded newlines. + [e11f79b18deb] + +2010-03-18 Todd C. Miller + + * compat/getprogname.c: + If system doesn't support getprogname or __programe and we are + building a shared object don't bother with Argc/Argv, just return + "sudo" + [aebde9062be7] + + * config.h.in, configure, configure.in, src/load_plugins.c: + Hard-code sudoers.so instead of using SUDOERS_PLUGIN since libtool + appears to always install a shared object with the .so suffix. + [f9bbd0c0e9d3] + + * compat/Makefile.in, configure, configure.in, + plugins/sample/Makefile.in, plugins/sudoers/Makefile.in, + src/Makefile.in: + Play more nicely with libtool and let it build libreplace (was + libmissing) for us. + [a4c6ebb2495c] + + * include/missing.h: + Include stdarg.h for va_list rather than requiring all consumers of + missing.h to include stdarg.h themselves. + [37382df948de] + + * include/lbuf.h, plugins/sudoers/auth/sudo_auth.c, + plugins/sudoers/check.c, plugins/sudoers/sudo_nss.c, + plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h, src/lbuf.c, + src/parse_args.c: + Pass in output function to lbuf_init() instead of writing to stdout. + A side effect is that the usage info can now go to stderr as it + should. + [6d261261a072] + +2010-03-17 Todd C. Miller + + * include/lbuf.h, plugins/sudoers/sudo_nss.c, + plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h, src/lbuf.c, + src/parse_args.c, src/sudo.c: + Use number of tty columns that is passed in user_info instead of + getting it directly in the lbuf code. + [8a16635c2638] + + * plugins/sudoers/alias.c, plugins/sudoers/auth/dce.c, + plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/pam.c, + plugins/sudoers/auth/sia.c, plugins/sudoers/auth/sudo_auth.h, + plugins/sudoers/check.c, plugins/sudoers/defaults.c, + plugins/sudoers/defaults.h, plugins/sudoers/env.c, + plugins/sudoers/getdate.c, plugins/sudoers/getdate.y, + plugins/sudoers/gram.c, plugins/sudoers/gram.y, + plugins/sudoers/interfaces.h, plugins/sudoers/logging.c, + plugins/sudoers/logging.h, plugins/sudoers/match.c, + plugins/sudoers/mon_systrace.h, plugins/sudoers/parse.c, + plugins/sudoers/parse.h, plugins/sudoers/pwutil.c, + plugins/sudoers/redblack.c, plugins/sudoers/redblack.h, + plugins/sudoers/set_perms.c, plugins/sudoers/sudo_nss.h, + plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h, + plugins/sudoers/sudoreplay.c, plugins/sudoers/testsudoers.c, + plugins/sudoers/timestr.c, plugins/sudoers/toke.c, + plugins/sudoers/toke.l, plugins/sudoers/tsgetgrpw.c, + plugins/sudoers/visudo.c: + Kill __P in sudoers + [63601e6cb171] + + * config.h.in, configure, configure.in, src/load_plugins.c: + Set the sudoers plugin name in configure so we get the extension + right. + [edad89924cd1] + + * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod: + Document lines/cols in user_info + [a808872394f3] + + * src/Makefile.in, src/sudo.c, src/sudo.h, src/ttysize.c: + Add tty size to user info + [23f3d27e77a7] + + * src/script.c: + Use TIOCGSIZE/TIOCSSIZE instead of TIOCGWINSZ/TIOCSWINSZ + [a2208dd09051] + +2010-03-16 Todd C. Miller + + * plugins/sudoers/sudoers.c: + Kill dead code Add missing sigsetjmp in sudo_policy_invalidate Error + out if we fail to lookup the user's name that is passed in + [e4e3728ed482] + + * plugins/sudoers/error.c: + Pass the error value back via siglongjmp. + [667b8ad575ce] + + * plugins/sudoers/check.c: + Use conversation function for lecture. + [1ab4719f509b] + + * plugins/sudoers/check.c: + Don't update ticket file if verify_user returns FALSE. + [2bbc46a39a2b] + +2010-03-15 Todd C. Miller + + * plugins/sudoers/sudoers.c, src/sudo.c: + Wire up invalidate and validate methods for sudoers + [c0630c7bca47] + + * plugins/sudoers/check.c, plugins/sudoers/sudoers.c, + plugins/sudoers/sudoers.h: + Add support for -k flag with a command. + [edad239b098b] + + * src/parse_args.c: + Allow -k to be specified with a command. + [43a45add9974] + + * plugins/sudoers/sudoers.c: + Wire up policy_list + [27cc35699eca] + + * plugins/sudoers/error.c: + Add newline at the end of message and space after the colon in + warning message + [5a591aa8e744] + + * plugins/sudoers/auth/sudo_auth.c: + Add missing newline after pass password warning + [337dba3870a7] + + * plugins/sudoers/sudoers.c: + Set user_groups and user_ngroups based on user_info + [61bee85128c8] + + * plugins/sudoers/error.c: + Make this compile + [7041c441e1c8] + + * plugins/sudoers/error.c, plugins/sudoers/sudoers.c: + Make _warning in error.c use the conversation function and remove + commented out warning/warningx in sudoers.c. + [7c9b09024b63] + + * plugins/sudoers/logging.c: + Use siglongjmp() in log_error for fatal errors + [b50e26f1c73f] + + * plugins/sample/Makefile.in, plugins/sudoers/Makefile.in: + Quiet a libtool warning + [b2331fb006bc] + + * Makefile: + Build sudoers plugin + [5cdf06e66978] + + * plugins/sudoers/gram.c, plugins/sudoers/gram.y: + Use warningx in yyerror() so the conversation function gets used + when built as part of sudoers. + [85f964215eef] + +2010-03-14 Todd C. Miller + + * plugins/sudoers/auth/pam.c: + Rename sudo_conv to conversation to avoid a namespace conflict. + [1ad359d36be9] + + * plugins/sudoers/Makefile.in, plugins/sudoers/alias.c, + plugins/sudoers/auth/afs.c, plugins/sudoers/auth/aix_auth.c, + plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/dce.c, + plugins/sudoers/auth/fwtk.c, plugins/sudoers/auth/kerb4.c, + plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/pam.c, + plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/rfc1938.c, + plugins/sudoers/auth/secureware.c, plugins/sudoers/auth/securid.c, + plugins/sudoers/auth/securid5.c, plugins/sudoers/auth/sia.c, + plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/auth/sudo_auth.h, + plugins/sudoers/check.c, plugins/sudoers/defaults.c, + plugins/sudoers/env.c, plugins/sudoers/error.c, + plugins/sudoers/find_path.c, plugins/sudoers/getspwuid.c, + plugins/sudoers/goodpath.c, plugins/sudoers/gram.c, + plugins/sudoers/gram.y, plugins/sudoers/interfaces.c, + plugins/sudoers/ldap.c, plugins/sudoers/logging.c, + plugins/sudoers/match.c, plugins/sudoers/mon_systrace.c, + plugins/sudoers/parse.c, plugins/sudoers/pwutil.c, + plugins/sudoers/redblack.c, plugins/sudoers/set_perms.c, + plugins/sudoers/sudo_nss.c, plugins/sudoers/sudoers.c, + plugins/sudoers/sudoers.h, plugins/sudoers/testsudoers.c, + plugins/sudoers/toke.c, plugins/sudoers/tsgetgrpw.c, + plugins/sudoers/vasgroups.c, plugins/sudoers/visudo.c: + Initial bits of sudoers plugin; still needs work. + [af2a2c59a952] + + * config.h.in: + Add HAVE_STRDUP and HAVE_STRNDUP + [50a3c0dd510f] + + * compat/Makefile.in, configure, configure.in: + Build libmissing in two flavors (one PIC one non-PIC) and link with + the appropriate one. + [b62f411a4c18] + + * Makefile, compat/fnmatch.c, compat/glob.c, compat/nanosleep.c, + compat/utimes.c, plugins/sample/Makefile.in, src/Makefile.in: + Build libmissing in two flavors (one PIC one non-PIC) and link with + the appropriate one. + [e1e04972b5fe] + +2010-03-13 Todd C. Miller + + * include/missing.h: + Add strdup and strndup and fix strsignal + [c159babe2896] + +2010-03-12 Todd C. Miller + + * compat/strdup.c, compat/strndup.c, configure, configure.in, + plugins/sample/Makefile.in, src/Makefile.in: + Add strdup and strndup to compat + [25c9fd399a4d] + + * plugins/sample/sample_plugin.c: + Need to include compat.h before missing.h + [c94f7aad380f] + + * compat/strsignal.c: + Must check HAVE_DECL_SYS_SIGLIST == 1 (not just if defined) since if + it doesn't exist configure will set it to 0. + [384580566389] + + * compat/glob.c: + Fix botched ANSI C coversion of globexp2() + [4a344b8cbe49] + * configure, configure.in: - Fix installation of sudoers.ldap in "make install" when --with-ldap - was specified without a directory. From Prof. Dr. Andreas Mueller - [5177a284b9ff] <1.7> + Remove redundant getgroups check + [0b16ec210c81] + + * configure, configure.in, src/lbuf.c, src/script.c, src/term.c: + Require either termios or termio, no more sgtty. + [9b2fa2f17a1c] + + * compat/strsignal.c, config.h.in, configure, configure.in: + Change the sys_siglist check to use AC_CHECK_DECLS and also check + for _sys_siglist and__sys_siglist + [2e078fed2408] + +2010-03-11 Todd C. Miller + + * configure, configure.in, src/Makefile.in: + Change SUDO_LDFLAGS to SUDOERS_LDFLAGS and add SUDOERS_OBJS. We now + use SUDO_OBJS for the main driver as part of OBJS. + [9ae4a80a5ade] + + * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod: + Mention in the conversation function section that a newline is not + implicit. + [04a233b6c491] + + * include/compat.h: + Add definition of WCOREDUMP for systems without it. This is known + to work on AIX and SunOS 4, but may be incorrect on other systems + that lack WCOREDUMP. + [c85b3ce6b77d] 2010-03-09 Todd C. Miller - * match.c: - When doing a glob match, short circuit if gl.gl_pathc is 0. From - Mark Kettenis. - [549f8f7c2463] <1.7> + * plugins/sample/sample_plugin.c, src/conversation.c: + conversation function no longer puts a newline at the end of info or + error messages. + [c534cae1ac4a] -2010-03-08 Todd C. Miller +2010-03-07 Todd C. Miller - * script.c: + * src/script.c: Use parent process group id instead of parent process id when checking foreground status and suspending parent. Fixes an issue when running commands under /usr/bin/time and others. - [eac86126e335] <1.7> + [564f528c3bb7] - * env.c: - In setenv(), if the var is empty, return 1 and set errno to EINVAL - instead of returning EINVAL directly. - [d202091ec15e] <1.7> +2010-03-06 Todd C. Miller -2010-02-22 Todd C. Miller + * aclocal.m4: + transcript option is now --with not --enable + [0646fac4cf93] - * match.c: - Check for pseudo-command by looking at the first character of the - command in sudoers instead of checking the user-supplied command for - a slash. - [88f3181692fe] <1.7> + * plugins/sample/sample_plugin.c: + Add support to -u and -g flags Check fmt_string retval Add timeout + for debugging purposes + [cfefa4fa60b5] -2010-02-09 Todd C. Miller + * src/script.c, src/sudo.c: + Wire up SIGALRM handler Set close on exec flag for child side of the + socketpair Fix signal handling when not doing I/O logging + [379581ec7272] - * toke.l: - Avoid a duplicate fclose() of the sudoers file. - [164d39108dde] <1.7> + * src/sudo.c: + g/c unused SIGCHLD handler + [0afa03912dce] - * toke.l: - Fix size arg when realloc()ing include stack. From Daniel Kopecek - [8900bccef219] <1.7> + * src/fmt_string.c, src/parse_args.c, src/sudo.c: + Don't use emalloc() in fmt_string(); we want to be able to use it + from a plugin. + [ade64d368147] + + * include/list.h: + tq_remove not list_remove + [0e0e1fd5c31c] + + * configure, configure.in: + AUTH_OBJS should contain .lo files not .o files. + [c64c82c9d5a2] + +2010-03-05 Todd C. Miller + + * src/parse_args.c: + Simplify conversion of command line args to name=value pairs. + [75ab127c6a94] + + * plugins/sample/sample_plugin.c: + Handle NULL reply from conversation function + [6ce09b6cb204] + + * compat/getline.c: + Don't depend on emalloc/erealloc + [73df09e2109f] + + * plugins/sample/Makefile.in: + Use $(OBJS) instead of sample_plugin.lo + [2d995db9aa99] -2010-02-06 Todd C. Miller + * plugins/sample/sample_plugin.c: + runas_user is in settings not user_info + [7ee12068bc57] + + * src/parse_args.c: + Fix a mismatch between sudo_settings and settings_pairs that causes + some settings to get the wrong values. + [b1bc6d81a65f] + +2010-03-04 Todd C. Miller + + * src/Makefile.in, src/aix.c, src/alloc.c, src/atobool.c, src/error.c, + src/fileops.c, src/lbuf.c, src/list.c, src/pty.c, src/sesh.c, + src/sudo.c, src/sudo_edit.c, src/term.c, src/zero_bytes.c: + Convert to ANSI C + [d03b6e4a3b75] + + * src/load_plugins.c: + Fix strlcpy() return value check. + [7cd66999a374] + + * INSTALL, configure, configure.in: + No longer need to substitute in script.o and pty.o; I/O logging + support is always built. + [45250024c5dc] - * aix.c, config.h.in, configure, configure.in: - Use setrlimit64(), if available, instead of setrlimit() when setting +2010-02-28 Todd C. Miller + + * src/script.c: + Add fallback to /bin/sh when execve() fails with ENOEXEC. + [7684a15a1352] + + * include/alloc.h, src/alloc.c: + Add estrndup() + [47621c83bed9] + +2010-02-27 Todd C. Miller + + * src/script.c, src/sudo.c: + Refactor script_execve() a bit so that it can be used in non-script + mode. Needs more cleanup. + [f09e022d547c] + + * src/sudo.c: + Ignore empty entries in command_info list + [1eea9a8de21c] + + * include/list.h, src/list.c: + Add tq_remove + [40908a617cb2] + + * src/conversation.c: + Pass timeout to tgetpass() + [9e66c918b771] + + * Makefile: + Add ChangeLog target + [da4a39150838] + + * README, WHATSNEW: + Bump version and update things slightly for sudo 1.8.0 + [4b73cc45e2d4] + + * configure, configure.in: + Sudo now requires an ANSI/ISO C compiler + [1e51f72e6964] + + * src/alloc.c, src/audit.c, src/error.c, src/lbuf.c, + src/sudo_noexec.c: + Convert to ANSI C + [5cbd315dbde8] + + * include/alloc.h, include/compat.h, include/error.h, include/lbuf.h, + include/list.h, include/missing.h: + Convert to ANSI C + [3f5016ff64f4] + + * compat/charclass.h, compat/closefrom.c, compat/fnmatch.c, + compat/fnmatch.h, compat/getcwd.c, compat/getline.c, + compat/getprogname.c, compat/glob.c, compat/glob.h, + compat/isblank.c, compat/memrchr.c, compat/mkstemp.c, + compat/nanosleep.c, compat/sigaction.c, compat/snprintf.c, + compat/strcasecmp.c, compat/strerror.c, compat/strlcat.c, + compat/strlcpy.c, compat/strsignal.c, compat/utime.h, + compat/utimes.c: + Convert to ANSI C + [0d635c85461c] + +2010-02-24 Todd C. Miller + + * src/sudo.c, src/tgetpass.c: + Make user_details extern so tgetpass can get at the uid and gid. Set + uid/gid to user before executing askpass program. Check environment + for SUDO_ASKPASS and use that if set. TODO: a way for the policy to + set the askpass program itself + [d33606396176] + + * src/sudo.c: + No longer need sudo_usage.h in sudo.c + [063e2946c382] + + * doc/sudo.cat, doc/sudo.man.in, doc/sudo.pod, doc/sudo_plugin.man.in, + doc/sudo_plugin.pod, src/Makefile.in, src/parse_args.c, + src/sudo_usage.h.in: + Document -D level command line flag which maps to the debug_level + setting. + [61f1e2ab3ac1] + + * doc/sudo_plugin.cat, doc/sudo_plugin.man.in, doc/sudo_plugin.pod: + Document debug_level in plugin doc. Still need to document the -D + flag in sudo itself. + [8c62daea3e9b] + +2010-02-21 Todd C. Miller + + * plugins/sample/sample_plugin.c: + include missing,h for vasprintf + [92503de49b39] + + * doc/Makefile.in, doc/plugin.pod, doc/sudo_plugin.cat, + doc/sudo_plugin.man.in, doc/sudo_plugin.pod: + Rename plugin.pod -> sudo_plugin.pod and wire into Makefile + [14cfb4775238] + + * plugins/sample/sample_plugin.c: + Need to include limits.h + [bda7f74343d2] + + * compat/glob.c: + No more sudo_getpw* + [232e52907634] + + * plugins/sample/Makefile.in, src/Makefile.in: + Add missing compat bits + [4843dd000e08] + + * compat/closefrom.c, compat/mkstemp.c, plugins/sample/Makefile.in: + compat files should not include sudo.h wire up compat in sample + plugin + [a175b8185e0f] + + * Makefile, configure, configure.in, doc/Makefile.in, src/Makefile.in: + Fix up compat dependencies. Fix distclean target in doc/Makefile.in + [57e49bc20857] + + * configure, configure.in: + Fix typo + [333655e3d5fe] + + * plugins/sample/sample_plugin.c: + Log input and output to temp files for proof of concept. + [ae1dfc34f7d6] + + * Makefile, configure, configure.in, doc/Makefile.in: + Add doc Makefile.in and wire it up + [6a310443c87d] + + * src/script.c: + Handle SIGSTOP in addition to SIGTSTP. Fixes a problem with + suspending a shell with the "suspend" builtint. + [3d65f182819a] + + * src/script.c: + In child, handle parent side of the pipe going away. + [a29c14d78cd9] + + * src/script.c: + No longer need to check for explicit death of the child (process #2) + since if it dies we will get EPIPE from the socketpair. Fix a + sizeof() that was causing a spurious error. Convert SCRIPT_DEBUG to + sudo_debug. + [24c55dd4ff60] + + * src/sudo.c: + Make sudo_debug do a single vfprintf() which will result in a single + write call on most systems. Avoids problems with interleaved debug + printf from different processes. Also remove an extraneous error + case since recv() can't return a short read and add some more XXX. + [b37a8533ef1e] + +2010-02-20 Todd C. Miller + + * src/script.c: + Fix uninitialized variable. + [e012a0a30890] + + * src/Makefile.in: + Fix sudo install target + [1417fa4b4ab9] + + * src/parse_args.c, src/sudo.c, src/sudo.h: + Wire up debug_level + [144fab289c73] + + * src/Makefile.in: + Fix dependencies + [5170940af2ce] + + * configure, configure.in: + Fix setting of plugin dir + [144eda170a72] + + * Makefile: + add clean targets + [d53f6f6f5c3a] + + * src/atobool.c: + Add missing source for sudo front end + [42487de9c489] + + * plugins/sample/Makefile.in, plugins/sample/sample_plugin.c: + Sample plugin demonstrating the sudo plugin API + [f1fd62d7644f] + + * Makefile, configure, configure.in, install-sh, pathnames.h.in, + plugins/sudoers/install-sh, src/Makefile.in, src/conversation.c, + src/fileops.c, src/fmt_string.c, src/load_plugins.c, + src/parse_args.c, src/pty.c, src/script.c, src/sudo.c, src/sudo.h, + src/sudo_plugin_int.h, src/sudo_usage.h.in, src/tgetpass.c, + sudo_usage.h.in: + Modular sudo front-end which loads policy and I/O plugins that do + most the actual work. Currently relies on dynamic loading using + dlopen(). See doc/plugin.pod for the plugin API. + [924f6eb2fbba] + + * doc/plugin.pod, include/sudo_plugin.h: + Sudo plugin API + [374ccbbd24ae] + + * compat/fnmatch.c, compat/glob.c, compat/nanosleep.c, + compat/utimes.c, plugins/sudoers/check.c, plugins/sudoers/gettime.c, + plugins/sudoers/match.c, plugins/sudoers/sudoreplay.c, + plugins/sudoers/testsudoers.c, plugins/sudoers/visudo.c, + src/fileops.c, src/sudo_edit.c: + Replace emul/include.h with compat/include.h to match new source + tree layout. + [7eccd10449a1] + + * src/lbuf.c: + Include missing.h for memrchr() proto + [03abd63a8a33] + + * HISTORY, LICENSE, Makefile.binary.in, Makefile.in, PORTING, + TROUBLESHOOTING, UPGRADE, aix.c, aixcrypt.exp, alias.c, alloc.c, + alloc.h, audit.c, auth/API, auth/afs.c, auth/aix_auth.c, + auth/bsdauth.c, auth/dce.c, auth/fwtk.c, auth/kerb4.c, auth/kerb5.c, + auth/pam.c, auth/passwd.c, auth/rfc1938.c, auth/secureware.c, + auth/securid.c, auth/securid5.c, auth/sia.c, auth/sudo_auth.c, + auth/sudo_auth.h, boottime.c, bsm_audit.c, bsm_audit.h, check.c, + closefrom.c, compat.h, compat/charclass.h, compat/closefrom.c, + compat/fnmatch.c, compat/fnmatch.h, compat/getcwd.c, + compat/getline.c, compat/getprogname.c, compat/glob.c, + compat/glob.h, compat/isblank.c, compat/memrchr.c, compat/mkstemp.c, + compat/nanosleep.c, compat/sigaction.c, compat/snprintf.c, + compat/strcasecmp.c, compat/strerror.c, compat/strlcat.c, + compat/strlcpy.c, compat/strsignal.c, compat/timespec.h, + compat/utime.h, compat/utimes.c, def_data.c, def_data.h, + def_data.in, defaults.c, defaults.h, doc/HISTORY, doc/LICENSE, + doc/PORTING, doc/TROUBLESHOOTING, doc/UPGRADE, doc/history.pod, + doc/license.pod, doc/sample.pam, doc/sample.sudoers, + doc/sample.syslog.conf, doc/schema.ActiveDirectory, + doc/schema.OpenLDAP, doc/schema.iPlanet, doc/sudo.cat, + doc/sudo.man.in, doc/sudo.man.pl, doc/sudo.pod, doc/sudoers.cat, + doc/sudoers.ldap.cat, doc/sudoers.ldap.man.in, doc/sudoers.ldap.pod, + doc/sudoers.man.in, doc/sudoers.man.pl, doc/sudoers.pod, + doc/sudoreplay.cat, doc/sudoreplay.man.in, doc/sudoreplay.pod, + doc/visudo.cat, doc/visudo.man.in, doc/visudo.pod, emul/charclass.h, + emul/fnmatch.h, emul/glob.h, emul/timespec.h, emul/utime.h, env.c, + error.c, error.h, fileops.c, find_path.c, fnmatch.c, getcwd.c, + getdate.c, getdate.y, getline.c, getprogname.c, getspwuid.c, + gettime.c, glob.c, goodpath.c, gram.c, gram.h, gram.y, history.pod, + include/alloc.h, include/compat.h, include/error.h, include/lbuf.h, + include/list.h, include/missing.h, ins_2001.h, ins_classic.h, + ins_csops.h, ins_goons.h, install-sh, insults.h, interfaces.c, + interfaces.h, isblank.c, lbuf.c, lbuf.h, ldap.c, license.pod, + list.c, list.h, logging.c, logging.h, match.c, memrchr.c, missing.h, + mkdefaults, mkstemp.c, mon_systrace.c, mon_systrace.h, nanosleep.c, + nonunix.h, parse.c, parse.h, plugins/sudoers/Makefile.binary.in, + plugins/sudoers/Makefile.in, plugins/sudoers/aixcrypt.exp, + plugins/sudoers/alias.c, plugins/sudoers/auth/API, + plugins/sudoers/auth/afs.c, plugins/sudoers/auth/aix_auth.c, + plugins/sudoers/auth/bsdauth.c, plugins/sudoers/auth/dce.c, + plugins/sudoers/auth/fwtk.c, plugins/sudoers/auth/kerb4.c, + plugins/sudoers/auth/kerb5.c, plugins/sudoers/auth/pam.c, + plugins/sudoers/auth/passwd.c, plugins/sudoers/auth/rfc1938.c, + plugins/sudoers/auth/secureware.c, plugins/sudoers/auth/securid.c, + plugins/sudoers/auth/securid5.c, plugins/sudoers/auth/sia.c, + plugins/sudoers/auth/sudo_auth.c, plugins/sudoers/auth/sudo_auth.h, + plugins/sudoers/boottime.c, plugins/sudoers/check.c, + plugins/sudoers/def_data.c, plugins/sudoers/def_data.h, + plugins/sudoers/def_data.in, plugins/sudoers/defaults.c, + plugins/sudoers/defaults.h, plugins/sudoers/env.c, + plugins/sudoers/find_path.c, plugins/sudoers/getdate.c, + plugins/sudoers/getdate.y, plugins/sudoers/getspwuid.c, + plugins/sudoers/gettime.c, plugins/sudoers/goodpath.c, + plugins/sudoers/gram.c, plugins/sudoers/gram.h, + plugins/sudoers/gram.y, plugins/sudoers/ins_2001.h, + plugins/sudoers/ins_classic.h, plugins/sudoers/ins_csops.h, + plugins/sudoers/ins_goons.h, plugins/sudoers/install-sh, + plugins/sudoers/insults.h, plugins/sudoers/interfaces.c, + plugins/sudoers/interfaces.h, plugins/sudoers/ldap.c, + plugins/sudoers/logging.c, plugins/sudoers/logging.h, + plugins/sudoers/match.c, plugins/sudoers/mkdefaults, + plugins/sudoers/mon_systrace.c, plugins/sudoers/mon_systrace.h, + plugins/sudoers/nonunix.h, plugins/sudoers/parse.c, + plugins/sudoers/parse.h, plugins/sudoers/pwutil.c, + plugins/sudoers/redblack.c, plugins/sudoers/redblack.h, + plugins/sudoers/set_perms.c, plugins/sudoers/sudo_nss.c, + plugins/sudoers/sudo_nss.h, plugins/sudoers/sudoers, + plugins/sudoers/sudoers.c, plugins/sudoers/sudoers.h, + plugins/sudoers/sudoers2ldif, plugins/sudoers/sudoreplay.c, + plugins/sudoers/testsudoers.c, plugins/sudoers/timestr.c, + plugins/sudoers/toke.c, plugins/sudoers/toke.l, + plugins/sudoers/tsgetgrpw.c, plugins/sudoers/vasgroups.c, + plugins/sudoers/visudo.c, pty.c, pwutil.c, redblack.c, redblack.h, + sample.pam, sample.sudoers, sample.syslog.conf, + schema.ActiveDirectory, schema.OpenLDAP, schema.iPlanet, script.c, + selinux.c, sesh.c, set_perms.c, sigaction.c, snprintf.c, src/aix.c, + src/alloc.c, src/audit.c, src/bsm_audit.c, src/bsm_audit.h, + src/error.c, src/fileops.c, src/lbuf.c, src/list.c, src/pty.c, + src/script.c, src/selinux.c, src/sesh.c, src/sudo_edit.c, + src/sudo_noexec.c, src/term.c, src/tgetpass.c, src/zero_bytes.c, + strcasecmp.c, strerror.c, strlcat.c, strlcpy.c, strsignal.c, sudo.c, + sudo.cat, sudo.h, sudo.man.in, sudo.man.pl, sudo.pod, sudo_edit.c, + sudo_noexec.c, sudo_nss.c, sudo_nss.h, sudoers, sudoers.cat, + sudoers.ldap.cat, sudoers.ldap.man.in, sudoers.ldap.pod, + sudoers.man.in, sudoers.man.pl, sudoers.pod, sudoers2ldif, + sudoreplay.c, sudoreplay.cat, sudoreplay.man.in, sudoreplay.pod, + term.c, testsudoers.c, tgetpass.c, timestr.c, toke.c, toke.l, + tsgetgrpw.c, utimes.c, vasgroups.c, visudo.c, visudo.cat, + visudo.man.in, visudo.pod, zero_bytes.c: + Rework source layout in preparation for modular sudo. + [7fc1978c6ad5] + +2010-02-13 Todd C. Miller + + * Avoid a duplicate fclose() of the sudoers file. + [5dba851088c1] + + * Fix size arg when realloc()ing include stack. From Daniel Kopecek + [0a2935061e33] + + * Use setrlimit64(), if available, instead of setrlimit() when setting AIX resource limits since rlim_t is 32bits. - [2cbb14d98fc1] <1.7> + [353db89bac61] - * logging.c: - Fix use after free when sending error messages. From Timo Juhani + * Fix use after free when sending error messages. From Timo Juhani Lindfors - [caf183fd9d94] <1.7> - -2010-01-18 Todd C. Miller + [e50dbd902382] * ChangeLog, Makefile.in: Generate the ChangeLog as part of "make dist" instead of having it in the repo. - [836c31615859] <1.7> - -2010-01-17 Todd C. Miller - - * Makefile.in: - Generate correct ChangeLog for 1.7 branch. - [586dd90b8878] <1.7> + [251b70964673] 2010-01-17 Todd C. Miller @@ -3011,6 +5909,12 @@ Remove CVS $Sudo$ tags. [de683a8b31f5] +2010-01-18 convert-repo + + * .hgtags: + update tags + [9b7aa44ae436] + 2009-12-26 Todd C. Miller * sudo_usage.h.in: diff --git a/INSTALL b/INSTALL index d9568d3..b8156e6 100644 --- a/INSTALL +++ b/INSTALL @@ -1,4 +1,4 @@ -Installation instructions for Sudo 1.7 +Installation instructions for Sudo 1.8 ====================================== Sudo uses a `configure' script to probe the capabilities and type @@ -30,13 +30,13 @@ For most systems and configurations it is possible simply to: have changed the paths via options to `configure'. 5) Type `make' to compile sudo. If you are building sudo - in a separate build tree (apart from the sudo source) - GNU make will probably be required. If `configure' did - its job properly (and you have a supported configuration) - there won't be any problems. If this doesn't work, take - a look at the files TROUBLESHOOTING and PORTING for tips - on what might have gone wrong. Please mail us if you have a - fix or if you are unable to come up with a fix (address at EOF). + in a separate build tree (apart from the sudo source) GNU + make will probably be required. If `configure' did its job + properly (and you have a supported configuration) there won't + be any problems. If this doesn't work, take a look at the + TROUBLESHOOTING file for tips on what might have gone wrong. + Please mail us if you have a fix or if you are unable to + come up with a fix (address at EOF). 6) Type `make install' (as root) to install sudo, visudo, the man pages, and a skeleton sudoers file. Note that the install @@ -134,6 +134,10 @@ Special features/options: `-l' will be prepended to it. Multiple libraries may be specified as long as they are space separated. + --with-plugindir=PATH + Set the directory that sudo looks in to find the policy and I/O + logging plugins. Defaults to the libexec dir used by configure. + --with-efence Link with the "electric fence" debugging malloc. @@ -141,13 +145,18 @@ Special features/options: Enable support for sudo BSM audit logs on systems that support it. Currently only supported under FreeBSD and Mac OS X. + --with-csops + Add CSOps standard options. You probably aren't interested in this. + + --with-devel + Configure development options. This will enable compiler warnings + and set the Makefile to be able to regenerate the sudoers parser + as well as the manual pages. + --with-linux-audit Enable audit support for Linux systems. Audits attempts to run a command as well as SELinux role changes. - --with-csops - Add CSOps standard options. You probably aren't interested in this. - --with-skey[=DIR] Enable S/Key OTP (One Time Password) support. If specified, DIR should contain include and lib directories with skey.h @@ -346,16 +355,6 @@ Special features/options: Enable support for role based access control (RBAC) on systems that support SELinux. - --with-libvas=[NAME] - Enable non-Unix group support using Quest Authentication - Services. If NAME is specified, it should be the name of - the shared library providing QAS support (libvas.so by default). - - --with-libvas-rpath=[PATH] - The path to search when loading libvas.so (or an alternate - name as specified by --with-libvas). This option only has - an effect when --with-libvas is specified. - The following options are also configurable at runtime: --with-long-otp-prompt @@ -567,15 +566,11 @@ The following options are also configurable at runtime: prompt as an argument and print the received password to the standard output. - --without-iologdir - Disable sudo's I/O logging support. This can be used to allow sudo - to be compiled on systems without pseudo-tty support. - --with-iologdir[=DIR] - By default, sudo stores I/O log files in either /var/log/sudo-io, - /var/adm/sudo-sudo-io or /usr/log/sudo-io. If DIR is - specified, I/O logs will be stored in the indicated directory - instead. + By default, sudo stores I/O log files in either /var/log/sudo-io, + /var/adm/sudo-io, or /usr/log/sudo-io. If this option is + specified, I/O logs will be stored in the indicated directory + instead. --disable-authentication By default, sudo requires the user to authenticate via a @@ -619,15 +614,14 @@ The following options are also configurable at runtime: the user that they are not allowed to run it, which can be confusing. --enable-zlib[=location] - Enable the use of the zlib compress library when storing - I/O log files. If specified, location is the base directory - containing the zlib include and lib directories. The special - values "system" and "builtin" can be used to indicate that - the system version of zlib should be used or that the version - of zlib shipped with sudo should be used instead. - If this option is not specified, configure will use the - system zlib if it is present and I/O logging support has - not been disabled. + Enable the use of the zlib compress library when storing + I/O log files. If specified, location is the base directory + containing the zlib include and lib directories. The special + values "system" and "builtin" can be used to indicate that + the system version of zlib should be used or that the version + of zlib shipped with sudo should be used instead. + If this option is not specified, configure will use the + system zlib if it is present. --disable-zlib Disable the use of the zlib compress library when storing @@ -725,11 +719,9 @@ Mac OS X: is bug id #7952709. HP-UX: - The default C compiler shipped with HP-UX does not support - creating position independent code and so is unable to support - sudo's "noexec" functionality. You must use either the HP ANSI - C compiler or gcc for noexec to work. Binary packages of gcc - are available http://hpux.connect.org.uk/. + The default C compiler shipped with HP-UX is not an ANSI compiler. + You must use either the HP ANSI C compiler or gcc to build sudo. + Binary packages of gcc are available from http://hpux.connect.org.uk/. To prevent PAM from overriding the value of umask on HP-UX 11, you will need to add a line like the following to /etc/pam.conf: @@ -765,12 +757,18 @@ SCO ODT: and /SLS/lng225b.ltr.Z. SunOS 4.x: + SunOS does not ship with an ANSI C compiler. You will need to + install an ANSI compiler such as gcc to build sudo. + The /bin/sh shipped with SunOS blows up while running configure. You can work around this by installing bash or zsh. If you have bash or zsh in your path, configure will use it instead automatically. ULTRIX 4.x: + ULTRIX does not ship with an ANSI C compiler. You will need to + install an ANSI compiler such as gcc to build sudo. + The /bin/sh shipped with ULTRIX blows up while running configure. You can work around this by installing bash or zsh. If you have bash or zsh in your path, configure will use it instead diff --git a/MANIFEST b/MANIFEST new file mode 100644 index 0000000..f50d03e --- /dev/null +++ b/MANIFEST @@ -0,0 +1,279 @@ +ChangeLog +INSTALL +INSTALL.configure +MANIFEST +Makefile.in +NEWS +README +README.LDAP +aclocal.m4 +common/Makefile.in +common/aix.c +common/alloc.c +common/atobool.c +common/fileops.c +common/fmt_string.c +common/lbuf.c +common/list.c +common/term.c +common/zero_bytes.c +compat/Makefile.in +compat/charclass.h +compat/closefrom.c +compat/dlfcn.h +compat/dlopen.c +compat/fnmatch.c +compat/fnmatch.h +compat/getcwd.c +compat/getline.c +compat/getprogname.c +compat/glob.c +compat/glob.h +compat/isblank.c +compat/memrchr.c +compat/mksiglist.c +compat/mksiglist.h +compat/mktemp.c +compat/nanosleep.c +compat/regress/fnmatch/fnm_test.c +compat/regress/fnmatch/fnm_test.in +compat/regress/glob/files +compat/regress/glob/globtest.c +compat/regress/glob/globtest.in +compat/setenv.c +compat/siglist.in +compat/snprintf.c +compat/strlcat.c +compat/strlcpy.c +compat/strsignal.c +compat/timespec.h +compat/unsetenv.c +compat/utime.h +compat/utimes.c +config.guess +config.h.in +config.sub +configure +configure.in +doc/HISTORY +doc/LICENSE +doc/Makefile.in +doc/TROUBLESHOOTING +doc/UPGRADE +doc/history.pod +doc/license.pod +doc/sample.pam +doc/sample.sudo.conf +doc/sample.sudoers +doc/sample.syslog.conf +doc/schema.ActiveDirectory +doc/schema.OpenLDAP +doc/schema.iPlanet +doc/sudo.cat +doc/sudo.man.in +doc/sudo.man.pl +doc/sudo.pod +doc/sudo_plugin.cat +doc/sudo_plugin.man.in +doc/sudo_plugin.pod +doc/sudoers.cat +doc/sudoers.ldap.cat +doc/sudoers.ldap.man.in +doc/sudoers.ldap.pod +doc/sudoers.man.in +doc/sudoers.man.pl +doc/sudoers.pod +doc/sudoreplay.cat +doc/sudoreplay.man.in +doc/sudoreplay.pod +doc/visudo.cat +doc/visudo.man.in +doc/visudo.pod +include/Makefile.in +include/alloc.h +include/error.h +include/fileops.h +include/lbuf.h +include/list.h +include/missing.h +include/sudo_plugin.h +indent.pro +install-sh +ltmain.sh +m4/libtool.m4 +m4/ltoptions.m4 +m4/ltsugar.m4 +m4/ltversion.m4 +m4/lt~obsolete.m4 +mkinstalldirs +mkpkg +pathnames.h.in +plugins/sample/Makefile.in +plugins/sample/sample_plugin.c +plugins/sample/sample_plugin.sym +plugins/sample_group/Makefile.in +plugins/sample_group/getgrent.c +plugins/sample_group/plugin_test.c +plugins/sample_group/sample_group.c +plugins/sample_group/sample_group.sym +plugins/sudoers/Makefile.in +plugins/sudoers/aixcrypt.exp +plugins/sudoers/alias.c +plugins/sudoers/audit.c +plugins/sudoers/auth/API +plugins/sudoers/auth/afs.c +plugins/sudoers/auth/aix_auth.c +plugins/sudoers/auth/bsdauth.c +plugins/sudoers/auth/dce.c +plugins/sudoers/auth/fwtk.c +plugins/sudoers/auth/kerb4.c +plugins/sudoers/auth/kerb5.c +plugins/sudoers/auth/pam.c +plugins/sudoers/auth/passwd.c +plugins/sudoers/auth/rfc1938.c +plugins/sudoers/auth/secureware.c +plugins/sudoers/auth/securid.c +plugins/sudoers/auth/securid5.c +plugins/sudoers/auth/sia.c +plugins/sudoers/auth/sudo_auth.c +plugins/sudoers/auth/sudo_auth.h +plugins/sudoers/boottime.c +plugins/sudoers/bsm_audit.c +plugins/sudoers/bsm_audit.h +plugins/sudoers/check.c +plugins/sudoers/def_data.c +plugins/sudoers/def_data.h +plugins/sudoers/def_data.in +plugins/sudoers/defaults.c +plugins/sudoers/defaults.h +plugins/sudoers/env.c +plugins/sudoers/find_path.c +plugins/sudoers/getdate.c +plugins/sudoers/getdate.y +plugins/sudoers/getspwuid.c +plugins/sudoers/goodpath.c +plugins/sudoers/gram.c +plugins/sudoers/gram.h +plugins/sudoers/gram.y +plugins/sudoers/group_plugin.c +plugins/sudoers/ins_2001.h +plugins/sudoers/ins_classic.h +plugins/sudoers/ins_csops.h +plugins/sudoers/ins_goons.h +plugins/sudoers/insults.h +plugins/sudoers/interfaces.c +plugins/sudoers/interfaces.h +plugins/sudoers/iolog.c +plugins/sudoers/iolog_path.c +plugins/sudoers/ldap.c +plugins/sudoers/linux_audit.c +plugins/sudoers/linux_audit.h +plugins/sudoers/logging.c +plugins/sudoers/logging.h +plugins/sudoers/match.c +plugins/sudoers/mkdefaults +plugins/sudoers/parse.c +plugins/sudoers/parse.h +plugins/sudoers/plugin_error.c +plugins/sudoers/pwutil.c +plugins/sudoers/redblack.c +plugins/sudoers/redblack.h +plugins/sudoers/regress/iolog_path/check_iolog_path.c +plugins/sudoers/regress/iolog_path/data +plugins/sudoers/regress/parser/check_fill.c +plugins/sudoers/regress/sudoers/test1.in +plugins/sudoers/regress/sudoers/test1.out.ok +plugins/sudoers/regress/sudoers/test1.toke.ok +plugins/sudoers/regress/sudoers/test2.in +plugins/sudoers/regress/sudoers/test2.out.ok +plugins/sudoers/regress/sudoers/test2.toke.ok +plugins/sudoers/regress/sudoers/test3.in +plugins/sudoers/regress/sudoers/test3.out.ok +plugins/sudoers/regress/sudoers/test3.toke.ok +plugins/sudoers/regress/sudoers/test4.in +plugins/sudoers/regress/sudoers/test4.out.ok +plugins/sudoers/regress/sudoers/test4.toke.ok +plugins/sudoers/regress/sudoers/test5.in +plugins/sudoers/regress/sudoers/test5.out.ok +plugins/sudoers/regress/sudoers/test5.toke.ok +plugins/sudoers/regress/sudoers/test6.in +plugins/sudoers/regress/sudoers/test6.out.ok +plugins/sudoers/regress/sudoers/test6.toke.ok +plugins/sudoers/regress/sudoers/test7.in +plugins/sudoers/regress/sudoers/test7.out.ok +plugins/sudoers/regress/sudoers/test7.toke.ok +plugins/sudoers/regress/sudoers/test8.in +plugins/sudoers/regress/sudoers/test8.out.ok +plugins/sudoers/regress/sudoers/test8.toke.ok +plugins/sudoers/regress/testsudoers/test1.out.ok +plugins/sudoers/regress/testsudoers/test1.sh +plugins/sudoers/set_perms.c +plugins/sudoers/sudo_nss.c +plugins/sudoers/sudo_nss.h +plugins/sudoers/sudoers.c +plugins/sudoers/sudoers.h +plugins/sudoers/sudoers.in +plugins/sudoers/sudoers.sym +plugins/sudoers/sudoers2ldif +plugins/sudoers/sudoers_version.h +plugins/sudoers/sudoreplay.c +plugins/sudoers/testsudoers.c +plugins/sudoers/timestr.c +plugins/sudoers/toke.c +plugins/sudoers/toke.h +plugins/sudoers/toke.l +plugins/sudoers/toke_util.c +plugins/sudoers/tsgetgrpw.c +plugins/sudoers/tsgetgrpw.h +plugins/sudoers/visudo.c +pp +src/Makefile.in +src/conversation.c +src/error.c +src/exec.c +src/exec_pty.c +src/get_pty.c +src/load_plugins.c +src/net_ifs.c +src/parse_args.c +src/preload.c +src/selinux.c +src/sesh.c +src/sudo.c +src/sudo.h +src/sudo_edit.c +src/sudo_exec.h +src/sudo_noexec.c +src/sudo_plugin_int.h +src/sudo_usage.h.in +src/tgetpass.c +src/ttysize.c +src/utmp.c +sudo.pp +zlib/Makefile.in +zlib/adler32.c +zlib/compress.c +zlib/crc32.c +zlib/crc32.h +zlib/deflate.c +zlib/deflate.h +zlib/gzclose.c +zlib/gzguts.h +zlib/gzlib.c +zlib/gzread.c +zlib/gzwrite.c +zlib/infback.c +zlib/inffast.c +zlib/inffast.h +zlib/inffixed.h +zlib/inflate.c +zlib/inflate.h +zlib/inftrees.c +zlib/inftrees.h +zlib/trees.c +zlib/trees.h +zlib/uncompr.c +zlib/zconf.h.in +zlib/zlib.h +zlib/zutil.c +zlib/zutil.h diff --git a/Makefile.in b/Makefile.in index b16338b..6df0c07 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1,6 +1,5 @@ # -# Copyright (c) 1996, 1998-2005, 2007-2011 -# Todd C. Miller +# Copyright (c) 2010-2011 Todd C. Miller # # Permission to use, copy, modify, and distribute this software for any # purpose with or without fee is hereby granted, provided that the above @@ -15,595 +14,96 @@ # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. # ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -# Sponsored in part by the Defense Advanced Research Projects -# Agency (DARPA) and Air Force Research Laboratory, Air Force -# Materiel Command, USAF, under agreement number F39502-99-1-0512. -# -# @configure_input@ -# - -#### Start of system configuration section. #### srcdir = @srcdir@ devdir = @devdir@ -authdir = $(srcdir)/auth -top_builddir = . - -# Compiler & tools to use -CC = @CC@ -FLEX = @FLEX@ -YACC = @YACC@ -NROFF = @NROFFPROG@ -Tascii -LIBTOOL = @LIBTOOL@ -AR=@AR@ -RANLIB=@RANLIB@ - -# Our install program supports extra flags... -INSTALL = $(SHELL) $(srcdir)/install-sh -c - -# Libraries -LIBS = @LIBS@ -NET_LIBS = @NET_LIBS@ -SUDO_LIBS = @SUDO_LIBS@ @AFS_LIBS@ @GETGROUPS_LIB@ $(LIBS) $(NET_LIBS) - -# C preprocessor flags -CPPFLAGS = -I. -I$(srcdir) @CPPFLAGS@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ -# Usually -O and/or -g -CFLAGS = @CFLAGS@ - -# Flags to pass to the link stage -LDFLAGS = -L. @LDFLAGS@ -SUDO_LDFLAGS = @SUDO_LDFLAGS@ $(LDFLAGS) - -# Where to install things... +# Installation paths for package building prefix = @prefix@ exec_prefix = @exec_prefix@ bindir = @bindir@ sbindir = @sbindir@ sysconfdir = @sysconfdir@ libexecdir = @libexecdir@ +includedir = @includedir@ datarootdir = @datarootdir@ localstatedir = @localstatedir@ docdir = @docdir@ mandir = @mandir@ timedir = @timedir@ -noexecfile = @NOEXECFILE@ -noexecdir = @NOEXECDIR@ - -# Directory in which to install sudo. -sudodir = $(bindir) -# Directory in which to install visudo -visudodir = $(sbindir) - -# Directory in which to install the sudoers file +# sudoers owner and mode for package building sudoersdir = $(sysconfdir) - -# Directory in which to install the man page -mantype = @MANTYPE@ -mansectsu = @mansectsu@ -mansectform = @mansectform@ -mandirsu = $(mandir)/$(mantype)$(mansectsu) -mandirform = $(mandir)/$(mantype)$(mansectform) - -# User and group ids the installed files should be "owned" by -install_uid = 0 -install_gid = 0 - -# User, group, and mode the sudoers file should be "owned" by (configure) sudoers_uid = @SUDOERS_UID@ sudoers_gid = @SUDOERS_GID@ sudoers_mode = @SUDOERS_MODE@ -# Pass in paths and uid/gid + OS dependent defined -DEFS = @OSDEFS@ -D_PATH_SUDOERS=\"$(sudoersdir)/sudoers\" -DSUDOERS_UID=$(sudoers_uid) -DSUDOERS_GID=$(sudoers_gid) -DSUDOERS_MODE=$(sudoers_mode) - -#### End of system configuration section. #### - -SHELL = @SHELL@ - -PROGS = @PROGS@ - -SRCS = aix.c alias.c alloc.c audit.c boottime.c bsm_audit.c check.c \ - closefrom.c def_data.c defaults.c env.c error.c exec.c exec_pty.c \ - fileops.c find_path.c fnmatch.c get_pty.c getcwd.c getprogname.c \ - getspwuid.c gettime.c glob.c goodpath.c gram.c gram.y interfaces.c \ - iolog.c isblank.c lbuf.c ldap.c linux_audit.c list.c logging.c match.c \ - mksiglist.c mkstemps.c memrchr.c nanosleep.c parse.c parse_args.c \ - pwutil.c set_perms.c setsid.c sigaction.c snprintf.c strcasecmp.c \ - strerror.c strlcat.c strlcpy.c strsignal.c sudo.c sudo_noexec.c \ - sudo_edit.c sudo_nss.c term.c testsudoers.c tgetpass.c toke.c toke.l \ - toke_util.c tsgetgrpw.c utimes.c vasgroups.c visudo.c zero_bytes.c \ - redblack.c selinux.c sesh.c sudoreplay.c getdate.c getdate.y getline.c \ - timestr.c $(AUTH_SRCS) - -AUTH_SRCS = auth/afs.c auth/aix_auth.c auth/bsdauth.c auth/dce.c auth/fwtk.c \ - auth/kerb4.c auth/kerb5.c auth/pam.c auth/passwd.c auth/rfc1938.c \ - auth/secureware.c auth/securid.c auth/securid5.c auth/sia.c \ - auth/sudo_auth.c - -HDRS = alloc.h bsm_audit.h def_data.h defaults.h error.h ins_2001.h \ - ins_classic.h ins_csops.h ins_goons.h insults.h interfaces.h lbuf.h \ - linux_audit.h list.h logging.h missing.h mksiglist.h nonunix.h \ - redblack.h parse.h sudo.h sudo_exec.h sudo_nss.h gram.h toke.h \ - auth/sudo_auth.h emul/charclass.h emul/fnmatch.h emul/glob.h \ - emul/timespec.h emul/utime.h - -AUTH_OBJS = sudo_auth.o @AUTH_OBJS@ - -COMMON_OBJS = alias.o alloc.o defaults.o error.o gram.o \ - list.o match.o pwutil.o timestr.o toke.o toke_util.o redblack.o \ - term.o zero_bytes.o @COMMON_OBJS@ - -SUDO_OBJS = $(AUTH_OBJS) @SUDO_OBJS@ audit.o boottime.o check.o env.o \ - exec.o gettime.o goodpath.o fileops.o find_path.o \ - interfaces.o lbuf.o logging.o parse.o parse_args.o set_perms.o \ - sudo.o sudo_edit.o sudo_nss.o tgetpass.o - -VISUDO_OBJS = visudo.o fileops.o gettime.o goodpath.o find_path.o +SUBDIRS = compat common @ZLIB_SRC@ plugins/sudoers src include doc -REPLAY_OBJS = getdate.o sudoreplay.o - -TEST_OBJS = interfaces.o testsudoers.o tsgetgrpw.o - -LIB_OBJS = @LIBOBJS@ - -ZLIB_OBJS = adler32.o compress.o crc32.o deflate.o gzclose.o gzlib.o \ - gzread.o gzwrite.o infback.o inffast.o inflate.o inftrees.o \ - trees.o uncompr.o zutil.o +SAMPLES = plugins/sample plugins/sample_group VERSION = @PACKAGE_VERSION@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ -DISTFILES = $(SRCS) $(HDRS) ChangeLog HISTORY INSTALL INSTALL.configure \ - LICENSE Makefile.in NEWS PORTING README README.LDAP \ - TROUBLESHOOTING UPGRADE aclocal.m4 aixcrypt.exp config.guess \ - config.h.in config.sub configure configure.in def_data.in \ - indent.pro install-sh ltmain.sh m4 mkdefaults mkinstalldirs \ - mkpkg pathnames.h.in pp sample.pam sample.syslog.conf \ - sample.sudoers schema.ActiveDirectory schema.OpenLDAP \ - schema.iPlanet siglist.in sudo.cat sudo.man.in sudo.pod sudo.pp \ - sudo_usage.h.in sudoers.in sudoers.cat sudoers.man.in sudoers.pod \ - sudoers.ldap.cat sudoers.ldap.man.in sudoers.ldap.pod \ - sudoers2ldif sudoreplay.cat sudoreplay.man.in sudoreplay.pod \ - visudo.cat visudo.man.in visudo.pod auth/API sudo.man.pl \ - sudoers.man.pl $(ZLIB_FILES) - -ZLIB_FILES = zlib/adler32.c zlib/compress.c zlib/crc32.c zlib/crc32.h \ - zlib/deflate.c zlib/deflate.h zlib/gzclose.c zlib/gzguts.h \ - zlib/gzlib.c zlib/gzread.c zlib/gzwrite.c zlib/infback.c \ - zlib/inffast.c zlib/inffast.h zlib/inffixed.h zlib/inflate.c \ - zlib/inflate.h zlib/inftrees.c zlib/inftrees.h zlib/trees.c \ - zlib/trees.h zlib/uncompr.c zlib/zconf.h.in zlib/zlib.h \ - zlib/zutil.c zlib/zutil.h - -SUDODEP = $(srcdir)/sudo.h $(srcdir)/alloc.h $(srcdir)/defaults.h \ - $(srcdir)/error.h $(srcdir)/list.h $(srcdir)/logging.h \ - $(srcdir)/missing.h $(srcdir)/sudo_nss.h $(devdir)/def_data.h \ - pathnames.h config.h - -AUTHDEP = $(SUDODEP) $(authdir)/sudo_auth.h - -INSDEP = $(srcdir)/ins_2001.h $(srcdir)/ins_classic.h $(srcdir)/ins_csops.h \ - $(srcdir)/ins_goons.h $(srcdir)/insults.h - -all: $(PROGS) - -.SUFFIXES: .o .c .h .l .y .lo - -.c.o: - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $< - -.c.lo: - $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $< - -libsudo.a: $(LIB_OBJS) $(COMMON_OBJS) - $(AR) rv $@ $(LIB_OBJS) $(COMMON_OBJS) - $(RANLIB) $@ - -libz.a: $(ZLIB_OBJS) - $(AR) rv $@ $(ZLIB_OBJS) - $(RANLIB) $@ - -sudo: libsudo.a @ZLIB_DEP@ $(SUDO_OBJS) - $(CC) -o $@ $(SUDO_OBJS) $(SUDO_LDFLAGS) -lsudo $(SUDO_LIBS) @ZLIB@ - -visudo: libsudo.a $(VISUDO_OBJS) - $(CC) -o $@ $(VISUDO_OBJS) $(LDFLAGS) -lsudo $(LIBS) $(NET_LIBS) - -sudoreplay: libsudo.a @ZLIB_DEP@ $(REPLAY_OBJS) - $(CC) -o $@ $(REPLAY_OBJS) $(LDFLAGS) -lsudo $(LIBS) @ZLIB@ - -testsudoers: $(TEST_OBJS) - $(CC) -o $@ $(TEST_OBJS) $(LDFLAGS) -lsudo $(LIBS) $(NET_LIBS) - -sudo_noexec.lo: $(srcdir)/sudo_noexec.c - $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/sudo_noexec.c - -libsudo_noexec.la: sudo_noexec.lo - $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ sudo_noexec.lo -avoid-version -rpath $(noexecdir) - -# Uncomment the following if you want "make distclean" to clean the parser -@DEV@GENERATED = gram.h gram.c toke.c def_data.c def_data.h getdate - -# Uncomment the lines before -@true if you intend to modify gram.y -$(devdir)/gram.c $(devdir)/gram.h: $(srcdir)/gram.y -@DEV@ $(YACC) -d $(srcdir)/gram.y -@DEV@ echo "#include " > $(devdir)/gram.c -@DEV@ cat y.tab.c >> $(devdir)/gram.c -@DEV@ rm -f y.tab.c -@DEV@ mv -f y.tab.h $(devdir)/gram.h - -@true - -# Uncomment the lines before -@true if you intend to modify toke.l -$(devdir)/toke.c: $(srcdir)/toke.l -@DEV@ $(FLEX) $(srcdir)/toke.l -@DEV@ echo "#include " > $(devdir)/toke.c -@DEV@ cat lex.yy.c >> $(devdir)/toke.c -@DEV@ rm -f lex.yy.c - -@true - -# Uncomment the lines before -@true if you intend to modify getdate.y -$(devdir)/getdate.c: $(srcdir)/getdate.y -@DEV@ echo "expect 10 shift/reduce conflicts" -@DEV@ $(YACC) $(srcdir)/getdate.y -@DEV@ echo "#include " > $(devdir)/getdate.c -@DEV@ cat y.tab.c >> $(devdir)/getdate.c -@DEV@ rm -f y.tab.c - -@true - -# Uncomment the following if you intend to modify def_data.in -@DEV@$(devdir)/def_data.h $(devdir)/def_data.c: $(srcdir)/def_data.in -@DEV@ perl $(srcdir)/mkdefaults -o def_data $(srcdir)/def_data.in +LIBTOOL_DEPS = @LIBTOOL_DEPS@ -siglist.c: mksiglist - ./mksiglist > $@ - -mksiglist: $(srcdir)/mksiglist.c $(srcdir)/mksiglist.h $(srcdir)/missing.h config.h - $(CC) $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/mksiglist.c -o $@ - -@DEV@$(srcdir)/mksiglist.h: $(srcdir)/siglist.in -@DEV@ awk 'BEGIN {print "/* public domain */\n"} /^ [A-Z]/ {printf("#ifdef SIG%s\n if (my_sys_siglist[SIG%s] == NULL)\n\tmy_sys_siglist[SIG%s] = \"%s\";\n#endif\n", $$1, $$1, $$1, substr($$0, 13))}' < $(srcdir)/siglist.in > $@ - -# Dependencies (not counting auth functions) -aix.o: $(srcdir)/aix.c - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/aix.c -alias.o: $(srcdir)/alias.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(srcdir)/redblack.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/alias.c -alloc.o: $(srcdir)/alloc.c $(SUDODEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/alloc.c -audit.o: $(srcdir)/audit.c $(SUDODEP) $(srcdir)/bsm_audit.h $(srcdir)/linux_audit.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/audit.c -boottime.o: $(srcdir)/boottime.c config.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/boottime.c -bsm_audit.o: $(srcdir)/bsm_audit.c $(SUDODEP) $(srcdir)/bsm_audit.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/bsm_audit.c -check.o: $(srcdir)/check.c $(SUDODEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/check.c -closefrom.o: $(srcdir)/closefrom.c config.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/closefrom.c -defaults.o: $(srcdir)/defaults.c $(SUDODEP) $(srcdir)/def_data.c $(authdir)/sudo_auth.h $(devdir)/gram.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/defaults.c -env.o: $(srcdir)/env.c $(SUDODEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/env.c -error.o: $(srcdir)/error.c $(srcdir)/missing.h $(srcdir)/error.h config.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/error.c -exec.o: $(srcdir)/exec.c $(SUDODEP) $(srcdir)/sudo_exec.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/exec.c -exec_pty.o: $(srcdir)/exec.c $(SUDODEP) $(srcdir)/sudo_exec.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/exec_pty.c -fileops.o: $(srcdir)/fileops.c $(SUDODEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/fileops.c -find_path.o: $(srcdir)/find_path.c $(SUDODEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/find_path.c -fnmatch.o: $(srcdir)/fnmatch.c $(srcdir)/emul/fnmatch.h $(srcdir)/missing.h config.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/fnmatch.c -get_pty.o: $(srcdir)/get_pty.c $(SUDODEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/get_pty.c -getcwd.o: $(srcdir)/getcwd.c $(srcdir)/missing.h config.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/getcwd.c -getdate.o: $(srcdir)/getdate.c $(srcdir)/missing.h config.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/getdate.c -getline.o: $(srcdir)/getline.c config.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/getline.c -getprogname.o: $(srcdir)/getprogname.c config.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/getprogname.c -getspwuid.o: $(srcdir)/getspwuid.c $(SUDODEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/getspwuid.c -gettime.o: $(srcdir)/gettime.c $(SUDODEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/gettime.c -glob.o: $(srcdir)/glob.c $(srcdir)/emul/glob.h $(srcdir)/missing.h config.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/glob.c -goodpath.o: $(srcdir)/goodpath.c $(SUDODEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/goodpath.c -gram.o: $(devdir)/gram.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(devdir)/gram.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(devdir)/gram.c -interfaces.o: $(srcdir)/interfaces.c $(SUDODEP) $(srcdir)/interfaces.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/interfaces.c -iolog.o: $(srcdir)/iolog.c $(SUDODEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/iolog.c -isblank.o: $(srcdir)/isblank.c $(srcdir)/missing.h config.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/isblank.c -lbuf.o: $(srcdir)/lbuf.c $(SUDODEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/lbuf.c -ldap.o: $(srcdir)/ldap.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/ldap.c -linux_audit.o: $(srcdir)/linux_audit.c $(SUDODEP) $(srcdir)/linux_audit.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/linux_audit.c -list.o: $(srcdir)/list.c $(SUDODEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/list.c -logging.o: $(srcdir)/logging.c $(SUDODEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/logging.c -match.o: $(srcdir)/match.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(srcdir)/interfaces.h $(devdir)/gram.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/match.c -memrchr.o: $(srcdir)/memrchr.c $(SUDODEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/memrchr.c -mkstemps.o: $(srcdir)/mkstemps.c $(SUDODEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/mkstemps.c -nanosleep.o: $(srcdir)/nanosleep.c $(srcdir)/missing.h config.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/nanosleep.c -parse.o: $(srcdir)/parse.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(devdir)/gram.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/parse.c -parse_args.o: $(srcdir)/parse_args.c $(SUDODEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/parse_args.c -pwutil.o: $(srcdir)/pwutil.c $(SUDODEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/pwutil.c -redblack.o: $(srcdir)/redblack.c $(SUDODEP) $(srcdir)/redblack.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/redblack.c -set_perms.o: $(srcdir)/set_perms.c $(SUDODEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/set_perms.c -setsid.o: $(srcdir)/setsid.c $(srcdir)/missing.h config.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/setsid.c -sigaction.o: $(srcdir)/sigaction.c $(srcdir)/missing.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/sigaction.c -siglist.o: siglist.c $(srcdir)/missing.h config.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/siglist.c -snprintf.o: $(srcdir)/snprintf.c $(srcdir)/missing.h config.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/snprintf.c -strcasecmp.o: $(srcdir)/strcasecmp.c $(srcdir)/missing.h config.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/strcasecmp.c -strerror.o: $(srcdir)/strerror.c $(srcdir)/missing.h config.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/strerror.c -strlcat.o: $(srcdir)/strlcat.c $(srcdir)/missing.h config.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/strlcat.c -strlcpy.o: $(srcdir)/strlcpy.c $(srcdir)/missing.h config.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/strlcpy.c -strsignal.o: $(srcdir)/strsignal.c $(srcdir)/missing.h config.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/strsignal.c -selinux.o: $(srcdir)/selinux.c $(SUDODEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/selinux.c -sudo.o: $(srcdir)/sudo.c $(SUDODEP) sudo_usage.h $(srcdir)/interfaces.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/sudo.c -sudoreplay.o: $(srcdir)/sudoreplay.c $(srcdir)/alloc.h $(srcdir)/missing.h $(srcdir)/error.h $(srcdir)/missing.h config.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/sudoreplay.c -sudo_edit.o: $(srcdir)/sudo_edit.c $(SUDODEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/sudo_edit.c -sudo_noexec.o: $(srcdir)/sudo_noexec.c $(srcdir)/missing.h config.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/sudo_noexec.c -sudo_nss.o: $(srcdir)/sudo_nss.c $(SUDODEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/sudo_nss.c -term.o: $(srcdir)/term.c $(SUDODEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/term.c -testsudoers.o: $(srcdir)/testsudoers.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(srcdir)/interfaces.h $(devdir)/gram.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/testsudoers.c -tgetpass.o: $(srcdir)/tgetpass.c $(SUDODEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/tgetpass.c -timestr.o: $(srcdir)/timestr.c $(srcdir)/missing.h config.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/timestr.c -toke.o: $(devdir)/toke.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(srcdir)/toke.h $(devdir)/gram.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(devdir)/toke.c -toke_util.o: $(srcdir)/toke_util.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/list.h $(srcdir)/toke.h $(devdir)/gram.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/toke_util.c -tsgetgrpw.o: $(srcdir)/tsgetgrpw.c $(SUDODEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/tsgetgrpw.c -utimes.o: $(srcdir)/utimes.c $(srcdir)/missing.h $(srcdir)/emul/utime.h config.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/utimes.c -vasgroups.o: $(srcdir)/vasgroups.c $(srcdir)/nonunix.h $(SUDODEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/vasgroups.c -visudo.o: $(srcdir)/visudo.c $(SUDODEP) $(devdir)/gram.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/visudo.c -zero_bytes.o: $(srcdir)/zero_bytes.c $(srcdir)/missing.h config.h - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(srcdir)/zero_bytes.c -sudo_auth.o: $(authdir)/sudo_auth.c $(AUTHDEP) $(INSDEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(authdir)/sudo_auth.c -afs.o: $(authdir)/afs.c $(AUTHDEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(authdir)/afs.c -aix_auth.o: $(authdir)/aix_auth.c $(AUTHDEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(authdir)/aix_auth.c -bsdauth.o: $(authdir)/bsdauth.c $(AUTHDEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(authdir)/bsdauth.c -dce.o: $(authdir)/dce.c $(AUTHDEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(authdir)/dce.c -fwtk.o: $(authdir)/fwtk.c $(AUTHDEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(authdir)/fwtk.c -kerb4.o: $(authdir)/kerb4.c $(AUTHDEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(authdir)/kerb4.c -kerb5.o: $(authdir)/kerb5.c $(AUTHDEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(authdir)/kerb5.c -pam.o: $(authdir)/pam.c $(AUTHDEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(authdir)/pam.c -passwd.o: $(authdir)/passwd.c $(AUTHDEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(authdir)/passwd.c -rfc1938.o: $(authdir)/rfc1938.c $(AUTHDEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(authdir)/rfc1938.c -secureware.o: $(authdir)/secureware.c $(AUTHDEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(authdir)/secureware.c -securid.o: $(authdir)/securid.c $(AUTHDEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(authdir)/securid.c -securid5.o: $(authdir)/securid5.c $(AUTHDEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(authdir)/securid5.c -sia.o: $(authdir)/sia.c $(AUTHDEP) - $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(OPTIONS) $(authdir)/sia.c - -# Zlib dependencies -adler32.o: $(srcdir)/zlib/zutil.h $(srcdir)/zlib/zlib.h zlib/zconf.h - $(CC) -c -I. -I$(srcdir)/zlib $(CFLAGS) $(srcdir)/zlib/adler32.c -compress.o: $(srcdir)/zlib/zlib.h zlib/zconf.h - $(CC) -c -I. -I$(srcdir)/zlib $(CFLAGS) $(srcdir)/zlib/compress.c -crc32.o: $(srcdir)/zlib/zutil.h $(srcdir)/zlib/zlib.h zlib/zconf.h $(srcdir)/zlib/crc32.h - $(CC) -c -I. -I$(srcdir)/zlib $(CFLAGS) $(srcdir)/zlib/crc32.c -deflate.o: $(srcdir)/zlib/deflate.h $(srcdir)/zlib/zutil.h $(srcdir)/zlib/zlib.h zlib/zconf.h - $(CC) -c -I. -I$(srcdir)/zlib $(CFLAGS) $(srcdir)/zlib/deflate.c -gzclose.o: $(srcdir)/zlib/zlib.h zlib/zconf.h $(srcdir)/zlib/gzguts.h - $(CC) -c -I. -I$(srcdir)/zlib $(CFLAGS) $(srcdir)/zlib/gzclose.c -gzlib.o: $(srcdir)/zlib/zlib.h zlib/zconf.h $(srcdir)/zlib/gzguts.h - $(CC) -c -I. -I$(srcdir)/zlib $(CFLAGS) $(srcdir)/zlib/gzlib.c -gzread.o: $(srcdir)/zlib/zlib.h zlib/zconf.h $(srcdir)/zlib/gzguts.h - $(CC) -c -I. -I$(srcdir)/zlib $(CFLAGS) $(srcdir)/zlib/gzread.c -gzwrite.o: $(srcdir)/zlib/zlib.h zlib/zconf.h $(srcdir)/zlib/gzguts.h - $(CC) -c -I. -I$(srcdir)/zlib $(CFLAGS) $(srcdir)/zlib/gzwrite.c -infback.o: $(srcdir)/zlib/zutil.h $(srcdir)/zlib/zlib.h zlib/zconf.h $(srcdir)/zlib/inftrees.h $(srcdir)/zlib/inflate.h $(srcdir)/zlib/inffast.h $(srcdir)/zlib/inffixed.h - $(CC) -c -I. -I$(srcdir)/zlib $(CFLAGS) $(srcdir)/zlib/infback.c -inffast.o: $(srcdir)/zlib/zutil.h $(srcdir)/zlib/zlib.h zlib/zconf.h $(srcdir)/zlib/inftrees.h $(srcdir)/zlib/inflate.h $(srcdir)/zlib/inffast.h - $(CC) -c -I. -I$(srcdir)/zlib $(CFLAGS) $(srcdir)/zlib/inffast.c -inflate.o: $(srcdir)/zlib/zutil.h $(srcdir)/zlib/zlib.h zlib/zconf.h $(srcdir)/zlib/inftrees.h $(srcdir)/zlib/inflate.h $(srcdir)/zlib/inffast.h $(srcdir)/zlib/inffixed.h - $(CC) -c -I. -I$(srcdir)/zlib $(CFLAGS) $(srcdir)/zlib/inflate.c -inftrees.o: $(srcdir)/zlib/zutil.h $(srcdir)/zlib/zlib.h zlib/zconf.h $(srcdir)/zlib/inftrees.h - $(CC) -c -I. -I$(srcdir)/zlib $(CFLAGS) $(srcdir)/zlib/inftrees.c -trees.o: $(srcdir)/zlib/deflate.h $(srcdir)/zlib/zutil.h $(srcdir)/zlib/zlib.h zlib/zconf.h $(srcdir)/zlib/trees.h - $(CC) -c -I. -I$(srcdir)/zlib $(CFLAGS) $(srcdir)/zlib/trees.c -uncompr.o: $(srcdir)/zlib/zlib.h zlib/zconf.h - $(CC) -c -I. -I$(srcdir)/zlib $(CFLAGS) $(srcdir)/zlib/uncompr.c -zutil.o: $(srcdir)/zlib/zutil.h $(srcdir)/zlib/zlib.h zlib/zconf.h - $(CC) -c -I. -I$(srcdir)/zlib $(CFLAGS) $(srcdir)/zlib/zutil.c - -@DEV@varsub: $(srcdir)/configure.in -@DEV@ printf 's#@%s@#1#\ns#@%s@#1#\ns#@%s@#1#\ns#@%s@#/etc#g\ns#@%s@#/usr/local#g\ns#@%s@#4#g\ns#@%s@#1m#g\n' SEMAN BAMAN LCMAN sysconfdir prefix mansectform mansectsu > $@; sed -n '/Begin initial values for man page substitution/,/End initial values for man page substitution/{;p;}' $(srcdir)/configure.in | sed -e '/^#/d' -e 's/^/s#@/' -e 's/=[\\"]*/@#/' -e 's/[\\"]*$$/#g/' >> $@ - -@DEV@$(srcdir)/sudo.man.in: $(srcdir)/sudo.pod -@DEV@ mansectsu=`echo @MANSECTSU@|tr A-Z a-z`; mansectform=`echo @MANSECTFORM@|tr A-Z a-z`; sed -n -e '/^=pod/q' -e 's/^/.\\" /p' $(srcdir)/sudo.pod > $@; pod2man --quotes=none --date="`date '+%B %e, %Y'`" --section=$$mansectsu --release=$(VERSION) --center="MAINTENANCE COMMANDS" $(srcdir)/sudo.pod | sed -e "s/(5)/($$mansectform)/" -e "s/(8)/($$mansectsu)/" | perl -p $(srcdir)/sudo.man.pl >> $@ - -sudo.man: $(srcdir)/sudo.man.in - $(SHELL) config.status --file=$@ - -@DEV@$(srcdir)/sudo.cat: varsub $(srcdir)/sudo.man.in -@DEV@ sed -f varsub $(srcdir)/sudo.man.in | $(NROFF) -man > $@ - -@DEV@$(srcdir)/visudo.man.in: $(srcdir)/visudo.pod -@DEV@ mansectsu=`echo @MANSECTSU@|tr A-Z a-z`; mansectform=`echo @MANSECTFORM@|tr A-Z a-z`; sed -n -e '/^=pod/q' -e 's/^/.\\" /p' $(srcdir)/visudo.pod > $@; pod2man --quotes=none --date="`date '+%B %e, %Y'`" --section=$$mansectsu --release=$(VERSION) --center="MAINTENANCE COMMANDS" $(srcdir)/visudo.pod | sed -e "s/(5)/($$mansectform)/" -e "s/(8)/($$mansectsu)/" -e 's|\\fI\\f\((CW*\)*I@\([^@]*\)\\fI@|\\fI@\2@|g' >> $@ - -visudo.man: $(srcdir)/visudo.man.in - $(SHELL) config.status --file=$@ - -@DEV@$(srcdir)/visudo.cat: varsub $(srcdir)/visudo.man.in -@DEV@ sed -f varsub $(srcdir)/visudo.man.in | $(NROFF) -man > $@ - -@DEV@$(srcdir)/sudoers.man.in: $(srcdir)/sudoers.pod -@DEV@ mansectsu=`echo @MANSECTSU@|tr A-Z a-z`; mansectform=`echo @MANSECTFORM@|tr A-Z a-z`; sed -n -e '/^=pod/q' -e 's/^/.\\" /p' $(srcdir)/sudoers.pod > $@; pod2man --quotes=none --date="`date '+%B %e, %Y'`" --section=$$mansectform --release=$(VERSION) --center="MAINTENANCE COMMANDS" $(srcdir)/sudoers.pod | sed -e "s/(5)/($$mansectform)/" -e "s/(8)/($$mansectsu)/" | perl -p $(srcdir)/sudoers.man.pl >> $@ - -sudoers.man: $(srcdir)/sudoers.man.in - $(SHELL) config.status --file=$@ - -@DEV@$(srcdir)/sudoers.cat: varsub $(srcdir)/sudoers.man.in -@DEV@ sed -f varsub $(srcdir)/sudoers.man.in | $(NROFF) -man > $@ - -@DEV@$(srcdir)/sudoers.ldap.man.in: $(srcdir)/sudoers.ldap.pod -@DEV@ mansectsu=`echo @MANSECTSU@|tr A-Z a-z`; mansectform=`echo @MANSECTFORM@|tr A-Z a-z`; sed -n -e '/^=pod/q' -e 's/^/.\\" /p' $(srcdir)/sudoers.ldap.pod > $@; pod2man --quotes=none --date="`date '+%B %e, %Y'`" --section=$$mansectform --release=$(VERSION) --center="MAINTENANCE COMMANDS" $(srcdir)/sudoers.ldap.pod | sed -e "s/(5)/($$mansectform)/" -e "s/(8)/($$mansectsu)/" -e 's|\\fI\\f\((CW*\)*I@\([^@]*\)\\fI@|\\fI@\2@|g' >> $@ - -sudoers.ldap.man: $(srcdir)/sudoers.ldap.man.in - $(SHELL) config.status --file=$@ - -@DEV@$(srcdir)/sudoers.ldap.cat: varsub $(srcdir)/sudoers.ldap.man.in -@DEV@ sed -f varsub $(srcdir)/sudoers.ldap.man.in | $(NROFF) -man > $@ - -@DEV@$(srcdir)/sudoreplay.man.in: $(srcdir)/sudoreplay.pod -@DEV@ mansectsu=`echo @MANSECTSU@|tr A-Z a-z`; mansectform=`echo @MANSECTFORM@|tr A-Z a-z`; sed -n -e '/^=pod/q' -e 's/^/.\\" /p' $(srcdir)/sudoreplay.pod > $@; pod2man --quotes=none --date="`date '+%B %e, %Y'`" --section=$$mansectsu --release=$(VERSION) --center="MAINTENANCE COMMANDS" $(srcdir)/sudoreplay.pod | sed -e "s/(5)/($$mansectform)/" -e "s/(8)/($$mansectsu)/" -e 's|\\fI\\f\((CW*\)*I@\([^@]*\)\\fI@|\\fI@\2@|g' >> $@ - -sudoreplay.man: $(srcdir)/sudoreplay.man.in - $(SHELL) config.status --file=$@ - -@DEV@$(srcdir)/sudoreplay.cat: varsub $(srcdir)/sudoreplay.man.in -@DEV@ sed -f varsub $(srcdir)/sudoreplay.man.in | $(NROFF) -man > $@ - -@DEV@HISTORY: $(srcdir)/history.pod -@DEV@ pod2text -l -i0 $(srcdir)/history.pod > $@ -@DEV@ -@DEV@LICENSE: $(srcdir)/license.pod -@DEV@ pod2text -l -i0 $(srcdir)/license.pod | sed '1,2d' > $@ - -sudoers: $(srcdir)/sudoers.in - (cd $(top_builddir) && $(SHELL) config.status --file=plugins/sudoers/$@) +SHELL = @SHELL@ -# The 1.7 branch started Jan 18, 2010 +all: config.status + for d in $(SUBDIRS) $(SAMPLES); \ + do (cd $$d && exec $(MAKE) $@) && continue; \ + exit $$?; \ + done + +check pre-install: config.status + for d in $(SUBDIRS); \ + do (cd $$d && exec $(MAKE) $@) && continue; \ + exit $$?; \ + done + +install-dirs install-binaries install-includes install-plugin uninstall: config.status pre-install + for d in $(SUBDIRS); \ + do (cd $$d && exec $(MAKE) $@) && continue; \ + exit $$?; \ + done + +install install-doc: config.status ChangeLog pre-install + for d in $(SUBDIRS); \ + do (cd $$d && exec $(MAKE) $@) && continue; \ + exit $$?; \ + done + +autoconf: + autoconf -I m4 + +# The 1.8 branch started February 25, 2011 ChangeLog: if test -d $(srcdir)/.hg && cd $(srcdir); then \ - if hg log --style=changelog -b 1.7 > $@.tmp && hg log --style=changelog -b default --date '<2010-01-18 00:00:00' >> $@.tmp; then \ + if hg log --style=changelog -b 1.8 > $@.tmp && hg log --style=changelog -b default --date '<2011-02-25 21:30:00' >> $@.tmp; then \ mv -f $@.tmp $@; \ else \ rm -f $@.tmp; \ fi; \ fi -pre-install: - @if test -r $(DESTDIR)$(sudoersdir)/sudoers; then \ - echo "Checking existing sudoers file for syntax errors."; \ - ./visudo -c -f $(DESTDIR)$(sudoersdir)/sudoers; \ +config.status: + @if [ ! -s config.status ]; then \ + echo "Please run configure first"; \ + exit 1; \ fi -install: pre-install install-dirs install-binaries @INSTALL_NOEXEC@ install-sudoers install-doc - -install-dirs: - $(SHELL) $(srcdir)/mkinstalldirs $(DESTDIR)$(sudodir) \ - $(DESTDIR)$(visudodir) $(DESTDIR)$(noexecdir) \ - $(DESTDIR)$(sudoersdir) $(DESTDIR)$(docdir) \ - $(DESTDIR)$(mandirsu) $(DESTDIR)$(mandirform) - $(SHELL) $(srcdir)/mkinstalldirs -m 0700 $(DESTDIR)$(timedir) +libtool: $(LIBTOOL_DEPS) + $(SHELL) ./config.status --recheck -install-binaries: install-dirs $(PROGS) - $(INSTALL) -b~ -O $(install_uid) -G $(install_gid) -M 04111 sudo $(DESTDIR)$(sudodir)/sudo - rm -f $(DESTDIR)$(sudodir)/sudoedit - ln $(DESTDIR)$(sudodir)/sudo $(DESTDIR)$(sudodir)/sudoedit - if [ -f sudoreplay ]; then $(INSTALL) -b~ -O $(install_uid) -G $(install_gid) -M 0111 sudoreplay $(DESTDIR)$(sudodir)/sudoreplay; fi - $(INSTALL) -b~ -O $(install_uid) -G $(install_gid) -M 0111 visudo $(DESTDIR)$(visudodir)/visudo - if [ -f sesh ]; then $(INSTALL) -b~ -O $(install_uid) -G $(install_gid) -M 0111 sesh $(DESTDIR)$(libexecdir)/sesh; fi +Makefile: $(srcdir)/Makefile.in + ./config.status --file Makefile -install-noexec: install-dirs libsudo_noexec.la - if [ -f .libs/lib$(noexecfile) ]; then $(INSTALL) -b~ -O $(install_uid) -G $(install_gid) -M 0755 .libs/lib$(noexecfile) $(DESTDIR)$(noexecdir)/$(noexecfile); fi - -install-sudoers: install-dirs - $(INSTALL) -d -O $(sudoers_uid) -G $(sudoers_gid) -M 0750 \ - $(DESTDIR)$(sudoersdir)/sudoers.d - test -f $(DESTDIR)$(sudoersdir)/sudoers || \ - $(INSTALL) -O $(sudoers_uid) -G $(sudoers_gid) -M $(sudoers_mode) \ - sudoers $(DESTDIR)$(sudoersdir)/sudoers - -install-doc: install-dirs ChangeLog - (cd $(srcdir) && for f in ChangeLog HISTORY LICENSE NEWS README TROUBLESHOOTING UPGRADE sample.*; do $(INSTALL) -O $(install_uid) -G $(install_gid) -M 0444 $$f $(DESTDIR)$(docdir); done) - @LDAP@(cd $(srcdir) && for f in README.LDAP schema.* sudoers2ldif; do $(INSTALL) -O $(install_uid) -G $(install_gid) -M 0444 $$f $(DESTDIR)$(docdir); done) - $(INSTALL) -O $(install_uid) -G $(install_gid) -M 0444 @mansrcdir@/sudo.$(mantype) $(DESTDIR)$(mandirsu)/sudo.$(mansectsu) - @rm -f $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu) - ln $(DESTDIR)$(mandirsu)/sudo.$(mansectsu) $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu) - @REPLAY@$(INSTALL) -O $(install_uid) -G $(install_gid) -M 0444 @mansrcdir@/sudoreplay.$(mantype) $(DESTDIR)$(mandirsu)/sudoreplay.$(mansectsu) - $(INSTALL) -O $(install_uid) -G $(install_gid) -M 0444 @mansrcdir@/visudo.$(mantype) $(DESTDIR)$(mandirsu)/visudo.$(mansectsu) - $(INSTALL) -O $(install_uid) -G $(install_gid) -M 0444 @mansrcdir@/sudoers.$(mantype) $(DESTDIR)$(mandirform)/sudoers.$(mansectform) - @LDAP@$(INSTALL) -O $(install_uid) -G $(install_gid) -M 0444 @mansrcdir@/sudoers.ldap.$(mantype) $(DESTDIR)$(mandirform)/sudoers.ldap.$(mansectform) -@MAN_POSTINSTALL@ - -check: - @echo nothing to check - -clean: - -rm -f *.a *.o *.lo stamp-* varsub $(PROGS) testsudoers core *.core core.* - -mostlyclean: clean - -distclean: clean - -rm -rf Makefile pathnames.h config.h config.status config.cache \ - config.log libtool sudoers sudo_noexec.lo .libs $(GENERATED) \ - sudo.man sudoers.man sudoers.ldap.man sudoreplay.man \ - visudo.man sudo_usage.h Makefile.binary zlib/zconf.h - -clobber: distclean - -realclean: distclean - rm -f TAGS tags - -cleandir: realclean - -dist: ChangeLog +dist: ChangeLog $(srcdir)/MANIFEST pax -w -x ustar -s '/^/$(PACKAGE_TARNAME)-$(VERSION)\//' \ - -f ../$(PACKAGE_TARNAME)-$(VERSION).tar $(DISTFILES) + -f ../$(PACKAGE_TARNAME)-$(VERSION).tar \ + `sed 's/[ ].*//' $(srcdir)/MANIFEST` gzip -9f ../$(PACKAGE_TARNAME)-$(VERSION).tar ls -l ../$(PACKAGE_TARNAME)-$(VERSION).tar.gz @@ -616,6 +116,7 @@ package: sudo.pp bindir=$(bindir) \ sbindir=$(sbindir) \ libexecdir=$(libexecdir) \ + includedir=$(includedir) \ timedir=$(timedir) \ mandir=$(mandir) \ docdir=$(docdir) \ @@ -626,4 +127,24 @@ package: sudo.pp sudoers_mode=$(sudoers_mode) \ version=$(VERSION) $(PPVARS) -.PHONY: ChangeLog +clean: config.status + for d in $(SUBDIRS) $(SAMPLES); do \ + (cd $$d && exec $(MAKE) $@); \ + done + +mostlyclean: clean + +distclean: config.status + for d in $(SUBDIRS) $(SAMPLES); do \ + (cd $$d && exec $(MAKE) $@); \ + done + -rm -rf Makefile pathnames.h config.h config.status config.cache \ + config.log libtool stamp-* autom4te.cache + +cleandir: distclean + +clobber: distclean + +realclean: distclean + +.PHONY: ChangeLog diff --git a/NEWS b/NEWS index 87bac52..729ad66 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,19 @@ -What's new in Sudo 1.7.6p1 +What's new in Sudo 1.8.1p2? + + * Two-character CIDR-style IPv4 netmasks are now matched correctly + in the sudoers file. + + * A build error with MIT Kerberos V has been resolved. + + * A crash on HP-UX in the sudoers plugin when wildcards are + present in the sudoers file has been resolved. + + * Sudo now works correctly on Tru64 Unix again. + +What's new in Sudo 1.8.1p1? + + * Fixed a problem on AIX where sudo was unable to set the final + uid if the PAM module modified the effective uid. * A non-existent includedir is now treated the same as an empty directory and not reported as an error. @@ -6,7 +21,9 @@ What's new in Sudo 1.7.6p1 * Removed extraneous parens in LDAP filter when sudoers_search_filter is enabled that can cause an LDAP search error. -What's new in Sudo 1.7.6? + * Fixed a "make -j" problem for "make install". + +What's new in Sudo 1.8.1? * A new LDAP setting, sudoers_search_filter, has been added to ldap.conf. This setting can be used to restrict the set of @@ -32,6 +49,62 @@ What's new in Sudo 1.7.6? * A bug that could result in corrupted output in "sudo -l" has been fixed. + * Sudo will now create an entry in the utmp (or utmpx) file when + allocating a pseudo-tty (e.g. when logging I/O). The "set_utmp" + and "utmp_runas" sudoers file options can be used to control this. + Other policy plugins may use the "set_utmp" and "utmp_user" + entries in the command_info list. + + * The sudoers policy now stores the TSID field in the logs + even when the "iolog_file" sudoers option is defined to a value + other than %{sessid}. Previously, the TSID field was only + included in the log file when the "iolog_file" option was set + to its default value. + + * The sudoreplay utility now supports arbitrary session IDs. + Previously, it would only work with the base-36 session IDs + that the sudoers plugin uses by default. + + * Sudo now passes "run_shell=true" to the policy plugin in the + settings list when sudo's -s command line option is specified. + The sudoers policy plugin uses this to implement the "set_home" + sudoers option which was missing from sudo 1.8.0. + + * The "noexec" functionality has been moved out of the sudoers + policy plugin and into the sudo front-end, which matches the + behavior documented in the plugin writer's guide. As a result, + the path to the noexec file is now specified in the sudo.conf + file instead of the sudoers file. + + * On Solaris 10, the PRIV_PROC_EXEC privilege is now used to + implement the "noexec" feature. Previously, this was implemented + via the LD_PRELOAD environment variable. + + * The exit values for "sudo -l", "sudo -v" and "sudo -l command" + have been fixed in the sudoers policy plugin. + + * The sudoers policy plugin now passes the login class, if any, + back to the sudo front-end. + + * The sudoers policy plugin was not being linked with requisite + libraries in certain configurations. + + * Sudo now parses command line arguments before loading any plugins. + This allows "sudo -V" or "sudo -h" to work even if there is a problem + with sudo.conf + + * Plugins are now linked with the static version of libgcc to allow + the plugin to run on a system where no shared libgcc is installed, + or where it is installed in a different location. + +What's new in Sudo 1.8.0? + + * Sudo has been refactored to use a modular framework that can + support third-party policy and I/O logging plugins. The default + plugin is "sudoers" which provides the traditional sudo functionality. + See the sudo_plugin manual for details on the plugin API and the + sample in the plugins directory for a simple example. + What's new in Sudo 1.7.5? * When using visudo in check mode, a file named "-" may be used to diff --git a/PORTING b/PORTING deleted file mode 100644 index 861e0c0..0000000 --- a/PORTING +++ /dev/null @@ -1,85 +0,0 @@ -Sudo porting hints -================== - -Before trying to port sudo to a new architecture, please join the -sudo-workers mailing list (see the README file) and ask if anyone -has a port working or in-progress. Sudo should be fairly easy to -port. Since it uses a configure script, most of the work is often -done for you. As long as your operating system is reasonably POSIX -compliant porting should be easy. If your operating system has a -separate library for POSIX compatibility you may need to add it by -using configure's --with-libraries option. - -If your OS is an SVR4 derivative (or some approximation thereof), it may -be sufficient to tell configure you are runnng SVR4, something like: - configure foo-bar-sysv4 -where foo is the hardware architecture and bar is the vendor. - -A possible pitfall is getdtablesize(2) which is used to get the -maximum number of open files the process can have. If an OS has -the POSIX sysconf(2) it will be used instead of getdtablesize(2). -ulimit(2) or getrlimit(2) can also be used on some OS's. If all -else fails you can use the value of NOFILE in . - -Sudo tries to clear the environment of dangerous environment variables -such as LD_* to prevent shared library spoofing. If you are porting -sudo to a new OS that has shared libraries you'll want to mask out -the variables that allow one to change the shared library path. -See initial_badenv_table() in env.c to see how this is done for -various operating systems. - -It is possible that on a really weird system, tgetpass() may not -compile. (The most common cause for this is that the "fd_set" type -is not defined in a place that sudo expects it to be. If you can -find the header file where "fd_set" is typedef'd, have tgetpass.c -include it and send in a bug report.) -Alternately, tgetpass.c may compile but not work (nothing happens -at the Password: prompt). It is possible that your C library -contains a broken or unusable crypt() function--try linking with --lcrypt if that exists. Another possibility is that select() is -not fully functional; running configure with --with-password-timeout=0 -will disable the use of select(). If sudo prompts you for a -password but never accepts it, see below. - -Sudo detects and recognizes most common shadow password schemes -automatically. If you find that sudo is not accepting your password -and you are sure that it has been typed in correctly there are two -likely problems. One possibility is that your C library has a -broken crypt() function (see above). The other is that your operating -system is using shadow passwords and sudo has not detected that -fact. Look in config.h to see what, if any, shadow password scheme -was detected. The most common are SVR4 (HAVE_GETSPNAM will be -defined) and SecureWare (HAVE_GETPRPWNAM will be defined). Check -the manual pages on your system for "getspnam" and "getprpwnam". -If one of those exist but the appropriate define does not exist in -config.h then the problem is most likely that those routines live -in a library that sudo does not know to link against. The manual -page should tell you what library this is. You can then use the ---with-libraries option to configure to tell sudo to link with the -library in question. For example: - --with-libraries='-lgen' -would cause sudo to link in libgen which contains "getspnam" on SCO -systems. - -If you are trying to port to a system without standard Berkeley -networking you may find that interfaces.c will not compile. This -is most likely on OS's with STREAMS-based networking. It should -be possible to make it work by modifying the ISC streams support -(see the _ISC #ifdef's). However, if you don't care about ip address -and network address support, you can just run configure with the ---without-interfaces flag to get a do-nothing load_interfaces() -stub function. - -Sudo wants POSIX signals (sigaction and friends). If your system -lacks sigaction but has the 4.3BSD sigvec() function, sigvec() will -be used instead via the wrapper functions in sigaction.c. It is -not currently possible to use the old SVR3 and 4.2BSD signals, but -this is due more to my lack of a test machine than anything else. - -If you port sudo to a new architecture, please send the output of -"configure", the config.log file and your changes to: - sudo@courtesan.com - -If you are unable to get sudo working, and you are willing to -give me an account on a machine, send mail to sudo@courtesan.com. -Note, however, that I can't make any promises. diff --git a/README b/README index 387734f..3ed6c5b 100644 --- a/README +++ b/README @@ -1,4 +1,4 @@ -This is Sudo version 1.7.5 +This is Sudo version 1.8.0 The sudo philosophy =================== @@ -27,15 +27,16 @@ summary of major changes to the current stable release, see the web page, http://www.sudo.ws/sudo/stable.html. If you are upgrading from an earlier version of Sudo, please see -the UPGRADE file. +the UPGRADE file in the doc directory. -For a history of sudo please see the HISTORY file. +For a history of sudo please see the HISTORY file in the doc directory. System requirements =================== -To build sudo from the source distribution you need a machine running -Unix (most flavors of BSD, SYSV, or POSIX will do), a working C -compiler, and the ar, make and ranlib utilities. +To build sudo from the source distribution you need a nominally +POSIX-compliant operating system (any modern version of BSD, Linux +or UNIX should work), a working ANSI/ISO C compiler (C89 or higher), +and the ar, make and ranlib utilities If you wish to modify the parser then you will need flex version 2.5.2 or later and either bison or byacc (sudo comes with a pre-flex'd @@ -92,6 +93,7 @@ Bug reports If you have found what you believe to be a bug, you can file a bug report in the sudo bug database, on the web at http://www.sudo.ws/bugs/. -Please read over the `TROUBLESHOOTING' file *before* submitting a bug -report. When reporting bugs, please be sure to include the version of -sudo you are using as well as the platform you are running it on. +Please read over the `TROUBLESHOOTING' file in the doc directory *before* +submitting a bug report. When reporting bugs, please be sure to include +the version of sudo you are using as well as the platform you are running +it on. diff --git a/aclocal.m4 b/aclocal.m4 index 255b91f..e83926c 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -79,6 +79,24 @@ if test X"$found" != X"yes"; then fi ])dnl +dnl +dnl check for utmp file +dnl +AC_DEFUN([SUDO_PATH_UTMP], [AC_MSG_CHECKING([for utmp file path]) +found=no +for p in "/var/run/utmp" "/var/adm/utmp" "/etc/utmp"; do + if test -r "$p"; then + found=yes + AC_MSG_RESULT([$p]) + SUDO_DEFINE_UNQUOTED(_PATH_UTMP, "$p") + break + fi +done +if test X"$found" != X"yes"; then + AC_MSG_RESULT([not found]) +fi +])dnl + dnl dnl Where the log file goes, use /var/log if it exists, else /{var,usr}/adm dnl @@ -234,22 +252,6 @@ AC_DEFUN([SUDO_FUNC_UNSETENV_VOID], fi ]) -dnl -dnl check putenv() argument for const -dnl -AC_DEFUN([SUDO_FUNC_PUTENV_CONST], -[AC_CACHE_CHECK([whether putenv has a const argument], -sudo_cv_func_putenv_const, -[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([AC_INCLUDES_DEFAULT -int putenv(const char *string) {return 0;}], [])], - [sudo_cv_func_putenv_const=yes], - [sudo_cv_func_putenv_const=no]) - ]) - if test $sudo_cv_func_putenv_const = yes; then - AC_DEFINE(PUTENV_CONST, 1, [Define to 1 if the `putenv' has a const argument.]) - fi -]) - dnl dnl check for sa_len field in struct sockaddr dnl diff --git a/auth/sudo_auth.c b/auth/sudo_auth.c deleted file mode 100644 index 42455ee..0000000 --- a/auth/sudo_auth.c +++ /dev/null @@ -1,266 +0,0 @@ -/* - * Copyright (c) 1999-2005, 2008-2010 Todd C. Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Sponsored in part by the Defense Advanced Research Projects - * Agency (DARPA) and Air Force Research Laboratory, Air Force - * Materiel Command, USAF, under agreement number F39502-99-1-0512. - */ - -#include - -#include -#include -#include -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif /* STDC_HEADERS */ -#ifdef HAVE_STRING_H -# include -#endif /* HAVE_STRING_H */ -#ifdef HAVE_STRINGS_H -# include -#endif /* HAVE_STRINGS_H */ -#ifdef HAVE_UNISTD_H -# include -#endif /* HAVE_UNISTD_H */ -#include -#include -#include - -#include "sudo.h" -#include "sudo_auth.h" -#include "insults.h" - -sudo_auth auth_switch[] = { -#ifdef AUTH_STANDALONE - AUTH_STANDALONE -#else -# ifndef WITHOUT_PASSWD - AUTH_ENTRY(0, "passwd", passwd_init, NULL, passwd_verify, passwd_cleanup) -# endif -# if defined(HAVE_GETPRPWNAM) && !defined(WITHOUT_PASSWD) - AUTH_ENTRY(0, "secureware", secureware_init, NULL, secureware_verify, secureware_cleanup) -# endif -# ifdef HAVE_AFS - AUTH_ENTRY(0, "afs", NULL, NULL, afs_verify, NULL) -# endif -# ifdef HAVE_DCE - AUTH_ENTRY(0, "dce", NULL, NULL, dce_verify, NULL) -# endif -# ifdef HAVE_KERB4 - AUTH_ENTRY(0, "kerb4", kerb4_init, NULL, kerb4_verify, NULL) -# endif -# ifdef HAVE_KERB5 - AUTH_ENTRY(0, "kerb5", kerb5_init, NULL, kerb5_verify, kerb5_cleanup) -# endif -# ifdef HAVE_SKEY - AUTH_ENTRY(0, "S/Key", NULL, rfc1938_setup, rfc1938_verify, NULL) -# endif -# ifdef HAVE_OPIE - AUTH_ENTRY(0, "OPIE", NULL, rfc1938_setup, rfc1938_verify, NULL) -# endif -#endif /* AUTH_STANDALONE */ - AUTH_ENTRY(0, NULL, NULL, NULL, NULL, NULL) -}; - -void -verify_user(pw, prompt) - struct passwd *pw; - char *prompt; -{ - int counter = def_passwd_tries + 1; - int success = AUTH_FAILURE; - int status; - int flags; - char *p; - sudo_auth *auth; - sigaction_t sa, osa; -#ifdef HAVE_BSM_AUDIT - extern char **NewArgv; -#endif - - /* Enable suspend during password entry. */ - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_RESTART; - sa.sa_handler = SIG_DFL; - (void) sigaction(SIGTSTP, &sa, &osa); - - /* Make sure we have at least one auth method. */ - if (auth_switch[0].name == NULL) { -#ifdef HAVE_BSM_AUDIT - audit_failure(NewArgv, "no authentication methods"); -#endif - log_error(0, "%s %s %s", - "There are no authentication methods compiled into sudo!", - "If you want to turn off authentication, use the", - "--disable-authentication configure option."); - } - - /* Set FLAG_ONEANDONLY if there is only one auth method. */ - if (auth_switch[1].name == NULL) - SET(auth_switch[0].flags, FLAG_ONEANDONLY); - - /* Initialize auth methods and unconfigure the method if necessary. */ - for (auth = auth_switch; auth->name; auth++) { - if (auth->init && IS_CONFIGURED(auth)) { - if (NEEDS_USER(auth)) - set_perms(PERM_USER); - - status = (auth->init)(pw, &prompt, auth); - if (status == AUTH_FAILURE) - CLR(auth->flags, FLAG_CONFIGURED); - else if (status == AUTH_FATAL) { /* XXX log */ -#ifdef HAVE_BSM_AUDIT - audit_failure(NewArgv, "authentication failure"); -#endif - exit(1); /* assume error msg already printed */ - } - - if (NEEDS_USER(auth)) - set_perms(PERM_ROOT); - } - } - - while (--counter) { - /* Do any per-method setup and unconfigure the method if needed */ - for (auth = auth_switch; auth->name; auth++) { - if (auth->setup && IS_CONFIGURED(auth)) { - if (NEEDS_USER(auth)) - set_perms(PERM_USER); - - status = (auth->setup)(pw, &prompt, auth); - if (status == AUTH_FAILURE) - CLR(auth->flags, FLAG_CONFIGURED); - else if (status == AUTH_FATAL) {/* XXX log */ -#ifdef HAVE_BSM_AUDIT - audit_failure(NewArgv, "authentication failure"); -#endif - exit(1); /* assume error msg already printed */ - } - - if (NEEDS_USER(auth)) - set_perms(PERM_ROOT); - } - } - - /* Get the password unless the auth function will do it for us */ -#ifdef AUTH_STANDALONE - p = prompt; -#else - p = (char *) tgetpass(prompt, def_passwd_timeout * 60, - tgetpass_flags); -#endif /* AUTH_STANDALONE */ - - /* Call authentication functions. */ - for (auth = auth_switch; p && auth->name; auth++) { - if (!IS_CONFIGURED(auth)) - continue; - - if (NEEDS_USER(auth)) - set_perms(PERM_USER); - - success = auth->status = (auth->verify)(pw, (char *)p, auth); - - if (NEEDS_USER(auth)) - set_perms(PERM_ROOT); - - if (auth->status != AUTH_FAILURE) - goto cleanup; - } -#ifndef AUTH_STANDALONE - if (p == NULL) - break; - zero_bytes(p, strlen(p)); -#endif - if (!ISSET(tgetpass_flags, TGP_ASKPASS)) - pass_warn(stderr); - } - -cleanup: - /* Call cleanup routines. */ - for (auth = auth_switch; auth->name; auth++) { - if (auth->cleanup && IS_CONFIGURED(auth)) { - if (NEEDS_USER(auth)) - set_perms(PERM_USER); - - status = (auth->cleanup)(pw, auth); - if (status == AUTH_FATAL) { /* XXX log */ -#ifdef HAVE_BSM_AUDIT - audit_failure(NewArgv, "authentication failure"); -#endif - exit(1); /* assume error msg already printed */ - } - - if (NEEDS_USER(auth)) - set_perms(PERM_ROOT); - } - } - - switch (success) { - case AUTH_SUCCESS: - (void) sigaction(SIGTSTP, &osa, NULL); - return; - case AUTH_INTR: - case AUTH_FAILURE: - if (counter != def_passwd_tries) { - if (def_mail_badpass || def_mail_always) - flags = 0; - else - flags = NO_MAIL; -#ifdef HAVE_BSM_AUDIT - audit_failure(NewArgv, "authentication failure"); -#endif - log_error(flags, "%d incorrect password attempt%s", - def_passwd_tries - counter, - (def_passwd_tries - counter == 1) ? "" : "s"); - } - /* FALLTHROUGH */ - case AUTH_FATAL: -#ifdef HAVE_BSM_AUDIT - audit_failure(NewArgv, "authentication failure"); -#endif - exit(1); - } - /* NOTREACHED */ -} - -void -pass_warn(fp) - FILE *fp; -{ - -#ifdef INSULT - if (def_insults) - (void) fprintf(fp, "%s\n", INSULT); - else -#endif - (void) fprintf(fp, "%s\n", def_badpass_message); -} - -void -dump_auth_methods() -{ - sudo_auth *auth; - - (void) fputs("Authentication methods:", stdout); - for (auth = auth_switch; auth->name; auth++) - (void) printf(" '%s'", auth->name); - (void) putchar('\n'); -} diff --git a/auth/sudo_auth.h b/auth/sudo_auth.h deleted file mode 100644 index 5024955..0000000 --- a/auth/sudo_auth.h +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 1999-2005, 2007-2009 Todd C. Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#ifndef SUDO_AUTH_H -#define SUDO_AUTH_H - -/* Auth function return values. */ -#define AUTH_SUCCESS 0 -#define AUTH_FAILURE 1 -#define AUTH_INTR 2 -#define AUTH_FATAL 3 - -typedef struct sudo_auth { - short flags; /* various flags, see below */ - short status; /* status from verify routine */ - char *name; /* name of the method as a string */ - void *data; /* method-specific data pointer */ - int (*init) __P((struct passwd *pw, char **prompt, struct sudo_auth *auth)); - int (*setup) __P((struct passwd *pw, char **prompt, struct sudo_auth *auth)); - int (*verify) __P((struct passwd *pw, char *p, struct sudo_auth *auth)); - int (*cleanup) __P((struct passwd *pw, struct sudo_auth *auth)); -} sudo_auth; - -/* Values for sudo_auth.flags. */ -/* XXX - these names are too long for my liking */ -#define FLAG_USER 0x01 /* functions must run as the user, not root */ -#define FLAG_CONFIGURED 0x02 /* method configured ok */ -#define FLAG_ONEANDONLY 0x04 /* one and only auth method */ - -/* Shortcuts for using the flags above. */ -#define NEEDS_USER(x) ((x)->flags & FLAG_USER) -#define IS_CONFIGURED(x) ((x)->flags & FLAG_CONFIGURED) -#define IS_ONEANDONLY(x) ((x)->flags & FLAG_ONEANDONLY) - -/* Prototypes for standalone methods */ -int fwtk_init __P((struct passwd *pw, char **prompt, sudo_auth *auth)); -int fwtk_verify __P((struct passwd *pw, char *prompt, sudo_auth *auth)); -int fwtk_cleanup __P((struct passwd *pw, sudo_auth *auth)); -int pam_init __P((struct passwd *pw, char **prompt, sudo_auth *auth)); -int pam_verify __P((struct passwd *pw, char *prompt, sudo_auth *auth)); -int pam_cleanup __P((struct passwd *pw, sudo_auth *auth)); -int sia_setup __P((struct passwd *pw, char **prompt, sudo_auth *auth)); -int sia_verify __P((struct passwd *pw, char *prompt, sudo_auth *auth)); -int sia_cleanup __P((struct passwd *pw, sudo_auth *auth)); -int aixauth_verify __P((struct passwd *pw, char *pass, sudo_auth *auth)); -int aixauth_cleanup __P((struct passwd *pw, sudo_auth *auth)); -int bsdauth_init __P((struct passwd *pw, char **prompt, sudo_auth *auth)); -int bsdauth_verify __P((struct passwd *pw, char *prompt, sudo_auth *auth)); -int bsdauth_cleanup __P((struct passwd *pw, sudo_auth *auth)); - -/* Prototypes for normal methods */ -int passwd_init __P((struct passwd *pw, char **prompt, sudo_auth *auth)); -int passwd_verify __P((struct passwd *pw, char *pass, sudo_auth *auth)); -int passwd_cleanup __P((struct passwd *pw, sudo_auth *auth)); -int secureware_init __P((struct passwd *pw, char **prompt, sudo_auth *auth)); -int secureware_verify __P((struct passwd *pw, char *pass, sudo_auth *auth)); -int secureware_cleanup __P((struct passwd *pw, sudo_auth *auth)); -int rfc1938_setup __P((struct passwd *pw, char **prompt, sudo_auth *auth)); -int rfc1938_verify __P((struct passwd *pw, char *pass, sudo_auth *auth)); -int afs_verify __P((struct passwd *pw, char *pass, sudo_auth *auth)); -int dce_verify __P((struct passwd *pw, char *pass, sudo_auth *auth)); -int kerb4_init __P((struct passwd *pw, char **prompt, sudo_auth *auth)); -int kerb4_verify __P((struct passwd *pw, char *pass, sudo_auth *auth)); -int kerb5_init __P((struct passwd *pw, char **prompt, sudo_auth *auth)); -int kerb5_verify __P((struct passwd *pw, char *pass, sudo_auth *auth)); -int kerb5_cleanup __P((struct passwd *pw, sudo_auth *auth)); -int securid_init __P((struct passwd *pw, char **prompt, sudo_auth *auth)); -int securid_setup __P((struct passwd *pw, char **prompt, sudo_auth *auth)); -int securid_verify __P((struct passwd *pw, char *pass, sudo_auth *auth)); - -/* Fields: need_root, name, init, setup, verify, cleanup */ -#define AUTH_ENTRY(r, n, i, s, v, c) \ - { (r|FLAG_CONFIGURED), AUTH_FAILURE, n, NULL, i, s, v, c }, - -/* Some methods cannots (or should not) interoperate with any others */ -#if defined(HAVE_PAM) -# define AUTH_STANDALONE \ - AUTH_ENTRY(0, "pam", \ - pam_init, NULL, pam_verify, pam_cleanup) -#elif defined(HAVE_SECURID) -# define AUTH_STANDALONE \ - AUTH_ENTRY(0, "SecurId", \ - securid_init, securid_setup, securid_verify, NULL) -#elif defined(HAVE_SIA_SES_INIT) -# define AUTH_STANDALONE \ - AUTH_ENTRY(0, "sia", \ - NULL, sia_setup, sia_verify, sia_cleanup) -#elif defined(HAVE_AIXAUTH) -# define AUTH_STANDALONE \ - AUTH_ENTRY(0, "aixauth", \ - NULL, NULL, aixauth_verify, aixauth_cleanup) -#elif defined(HAVE_FWTK) -# define AUTH_STANDALONE \ - AUTH_ENTRY(0, "fwtk", \ - fwtk_init, NULL, fwtk_verify, fwtk_cleanup) -#elif defined(HAVE_BSD_AUTH_H) -# define AUTH_STANDALONE \ - AUTH_ENTRY(0, "bsdauth", \ - bsdauth_init, NULL, bsdauth_verify, bsdauth_cleanup) -#endif - -#endif /* SUDO_AUTH_H */ diff --git a/common/Makefile.in b/common/Makefile.in new file mode 100644 index 0000000..a0fd01d --- /dev/null +++ b/common/Makefile.in @@ -0,0 +1,112 @@ +# +# Copyright (c) 2011 Todd C. Miller +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# @configure_input@ +# + +#### Start of system configuration section. #### + +srcdir = @srcdir@ +devdir = @devdir@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +incdir = $(top_srcdir)/include + +# Compiler & tools to use +CC = @CC@ +LIBTOOL = @LIBTOOL@ + +# C preprocessor flags +CPPFLAGS = -I. -I$(top_builddir) -I$(incdir) @CPPFLAGS@ + +# Usually -O and/or -g +CFLAGS = @CFLAGS@ + +# OS dependent defines +DEFS = @OSDEFS@ + +#### End of system configuration section. #### + +SHELL = @SHELL@ + +LTOBJS = alloc.lo atobool.lo fileops.lo fmt_string.lo \ + lbuf.lo list.lo term.lo zero_bytes.lo @COMMON_OBJS@ + +all: libcommon.la + +Makefile: $(srcdir)/Makefile.in + (cd $(top_builddir) && ./config.status --file common/Makefile) + +.SUFFIXES: .c .h .lo + +.c.lo: + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $< + +libcommon.la: $(LTOBJS) + $(LIBTOOL) --mode=link $(CC) -o $@ $(LTOBJS) -no-install + +# Dependencies +aix.lo: $(srcdir)/aix.c $(incdir)/missing.h $(incdir)/alloc.h $(incdir)/error.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/aix.c +alloc.lo: $(srcdir)/alloc.c $(incdir)/missing.h $(incdir)/alloc.h $(incdir)/error.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/alloc.c +atobool.lo: $(srcdir)/atobool.c $(incdir)/missing.h $(incdir)/missing.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/atobool.c +fileops.lo: $(srcdir)/fileops.c $(incdir)/fileops.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/fileops.c +fmt_string.lo: $(srcdir)/fmt_string.c $(incdir)/missing.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/fmt_string.c +lbuf.lo: $(srcdir)/lbuf.c $(incdir)/missing.h $(incdir)/alloc.h $(incdir)/error.h $(incdir)/missing.h $(incdir)/lbuf.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/lbuf.c +list.lo: $(srcdir)/list.c $(incdir)/missing.h $(incdir)/list.h $(incdir)/error.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/list.c +term.lo: $(srcdir)/term.c $(incdir)/missing.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/term.c +zero_bytes.lo: $(srcdir)/zero_bytes.c $(incdir)/missing.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/zero_bytes.c + +pre-install: + +install: + +install-dirs: + +install-binaries: + +install-includes: + +install-doc: + +install-plugin: + +uninstall: + +check: + +clean: + -$(LIBTOOL) --mode=clean rm -f *.lo *.o *.la *.a stamp-* core *.core core.* + +mostlyclean: clean + +distclean: clean + -rm -rf Makefile .libs + +clobber: distclean + +realclean: distclean + rm -f TAGS tags + +cleandir: realclean diff --git a/aix.c b/common/aix.c similarity index 93% rename from aix.c rename to common/aix.c index 873896e..00c0f6a 100644 --- a/aix.c +++ b/common/aix.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2010 Todd C. Miller + * Copyright (c) 2008, 2010-2011 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -66,10 +66,7 @@ static struct aix_limit aix_limits[] = { }; static int -aix_getlimit(user, lim, valp) - char *user; - char *lim; - rlim64_t *valp; +aix_getlimit(char *user, char *lim, rlim64_t *valp) { int val; @@ -80,8 +77,7 @@ aix_getlimit(user, lim, valp) } static void -aix_setlimits(user) - char *user; +aix_setlimits(char *user) { struct rlimit64 rlim; rlim64_t val; @@ -136,8 +132,7 @@ aix_setlimits(user) * group lookups are made against the correct source (files, NIS, LDAP, etc). */ void -aix_setauthdb(user) - char *user; +aix_setauthdb(char *user) { char *registry; @@ -157,7 +152,7 @@ aix_setauthdb(user) * Restore the saved administrative domain, if any. */ void -aix_restoreauthdb() +aix_restoreauthdb(void) { if (setauthdb(NULL, NULL) != 0) error(1, "unable to restore registry"); @@ -165,9 +160,7 @@ aix_restoreauthdb() #endif void -aix_prep_user(user, tty) - char *user; - char *tty; +aix_prep_user(char *user, const char *tty) { char *info; int len; diff --git a/alloc.c b/common/alloc.c similarity index 87% rename from alloc.c rename to common/alloc.c index 535465c..7fbf3c8 100644 --- a/alloc.c +++ b/common/alloc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005, 2007, 2010 + * Copyright (c) 1999-2005, 2007, 2010-2011 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -71,8 +71,7 @@ * malloc(3) fails. */ void * -emalloc(size) - size_t size; +emalloc(size_t size) { void *ptr; @@ -89,9 +88,7 @@ emalloc(size) * if overflow would occur or if the system malloc(3) fails. */ void * -emalloc2(nmemb, size) - size_t nmemb; - size_t size; +emalloc2(size_t nmemb, size_t size) { void *ptr; @@ -112,9 +109,7 @@ emalloc2(nmemb, size) * if the system realloc(3) does not support this. */ void * -erealloc(ptr, size) - void *ptr; - size_t size; +erealloc(void *ptr, size_t size) { if (size == 0) @@ -133,10 +128,7 @@ erealloc(ptr, size) * does not support this. */ void * -erealloc3(ptr, nmemb, size) - void *ptr; - size_t nmemb; - size_t size; +erealloc3(void *ptr, size_t nmemb, size_t size) { if (nmemb == 0 || size == 0) @@ -156,14 +148,34 @@ erealloc3(ptr, nmemb, size) * malloc(3) fails. NOTE: unlike strdup(3), estrdup(NULL) is legal. */ char * -estrdup(src) - const char *src; +estrdup(const char *src) +{ + char *dst = NULL; + size_t len; + + if (src != NULL) { + len = strlen(src); + dst = (char *) emalloc(len + 1); + (void) memcpy(dst, src, len); + dst[len] = '\0'; + } + return dst; +} + +/* + * estrdup() is like strndup(3) except that it exits with an error if + * malloc(3) fails. NOTE: unlike strdup(3), estrdup(NULL) is legal. + */ +char * +estrndup(const char *src, size_t maxlen) { char *dst = NULL; size_t len; if (src != NULL) { len = strlen(src); + if (len > maxlen) + len = maxlen; dst = (char *) emalloc(len + 1); (void) memcpy(dst, src, len); dst[len] = '\0'; @@ -176,22 +188,11 @@ estrdup(src) * returns -1 (out of memory). */ int -#ifdef __STDC__ easprintf(char **ret, const char *fmt, ...) -#else -easprintf(ret, fmt, va_alist) - char **ret; - const char *fmt; - va_dcl -#endif { int len; va_list ap; -#ifdef __STDC__ va_start(ap, fmt); -#else - va_start(ap); -#endif len = vasprintf(ret, fmt, ap); va_end(ap); @@ -205,10 +206,7 @@ easprintf(ret, fmt, va_alist) * returns -1 (out of memory). */ int -evasprintf(ret, format, args) - char **ret; - const char *format; - va_list args; +evasprintf(char **ret, const char *format, va_list args) { int len; @@ -221,8 +219,7 @@ evasprintf(ret, format, args) * Wrapper for free(3) so we can depend on C89 semantics. */ void -efree(ptr) - void *ptr; +efree(void *ptr) { if (ptr != NULL) free(ptr); diff --git a/common/atobool.c b/common/atobool.c new file mode 100644 index 0000000..f22aae8 --- /dev/null +++ b/common/atobool.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2010 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include + +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS) +# include +# endif +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ + +#include "missing.h" + +int +atobool(const char *str) +{ + switch (*str) { + case '0': + case '1': + if (str[1] == '\0') + return *str - '0'; + break; + case 'y': + case 'Y': + if (strcasecmp(str, "yes") == 0) + return 1; + break; + case 't': + case 'T': + if (strcasecmp(str, "true") == 0) + return 1; + break; + case 'o': + case 'O': + if (strcasecmp(str, "on") == 0) + return 1; + if (strcasecmp(str, "off") == 0) + return 0; + break; + case 'n': + case 'N': + if (strcasecmp(str, "no") == 0) + return 0; + break; + case 'f': + case 'F': + if (strcasecmp(str, "false") == 0) + return 0; + break; + } + return -1; +} diff --git a/fileops.c b/common/fileops.c similarity index 90% rename from fileops.c rename to common/fileops.c index ae9a7df..38cc0c1 100644 --- a/fileops.c +++ b/common/fileops.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005, 2007, 2009, 2010 + * Copyright (c) 1999-2005, 2007, 2009-2011 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -44,10 +44,11 @@ # include #endif #ifndef HAVE_TIMESPEC -# include "emul/timespec.h" +# include "compat/timespec.h" #endif -#include "sudo.h" +#include "missing.h" +#include "fileops.h" #ifndef LINE_MAX # define LINE_MAX 2048 @@ -57,10 +58,7 @@ * Update the access and modify times on an fd or file. */ int -touch(fd, path, tvp) - int fd; - char *path; - struct timeval *tvp; +touch(int fd, char *path, struct timeval *tvp) { struct timeval times[2]; @@ -85,9 +83,7 @@ touch(fd, path, tvp) */ #ifdef HAVE_LOCKF int -lock_file(fd, lockit) - int fd; - int lockit; +lock_file(int fd, int lockit) { int op = 0; @@ -106,9 +102,7 @@ lock_file(fd, lockit) } #elif HAVE_FLOCK int -lock_file(fd, lockit) - int fd; - int lockit; +lock_file(int fd, int lockit) { int op = 0; @@ -127,9 +121,7 @@ lock_file(fd, lockit) } #else int -lock_file(fd, lockit) - int fd; - int lockit; +lock_file(int fd, int lockit) { #ifdef F_SETLK int func; @@ -154,8 +146,7 @@ lock_file(fd, lockit) * and trailing spaces. Returns static storage that is reused. */ char * -sudo_parseln(fp) - FILE *fp; +sudo_parseln(FILE *fp) { size_t len; char *cp = NULL; diff --git a/common/fmt_string.c b/common/fmt_string.c new file mode 100644 index 0000000..a9c7232 --- /dev/null +++ b/common/fmt_string.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2010-2011 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include + +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS) +# include +# endif +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ + +#include "missing.h" + +/* + * Allocate storage for a name=value string and return it. + */ +char * +fmt_string(const char *var, const char *val) +{ + size_t var_len = strlen(var); + size_t val_len = strlen(val); + char *cp, *str; + + cp = str = malloc(var_len + 1 + val_len + 1); + if (str != NULL) { + memcpy(cp, var, var_len); + cp += var_len; + *cp++ = '='; + memcpy(cp, val, val_len); + cp += val_len; + *cp = '\0'; + } + + return str; +} diff --git a/lbuf.c b/common/lbuf.c similarity index 79% rename from lbuf.c rename to common/lbuf.c index bafea18..92f489e 100644 --- a/lbuf.c +++ b/common/lbuf.c @@ -20,7 +20,6 @@ #include #include -#include #include #ifdef STDC_HEADERS # include @@ -43,61 +42,27 @@ # include #endif /* HAVE_UNISTD_H */ #include -#ifdef HAVE_TERMIOS_H -# include -#else -# ifdef HAVE_TERMIO_H -# include -# endif -#endif -#include "sudo.h" +#include "missing.h" +#include "alloc.h" +#include "error.h" #include "lbuf.h" -/* Compatibility with older tty systems. */ -#if !defined(TIOCGWINSZ) && defined(TIOCGSIZE) -# define TIOCGWINSZ TIOCGSIZE -# define winsize ttysize -# define ws_col ts_cols -#endif - -int -get_ttycols() -{ - char *p; - int cols; -#ifdef TIOCGWINSZ - struct winsize wsize; - - if (ioctl(STDERR_FILENO, TIOCGWINSZ, &wsize) == 0 && wsize.ws_col != 0) - return (int)wsize.ws_col; -#endif - - /* Fall back on $COLUMNS. */ - if ((p = getenv("COLUMNS")) == NULL || (cols = atoi(p)) <= 0) - cols = 80; - return cols; -} - void -lbuf_init(lbuf, output, indent, continuation) - struct lbuf *lbuf; - int (*output)__P((const char *)); - int indent; - const char *continuation; +lbuf_init(struct lbuf *lbuf, int (*output)(const char *), + int indent, const char *continuation, int cols) { lbuf->output = output; lbuf->continuation = continuation; lbuf->indent = indent; - lbuf->cols = get_ttycols(); + lbuf->cols = cols; lbuf->len = 0; lbuf->size = 0; lbuf->buf = NULL; } void -lbuf_destroy(lbuf) - struct lbuf *lbuf; +lbuf_destroy(struct lbuf *lbuf) { efree(lbuf->buf); lbuf->buf = NULL; @@ -107,24 +72,13 @@ lbuf_destroy(lbuf) * Append strings to the buffer, expanding it as needed. */ void -#ifdef __STDC__ lbuf_append_quoted(struct lbuf *lbuf, const char *set, ...) -#else -lbuf_append_quoted(lbuf, set, va_alist) - struct lbuf *lbuf; - const char *set; - va_dcl -#endif { va_list ap; int len = 0; char *cp, *s; -#ifdef __STDC__ va_start(ap, set); -#else - va_start(ap); -#endif while ((s = va_arg(ap, char *)) != NULL) { len += strlen(s); for (cp = s; (cp = strpbrk(cp, set)) != NULL; cp++) @@ -140,11 +94,7 @@ lbuf_append_quoted(lbuf, set, va_alist) lbuf->buf = erealloc(lbuf->buf, lbuf->size); } -#ifdef __STDC__ va_start(ap, set); -#else - va_start(ap); -#endif /* Append each string. */ while ((s = va_arg(ap, char *)) != NULL) { while ((cp = strpbrk(s, set)) != NULL) { @@ -169,23 +119,13 @@ lbuf_append_quoted(lbuf, set, va_alist) * Append strings to the buffer, expanding it as needed. */ void -#ifdef __STDC__ lbuf_append(struct lbuf *lbuf, ...) -#else -lbuf_append(lbuf, va_alist) - struct lbuf *lbuf; - va_dcl -#endif { va_list ap; int len = 0; char *s; -#ifdef __STDC__ va_start(ap, lbuf); -#else - va_start(ap); -#endif while ((s = va_arg(ap, char *)) != NULL) len += strlen(s); va_end(ap); @@ -198,11 +138,7 @@ lbuf_append(lbuf, va_alist) lbuf->buf = erealloc(lbuf->buf, lbuf->size); } -#ifdef __STDC__ va_start(ap, lbuf); -#else - va_start(ap); -#endif /* Append each string. */ while ((s = va_arg(ap, char *)) != NULL) { len = strlen(s); @@ -214,10 +150,7 @@ lbuf_append(lbuf, va_alist) } static void -lbuf_println(lbuf, line, len) - struct lbuf *lbuf; - char *line; - int len; +lbuf_println(struct lbuf *lbuf, char *line, int len) { char *cp, save; int i, have, contlen; @@ -276,8 +209,7 @@ lbuf_println(lbuf, line, len) * The lbuf is reset on return. */ void -lbuf_print(lbuf) - struct lbuf *lbuf; +lbuf_print(struct lbuf *lbuf) { char *cp, *ep; int len; diff --git a/list.c b/common/list.c similarity index 92% rename from list.c rename to common/list.c index 2fb4967..6933177 100644 --- a/list.c +++ b/common/list.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2008 Todd C. Miller + * Copyright (c) 2007-2008, 2010-2011 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -29,7 +29,11 @@ # endif #endif /* STDC_HEADERS */ -#include "sudo.h" +#include "missing.h" +#include "list.h" +#ifdef DEBUG +# include "error.h" +#endif struct list_proto { struct list_proto *prev; @@ -46,8 +50,7 @@ struct list_head_proto { * Returns the popped element. */ void * -tq_pop(vh) - void *vh; +tq_pop(void *vh) { struct list_head_proto *h = (struct list_head_proto *)vh; void *last = NULL; @@ -70,9 +73,7 @@ tq_pop(vh) * with a head node. */ void -list2tq(vh, vl) - void *vh; - void *vl; +list2tq(void *vh, void *vl) { struct list_head_proto *h = (struct list_head_proto *)vh; struct list_proto *l = (struct list_proto *)vl; @@ -98,9 +99,7 @@ list2tq(vh, vl) * circular properties of the prev pointer to simplify the logic. */ void -list_append(vl1, vl2) - void *vl1; - void *vl2; +list_append(void *vl1, void *vl2) { struct list_proto *l1 = (struct list_proto *)vl1; struct list_proto *l2 = (struct list_proto *)vl2; @@ -116,9 +115,7 @@ list_append(vl1, vl2) * e from a semi-circle queue to normal doubly-linked list. */ void -tq_append(vh, vl) - void *vh; - void *vl; +tq_append(void *vh, void *vl) { struct list_head_proto *h = (struct list_head_proto *)vh; struct list_proto *l = (struct list_proto *)vl; @@ -136,9 +133,7 @@ tq_append(vh, vl) * Remove element from the tail_queue */ void -tq_remove(vh, vl) - void *vh; - void *vl; +tq_remove(void *vh, void *vl) { struct list_head_proto *h = (struct list_head_proto *)vh; struct list_proto *l = (struct list_proto *)vl; diff --git a/term.c b/common/term.c similarity index 54% rename from term.c rename to common/term.c index 4aa7128..b8f03db 100644 --- a/term.c +++ b/common/term.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2011 Todd C. Miller + * Copyright (c) 2011 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -36,18 +36,9 @@ #ifdef HAVE_STRINGS_H # include #endif /* HAVE_STRINGS_H */ -#ifdef HAVE_TERMIOS_H -# include -#else -# ifdef HAVE_TERMIO_H -# include -# else -# include -# include -# endif /* HAVE_TERMIO_H */ -#endif /* HAVE_TERMIOS_H */ +#include -#include "sudo.h" +#include "missing.h" #ifndef TCSASOFT # define TCSASOFT 0 @@ -70,43 +61,13 @@ # endif #endif -/* - * Compat macros for non-termios systems. - */ -#ifndef HAVE_TERMIOS_H -# ifdef HAVE_TERMIO_H -# undef termios -# define termios termio -# define tcgetattr(f, t) ioctl(f, TCGETA, t) -# define tcsetattr(f, a, t) ioctl(f, a, t) -# undef TCSAFLUSH -# define TCSAFLUSH TCSETAF -# undef TCSADRAIN -# define TCSADRAIN TCSETAW -# else /* SGTTY */ -# undef termios -# define termios sgttyb -# define c_lflag sg_flags -# define tcgetattr(f, t) ioctl(f, TIOCGETP, t) -# define tcsetattr(f, a, t) ioctl(f, a, t) -# undef TCSAFLUSH -# define TCSAFLUSH TIOCSETP -# undef TCSADRAIN -# define TCSADRAIN TIOCSETN -# endif /* HAVE_TERMIO_H */ -#endif /* HAVE_TERMIOS_H */ - -typedef struct termios sudo_term_t; - -static sudo_term_t term, oterm; +static struct termios term, oterm; static int changed; int term_erase; int term_kill; int -term_restore(fd, flush) - int fd; - int flush; +term_restore(int fd, int flush) { if (changed) { int flags = TCSASOFT; @@ -119,8 +80,7 @@ term_restore(fd, flush) } int -term_noecho(fd) - int fd; +term_noecho(int fd) { if (!changed && tcgetattr(fd, &oterm) != 0) return 0; @@ -136,12 +96,8 @@ term_noecho(fd) return 0; } -#if defined(HAVE_TERMIOS_H) || defined(HAVE_TERMIO_H) - int -term_raw(fd, isig) - int fd; - int isig; +term_raw(int fd, int isig) { struct termios term; @@ -164,8 +120,7 @@ term_raw(fd, isig) } int -term_cbreak(fd) - int fd; +term_cbreak(int fd) { if (!changed && tcgetattr(fd, &oterm) != 0) return 0; @@ -188,81 +143,13 @@ term_cbreak(fd) } int -term_copy(src, dst) - int src; - int dst; +term_copy(int src, int dst) { struct termios tt; if (tcgetattr(src, &tt) != 0) return 0; - /* XXX - add TCSANOW compat define */ if (tcsetattr(dst, TCSANOW|TCSASOFT, &tt) != 0) return 0; return 1; } - -#else /* SGTTY */ - -int -term_raw(fd, isig) - int fd; - int isig; -{ - if (!changed && ioctl(fd, TIOCGETP, &oterm) != 0) - return 0; - (void) memcpy(&term, &oterm, sizeof(term)); - /* Set terminal to raw mode */ - /* XXX - how to support isig? */ - CLR(term.c_lflag, ECHO); - SET(term.sg_flags, RAW); - if (ioctl(fd, TIOCSETP, &term) == 0) { - changed = 1; - return 1; - } - return 0; -} - -int -term_cbreak(fd) - int fd; -{ - if (!changed && ioctl(fd, TIOCGETP, &oterm) != 0) - return 0; - (void) memcpy(&term, &oterm, sizeof(term)); - /* Set terminal to half-cooked mode */ - CLR(term.c_lflag, ECHO); - SET(term.sg_flags, CBREAK); - if (ioctl(fd, TIOCSETP, &term) == 0) { - term_erase = term.sg_erase; - term_kill = term.sg_kill; - changed = 1; - return 1; - } - return 0; -} - -int -term_copy(src, dst) - int src; - int dst; -{ - struct sgttyb b; - struct tchars tc; - struct ltchars lc; - int l, lb; - - if (ioctl(src, TIOCGETP, &b) != 0 || ioctl(src, TIOCGETC, &tc) != 0 || - ioctl(src, TIOCGETD, &l) != 0 || ioctl(src, TIOCGLTC, &lc) != 0 || - ioctl(src, TIOCLGET, &lb)) { - return 0; - } - if (ioctl(dst, TIOCSETP, &b) != 0 || ioctl(dst, TIOCSETC, &tc) != 0 || - ioctl(dst, TIOCSLTC, &lc) != 0 || ioctl(dst, TIOCLSET, &lb) != 0 || - ioctl(dst, TIOCSETD, &l) != 0) { - return 0; - } - return 1; -} - -#endif diff --git a/zero_bytes.c b/common/zero_bytes.c similarity index 88% rename from zero_bytes.c rename to common/zero_bytes.c index bce0895..f6f22bc 100644 --- a/zero_bytes.c +++ b/common/zero_bytes.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2003-2005, 2007 Todd C. Miller + * Copyright (c) 2003-2005, 2007, 2010 + * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -25,9 +26,7 @@ * the compiler will not be able to optimize away this function. */ void -zero_bytes(v, n) - volatile void *v; - size_t n; +zero_bytes(volatile void *v, size_t n) { volatile char *p, *ep; diff --git a/compat/Makefile.in b/compat/Makefile.in new file mode 100644 index 0000000..79b7da4 --- /dev/null +++ b/compat/Makefile.in @@ -0,0 +1,162 @@ +# +# Copyright (c) 2011 Todd C. Miller +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# @configure_input@ +# + +#### Start of system configuration section. #### + +srcdir = @srcdir@ +devdir = @devdir@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +incdir = $(top_srcdir)/include + +# Compiler & tools to use +CC = @CC@ +LIBTOOL = @LIBTOOL@ + +# C preprocessor flags +CPPFLAGS = -I$(top_builddir) -I$(incdir) @CPPFLAGS@ + +# Usually -O and/or -g +CFLAGS = @CFLAGS@ + +# OS dependent defines +DEFS = @OSDEFS@ + +#### End of system configuration section. #### + +SHELL = @SHELL@ + +LIBOBJDIR = + +LTLIBOBJS = @LTLIBOBJS@ + +all: libreplace.la + +Makefile: $(srcdir)/Makefile.in + (cd $(top_builddir) && ./config.status --file compat/Makefile) + +.SUFFIXES: .o .c .h .lo + +.c.lo: + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $< + +libreplace.la: $(LTLIBOBJS) + $(LIBTOOL) --mode=link $(CC) -o $@ $(LTLIBOBJS) -no-install + +./siglist.c: ./mksiglist + ./mksiglist > $@ + +./mksiglist: $(srcdir)/mksiglist.c $(srcdir)/mksiglist.h $(incdir)/missing.h $(top_builddir)/config.h + $(CC) $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/mksiglist.c -o $@ + +fnm_test.o: $(srcdir)/regress/fnmatch/fnm_test.c + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/regress/fnmatch/fnm_test.c + +fnm_test: fnm_test.o libreplace.la + $(LIBTOOL) --mode=link $(CC) -o $@ fnm_test.o libreplace.la + +globtest.o: $(srcdir)/regress/glob/globtest.c + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/regress/glob/globtest.c + +globtest: globtest.o libreplace.la + $(LIBTOOL) --mode=link $(CC) -o $@ globtest.o libreplace.la + +@DEV@$(srcdir)/mksiglist.h: $(srcdir)/siglist.in +@DEV@ awk 'BEGIN {print "/* public domain */\n"} /^ [A-Z]/ {printf("#ifdef SIG%s\n if (my_sys_siglist[SIG%s] == NULL)\n\tmy_sys_siglist[SIG%s] = \"%s\";\n#endif\n", $$1, $$1, $$1, substr($$0, 13))}' < $(srcdir)/siglist.in > $@ + +# Dependencies +closefrom.lo: $(srcdir)/closefrom.c $(incdir)/missing.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/closefrom.c +dlopen.lo: $(srcdir)/dlopen.c $(srcdir)/dlfcn.h $(incdir)/missing.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/dlopen.c +fnmatch.lo: $(srcdir)/fnmatch.c $(srcdir)/fnmatch.h $(srcdir)/charclass.h $(incdir)/missing.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/fnmatch.c +getcwd.lo: $(srcdir)/getcwd.c $(incdir)/missing.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/getcwd.c +getline.lo: $(srcdir)/getline.c $(incdir)/missing.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/getline.c +getprogname.lo: $(srcdir)/getprogname.c $(incdir)/missing.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/getprogname.c +glob.lo: $(srcdir)/glob.c $(srcdir)/glob.h $(srcdir)/charclass.h $(incdir)/missing.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/glob.c +isblank.lo: $(srcdir)/isblank.c $(incdir)/missing.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/isblank.c +memrchr.lo: $(srcdir)/memrchr.c $(incdir)/missing.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/memrchr.c +mktemp.lo: $(srcdir)/mktemp.c $(incdir)/missing.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/mktemp.c +nanosleep.lo: $(srcdir)/nanosleep.c $(incdir)/missing.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/nanosleep.c +siglist.lo: ./siglist.c $(incdir)/missing.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) ./siglist.c +snprintf.lo: $(srcdir)/snprintf.c $(incdir)/missing.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/snprintf.c +strcasecmp.lo: $(srcdir)/strcasecmp.c $(incdir)/missing.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/strcasecmp.c +strerror.lo: $(srcdir)/strerror.c $(incdir)/missing.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/strerror.c +strlcat.lo: $(srcdir)/strlcat.c $(incdir)/missing.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/strlcat.c +strlcpy.lo: $(srcdir)/strlcpy.c $(incdir)/missing.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/strlcpy.c +strsignal.lo: $(srcdir)/strsignal.c $(incdir)/missing.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/strsignal.c +utimes.lo: $(srcdir)/utimes.c $(incdir)/missing.h $(srcdir)/utime.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/utimes.c + +pre-install: + +install: + +install-dirs: + +install-binaries: + +install-includes: + +install-doc: + +install-plugin: + +uninstall: + +check: fnm_test globtest + @./fnm_test $(srcdir)/regress/fnmatch/fnm_test.in + @mkdir -p `sed 's@/[^/]*$$@@' $(srcdir)/regress/glob/files | sort -u` + @touch `cat $(srcdir)/regress/glob/files` + @chmod 0755 `grep '/r[^/]*$$' $(srcdir)/regress/glob/files` + @chmod 0444 `grep '/s[^/]*$$' $(srcdir)/regress/glob/files` + @chmod 0711 `grep '/t[^/]*$$' $(srcdir)/regress/glob/files` + @./globtest $(srcdir)/regress/glob/globtest.in + @rm -rf fake + +clean: + -$(LIBTOOL) --mode=clean rm -f mksiglist siglist.c *.lo *.o *.la *.a stamp-* core *.core core.* + +mostlyclean: clean + +distclean: clean + -rm -rf Makefile .libs + +clobber: distclean + +realclean: distclean + rm -f TAGS tags + +cleandir: realclean diff --git a/emul/charclass.h b/compat/charclass.h similarity index 92% rename from emul/charclass.h rename to compat/charclass.h index 15463ff..4fcf15e 100644 --- a/emul/charclass.h +++ b/compat/charclass.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Todd C. Miller + * Copyright (c) 2008, 2010 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -19,7 +19,7 @@ */ static struct cclass { const char *name; - int (*isctype) __P((int)); + int (*isctype)(int); } cclasses[] = { { "alnum", isalnum }, { "alpha", isalpha }, diff --git a/closefrom.c b/compat/closefrom.c similarity index 96% rename from closefrom.c rename to compat/closefrom.c index 68da392..71777e7 100644 --- a/closefrom.c +++ b/compat/closefrom.c @@ -60,8 +60,7 @@ * This is the expensive (ballback) method. */ void -closefrom_fallback(lowfd) - int lowfd; +closefrom_fallback(int lowfd) { long fd, maxfd; @@ -88,8 +87,7 @@ closefrom_fallback(lowfd) */ #ifdef HAVE_FCNTL_CLOSEM void -closefrom(lowfd) - int lowfd; +closefrom(int lowfd) { if (fcntl(lowfd, F_CLOSEM, 0) == -1) closefrom_fallback(lowfd); @@ -97,8 +95,7 @@ closefrom(lowfd) #else # ifdef HAVE_DIRFD void -closefrom(lowfd) - int lowfd; +closefrom(int lowfd) { struct dirent *dent; DIR *dirp; diff --git a/compat/dlfcn.h b/compat/dlfcn.h new file mode 100644 index 0000000..922c755 --- /dev/null +++ b/compat/dlfcn.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2010 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _DLFCN_H_ +#define _DLFCN_H_ + +/* Emulated functions. */ +void *sudo_dlopen(const char *path, int mode); +int sudo_dlclose(void *handle); +void *sudo_dlsym(void *handle, const char *symbol); +char *sudo_dlerror(void); + +/* Map emulated functions to standard names. */ +#define dlopen(p, m) sudo_dlopen(p, m) +#define dlclose(h) sudo_dlclose(h) +#define dlsym(h, s) sudo_dlsym(h, s) +#define dlerror() sudo_dlerror() + +/* Values for dlopen() mode. */ +#define RTLD_LAZY 0x1 +#define RTLD_NOW 0x2 +#define RTLD_GLOBAL 0x4 +#define RTLD_LOCAL 0x8 + +/* Special handle arguments for dlsym(). */ +#define RTLD_NEXT ((void *) -1) /* Search subsequent objects. */ +#define RTLD_DEFAULT ((void *) -2) /* Use default search algorithm. */ +#define RTLD_SELF ((void *) -3) /* Search the caller itself. */ + +#endif /* !_DLFCN_H_ */ diff --git a/compat/dlopen.c b/compat/dlopen.c new file mode 100644 index 0000000..fa7fd71 --- /dev/null +++ b/compat/dlopen.c @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2010 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include + +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#include + +#include "compat/dlfcn.h" +#include "missing.h" + +#ifdef HAVE_SHL_LOAD +/* + * Emulate dlopen() using shl_load(). + */ +#include + +#ifndef DYNAMIC_PATH +# define DYNAMIC_PATH 0 +#endif + +void * +sudo_dlopen(const char *path, int mode) +{ + int flags = DYNAMIC_PATH; + + if (mode == 0) + mode = RTLD_LAZY; /* default behavior */ + + /* We don't support RTLD_GLOBAL or RTLD_LOCAL yet. */ + if (ISSET(mode, RTLD_LAZY)) + flags |= BIND_DEFERRED; + if (ISSET(mode, RTLD_NOW)) + flags |= BIND_IMMEDIATE; + + return (void *)shl_load(path, flags, 0L); +} + +int +sudo_dlclose(void *handle) +{ + return shl_unload((shl_t)handle); +} + +void * +sudo_dlsym(void *vhandle, const char *symbol) +{ + shl_t handle = vhandle; + void *value = NULL; + + (void)shl_findsym(&handle, symbol, TYPE_UNDEFINED, &value); + + return value; +} + +char * +sudo_dlerror(void) +{ + return strerror(errno); +} + +#else /* !HAVE_SHL_LOAD */ + +/* + * Emulate dlopen() using a static list of symbols compiled into sudo. + */ + +struct sudo_preload_table { + const char *name; + void *address; +}; +extern struct sudo_preload_table sudo_preload_table[]; + +void * +sudo_dlopen(const char *path, int mode) +{ + return (void *)path; +} + +int +sudo_dlclose(void *handle) +{ + return 0; +} + +void * +sudo_dlsym(void *handle, const char *symbol) +{ + struct sudo_preload_table *sym; + + for (sym = sudo_preload_table; sym->name != NULL; sym++) { + if (strcmp(symbol, sym->name) == 0) + return sym->address; + } + return NULL; +} + +char * +sudo_dlerror(void) +{ + return strerror(errno); +} + +#endif /* HAVE_SHL_LOAD */ diff --git a/fnmatch.c b/compat/fnmatch.c similarity index 92% rename from fnmatch.c rename to compat/fnmatch.c index 723e53d..91ef814 100644 --- a/fnmatch.c +++ b/compat/fnmatch.c @@ -50,8 +50,8 @@ #endif /* HAVE_STRINGS_H */ #include "missing.h" -#include "emul/fnmatch.h" -#include "emul/charclass.h" +#include "compat/charclass.h" +#include "compat/fnmatch.h" #undef EOS #define EOS '\0' @@ -64,13 +64,11 @@ __unused static const char rcsid[] = "$OpenBSD: fnmatch.c,v 1.6 1998/03/19 00:29:59 millert Exp $"; #endif /* LIBC_SCCS and not lint */ -static int rangematch __P((const char *, int, int, char **)); -static int classmatch __P((const char *, int, int, const char **)); +static int rangematch(const char *, int, int, char **); +static int classmatch(const char *, int, int, const char **); int -fnmatch(pattern, string, flags) - const char *pattern, *string; - int flags; +rpl_fnmatch(const char *pattern, const char *string, int flags) { const char *stringstart; char *newp; @@ -107,9 +105,9 @@ fnmatch(pattern, string, flags) /* Optimize for pattern with * at end or before /. */ if (c == EOS) { if (ISSET(flags, FNM_PATHNAME)) - return ISSET(flags, FNM_LEADING_DIR) || + return (ISSET(flags, FNM_LEADING_DIR) || strchr(string, '/') == NULL ? - 0 : FNM_NOMATCH; + 0 : FNM_NOMATCH); else return 0; } else if (c == '/' && ISSET(flags, FNM_PATHNAME)) { @@ -170,15 +168,7 @@ fnmatch(pattern, string, flags) } static int -#ifdef __STDC__ rangematch(const char *pattern, int test, int flags, char **newp) -#else -rangematch(pattern, test, flags, newp) - const char *pattern; - int test; - int flags; - char **newp; -#endif { int negate, ok, rv; char c, c2; @@ -243,15 +233,7 @@ rangematch(pattern, test, flags, newp) } static int -#ifdef __STDC__ classmatch(const char *pattern, int test, int foldcase, const char **ep) -#else -classmatch(pattern, test, foldcase, ep) - const char *pattern; - int test; - int foldcase; - const char **ep; -#endif { struct cclass *cc; const char *colon; diff --git a/emul/fnmatch.h b/compat/fnmatch.h similarity index 95% rename from emul/fnmatch.h rename to compat/fnmatch.h index 9f65bc5..b7504ce 100644 --- a/emul/fnmatch.h +++ b/compat/fnmatch.h @@ -41,6 +41,8 @@ #define FNM_LEADING_DIR 0x08 /* Ignore / after Imatch. */ #define FNM_CASEFOLD 0x10 /* Case insensitive search. */ -int fnmatch __P((const char *, const char *, int)); +int rpl_fnmatch(const char *, const char *, int); + +#define fnmatch(_a, _b, _c) rpl_fnmatch((_a), (_b), (_c)) #endif /* !_FNMATCH_H_ */ diff --git a/getcwd.c b/compat/getcwd.c similarity index 99% rename from getcwd.c rename to compat/getcwd.c index 1260ad4..3185504 100644 --- a/getcwd.c +++ b/compat/getcwd.c @@ -78,9 +78,7 @@ (dp->d_name[1] == '.' && dp->d_name[2] == '\0'))) char * -getcwd(pt, size) - char *pt; - size_t size; +getcwd(char *pt, size_t size) { struct dirent *dp; DIR *dir = NULL; diff --git a/getline.c b/compat/getline.c similarity index 82% rename from getline.c rename to compat/getline.c index 2b3d324..606fd0e 100644 --- a/getline.c +++ b/compat/getline.c @@ -36,7 +36,6 @@ #include #include "missing.h" -#include "alloc.h" #ifndef LINE_MAX # define LINE_MAX 2048 @@ -44,12 +43,9 @@ #ifdef HAVE_FGETLN ssize_t -getline(bufp, bufsizep, fp) - char **bufp; - size_t *bufsizep; - FILE *fp; +getline(char **bufp, size_t *bufsizep, FILE *fp) { - char *buf; + char *buf, *cp; size_t bufsize; size_t len; @@ -58,7 +54,10 @@ getline(bufp, bufsizep, fp) bufsize = *bufp ? *bufsizep : 0; if (bufsize < len + 1) { bufsize = len + 1; - *bufp = erealloc(*bufp, bufsize); + cp = *bufp ? realloc(*bufp, bufsize) : malloc(bufsize); + if (cp == NULL) + return -1; + *bufp = cp; *bufsizep = bufsize; } memcpy(*bufp, buf, len); @@ -68,12 +67,9 @@ getline(bufp, bufsizep, fp) } #else ssize_t -getline(bufp, bufsizep, fp) - char **bufp; - size_t *bufsizep; - FILE *fp; +getline(char **bufp, size_t *bufsizep, FILE *fp) { - char *buf; + char *buf, *cp; size_t bufsize; ssize_t len = 0; @@ -81,7 +77,10 @@ getline(bufp, bufsizep, fp) bufsize = *bufsizep; if (buf == NULL || bufsize == 0) { bufsize = LINE_MAX; - buf = erealloc(buf, LINE_MAX); + cp = buf ? realloc(buf, bufsize) : malloc(bufsize); + if (cp == NULL) + return -1; + buf = cp; } for (;;) { @@ -93,7 +92,10 @@ getline(bufp, bufsizep, fp) if (!len || buf[len - 1] == '\n' || feof(fp)) break; bufsize *= 2; - buf = erealloc(buf, bufsize); + cp = realloc(buf, bufsize); + if (cp == NULL) + return -1; + buf = cp; } *bufp = buf; *bufsizep = bufsize; diff --git a/setsid.c b/compat/getprogname.c similarity index 66% rename from setsid.c rename to compat/getprogname.c index 79271c8..34673f5 100644 --- a/setsid.c +++ b/compat/getprogname.c @@ -17,33 +17,30 @@ #include #include -#include -#include -#include -#ifdef HAVE_UNISTD_H -# include -#endif /* HAVE_UNISTD_H */ +#include +#include -#include #include "missing.h" -pid_t -setsid() +static const char *progname = "sudo"; + +void +setprogname(const char *name) { - int fd; - -#ifdef SETPGRP_VOID - if (setpgrp() == -1) -#else - if (setpgrp(0, 0) == -1) -#endif - return -1; -# ifdef TIOCNOTTY - if ((fd = open(_PATH_TTY, O_RDWR, 0644)) != -1) { - (void) ioctl(fd, TIOCNOTTY, NULL); - close(fd); + const char *base; + + if ((base = strrchr(name, '/')) != NULL) { + base++; + } else { + base = name; } -# endif - return getpid(); + if (strcmp(progname, base) != 0) + progname = base; +} + +const char * +getprogname(void) +{ + return progname; } diff --git a/glob.c b/compat/glob.c similarity index 85% rename from glob.c rename to compat/glob.c index 66dcadc..cf9a4e2 100644 --- a/glob.c +++ b/compat/glob.c @@ -96,8 +96,8 @@ #include #include "missing.h" -#include "emul/glob.h" -#include "emul/charclass.h" +#include "compat/glob.h" +#include "compat/charclass.h" #define DOLLAR '$' #define DOT '.' @@ -150,38 +150,32 @@ typedef char Char; #define ismeta(c) (((c)&M_QUOTE) != 0) -static int compare __P((const void *, const void *)); -static int g_Ctoc __P((const Char *, char *, unsigned int)); -static int g_lstat __P((Char *, struct stat *, glob_t *)); -static DIR *g_opendir __P((Char *, glob_t *)); -static Char *g_strchr __P((const Char *, int)); -static int g_strncmp __P((const Char *, const char *, size_t)); -static int g_stat __P((Char *, struct stat *, glob_t *)); -static int glob0 __P((const Char *, glob_t *)); -static int glob1 __P((Char *, Char *, glob_t *)); -static int glob2 __P((Char *, Char *, Char *, Char *, Char *, Char *, - glob_t *)); -static int glob3 __P((Char *, Char *, Char *, Char *, Char *, Char *, - Char *, Char *, glob_t *)); -static int globextend __P((const Char *, glob_t *)); +static int compare(const void *, const void *); +static int g_Ctoc(const Char *, char *, unsigned int); +static int g_lstat(Char *, struct stat *, glob_t *); +static DIR *g_opendir(Char *, glob_t *); +static Char *g_strchr(const Char *, int); +static int g_strncmp(const Char *, const char *, size_t); +static int g_stat(Char *, struct stat *, glob_t *); +static int glob0(const Char *, glob_t *); +static int glob1(Char *, Char *, glob_t *); +static int glob2(Char *, Char *, Char *, Char *, Char *, Char *, + glob_t *); +static int glob3(Char *, Char *, Char *, Char *, Char *, Char *, + Char *, Char *, glob_t *); +static int globextend(const Char *, glob_t *); static const Char * - globtilde __P((const Char *, Char *, size_t, glob_t *)); -static int globexp1 __P((const Char *, glob_t *)); -static int globexp2 __P((const Char *, const Char *, glob_t *, int *)); -static int match __P((Char *, Char *, Char *)); + globtilde(const Char *, Char *, size_t, glob_t *); +static int globexp1(const Char *, glob_t *); +static int globexp2(const Char *, const Char *, glob_t *, int *); +static int match(Char *, Char *, Char *); #ifdef DEBUG -static void qprintf __P((const char *, Char *)); +static void qprintf(const char *, Char *); #endif -extern struct passwd *sudo_getpwnam __P((const char *)); -extern struct passwd *sudo_getpwuid __P((uid_t)); -extern void pw_delref __P((struct passwd *)); - int -glob(pattern, flags, errfunc, pglob) - const char *pattern; - int flags, (*errfunc) __P((const char *, int)); - glob_t *pglob; +rpl_glob(const char *pattern, int flags, int (*errfunc)(const char *, int), + glob_t *pglob) { const unsigned char *patnext; int c; @@ -229,9 +223,7 @@ glob(pattern, flags, errfunc, pglob) * characters */ static int -globexp1(pattern, pglob) - const Char *pattern; - glob_t *pglob; +globexp1(const Char *pattern, glob_t *pglob) { const Char* ptr = pattern; int rv; @@ -254,10 +246,7 @@ globexp1(pattern, pglob) * If it fails then it tries to glob the rest of the pattern and returns. */ static int -globexp2(ptr, pattern, pglob, rv) - const Char *ptr, *pattern; - glob_t *pglob; - int *rv; +globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv) { int i; Char *lm, *ls; @@ -362,13 +351,9 @@ globexp2(ptr, pattern, pglob, rv) * expand tilde from the passwd file. */ static const Char * -globtilde(pattern, patbuf, patbuf_len, pglob) - const Char *pattern; - Char *patbuf; - size_t patbuf_len; - glob_t *pglob; +globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob) { - struct passwd *pwd = NULL; + struct passwd *pwd; char *h; const Char *p; Char *b, *eb; @@ -390,7 +375,7 @@ globtilde(pattern, patbuf, patbuf_len, pglob) * first and then trying the password file */ if ((h = getenv("HOME")) == NULL) { - if ((pwd = sudo_getpwuid(getuid())) == NULL) + if ((pwd = getpwuid(getuid())) == NULL) return pattern; else h = pwd->pw_dir; @@ -399,7 +384,7 @@ globtilde(pattern, patbuf, patbuf_len, pglob) /* * Expand a ~user */ - if ((pwd = sudo_getpwnam((char*) patbuf)) == NULL) + if ((pwd = getpwnam((char*) patbuf)) == NULL) return pattern; else h = pwd->pw_dir; @@ -414,17 +399,11 @@ globtilde(pattern, patbuf, patbuf_len, pglob) continue; *b = EOS; - if (pwd) - pw_delref(pwd); - return patbuf; } static int -g_strncmp(s1, s2, n) - const Char *s1; - const char *s2; - size_t n; +g_strncmp(const Char *s1, const char *s2, size_t n) { int rv = 0; @@ -439,9 +418,7 @@ g_strncmp(s1, s2, n) } static int -g_charclass(patternp, bufnextp) - const Char **patternp; - Char **bufnextp; +g_charclass(const Char **patternp, Char **bufnextp) { const Char *pattern = *patternp + 1; Char *bufnext = *bufnextp; @@ -475,9 +452,7 @@ g_charclass(patternp, bufnextp) * to find no matches. */ static int -glob0(pattern, pglob) - const Char *pattern; - glob_t *pglob; +glob0(const Char *pattern, glob_t *pglob) { const Char *qpatnext; int c, err, oldpathc; @@ -573,16 +548,13 @@ glob0(pattern, pglob) } static int -compare(p, q) - const void *p, *q; +compare(const void *p, const void *q) { return strcmp(*(char **)p, *(char **)q); } static int -glob1(pattern, pattern_last, pglob) - Char *pattern, *pattern_last; - glob_t *pglob; +glob1(Char *pattern, Char *pattern_last, glob_t *pglob) { Char pathbuf[PATH_MAX]; @@ -600,11 +572,8 @@ glob1(pattern, pattern_last, pglob) * meta characters. */ static int -glob2(pathbuf, pathbuf_last, pathend, pathend_last, pattern, pattern_last, pglob) - Char *pathbuf, *pathbuf_last; - Char *pathend, *pathend_last; - Char *pattern, *pattern_last; - glob_t *pglob; +glob2(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, + Char *pattern, Char *pattern_last, glob_t *pglob) { struct stat sb; Char *p, *q; @@ -663,11 +632,9 @@ glob2(pathbuf, pathbuf_last, pathend, pathend_last, pattern, pattern_last, pglob } static int -glob3(pathbuf, pathbuf_last, pathend, pathend_last, pattern, pattern_last, - restpattern, restpattern_last, pglob) - Char *pathbuf, *pathbuf_last, *pathend, *pathend_last; - Char *pattern, *pattern_last, *restpattern, *restpattern_last; - glob_t *pglob; +glob3(Char *pathbuf, Char *pathbuf_last, Char *pathend, Char *pathend_last, + Char *pattern, Char *pattern_last, Char *restpattern, + Char *restpattern_last, glob_t *pglob) { struct dirent *dp; DIR *dirp; @@ -740,9 +707,7 @@ glob3(pathbuf, pathbuf_last, pathend, pathend_last, pattern, pattern_last, * gl_pathv points to (gl_offs + gl_pathc + 1) items. */ static int -globextend(path, pglob) - const Char *path; - glob_t *pglob; +globextend(const Char *path, glob_t *pglob) { char **pathv; int i; @@ -790,8 +755,7 @@ globextend(path, pglob) * pattern causes a recursion level. */ static int -match(name, pat, patend) - Char *name, *pat, *patend; +match(Char *name, Char *pat, Char *patend) { int ok, negate_range; Char c, k; @@ -846,8 +810,7 @@ match(name, pat, patend) /* Free allocated data belonging to a glob_t structure. */ void -globfree(pglob) - glob_t *pglob; +rpl_globfree(glob_t *pglob) { int i; char **pp; @@ -863,9 +826,7 @@ globfree(pglob) } static DIR * -g_opendir(str, pglob) - Char *str; - glob_t *pglob; +g_opendir(Char *str, glob_t *pglob) { char buf[PATH_MAX]; @@ -880,10 +841,7 @@ g_opendir(str, pglob) } static int -g_lstat(fn, sb, pglob) - Char *fn; - struct stat *sb; - glob_t *pglob; +g_lstat(Char *fn, struct stat *sb, glob_t *pglob) { char buf[PATH_MAX]; @@ -893,10 +851,7 @@ g_lstat(fn, sb, pglob) } static int -g_stat(fn, sb, pglob) - Char *fn; - struct stat *sb; - glob_t *pglob; +g_stat(Char *fn, struct stat *sb, glob_t *pglob) { char buf[PATH_MAX]; @@ -906,9 +861,7 @@ g_stat(fn, sb, pglob) } static Char * -g_strchr(str, ch) - const Char *str; - int ch; +g_strchr(const Char *str, int ch) { do { if (*str == ch) @@ -918,10 +871,7 @@ g_strchr(str, ch) } static int -g_Ctoc(str, buf, len) - const Char *str; - char *buf; - unsigned int len; +g_Ctoc(const Char *str, char *buf, unsigned int len) { while (len--) { @@ -933,9 +883,7 @@ g_Ctoc(str, buf, len) #ifdef DEBUG static void -qprintf(str, s) - const char *str; - Char *s; +qprintf(const char *str, Char *s) { Char *p; diff --git a/emul/glob.h b/compat/glob.h similarity index 94% rename from emul/glob.h rename to compat/glob.h index 36efc00..7e7153b 100644 --- a/emul/glob.h +++ b/compat/glob.h @@ -45,11 +45,7 @@ typedef struct { int gl_flags; /* Copy of flags parameter to glob. */ char **gl_pathv; /* List of paths matching pattern. */ /* Copy of errfunc parameter to glob. */ -#ifdef __STDC__ int (*gl_errfunc)(const char *, int); -#else - int (*gl_errfunc)(); -#endif } glob_t; /* Flags */ @@ -73,12 +69,10 @@ typedef struct { #define GLOB_NOSYS (-4) /* Function not supported. */ #define GLOB_ABEND GLOB_ABORTED -#ifdef __STDC__ -int glob(const char *, int, int (*)(const char *, int), glob_t *); -void globfree(glob_t *); -#else -int glob(); -void globfree(); -#endif +int rpl_glob(const char *, int, int (*)(const char *, int), glob_t *); +void rpl_globfree(glob_t *); + +#define glob(_a, _b, _c, _d) rpl_glob((_a), (_b), (_c), (_d)) +#define globfree(_a) rpl_globfree((_a)) #endif /* !_GLOB_H_ */ diff --git a/isblank.c b/compat/isblank.c similarity index 90% rename from isblank.c rename to compat/isblank.c index a7f01e2..083d805 100644 --- a/isblank.c +++ b/compat/isblank.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Todd C. Miller + * Copyright (c) 2008, 2010-2011 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -22,8 +22,7 @@ #undef isblank int -isblank(ch) - int ch; +isblank(int ch) { return ch == ' ' || ch == '\t'; } diff --git a/memrchr.c b/compat/memrchr.c similarity index 89% rename from memrchr.c rename to compat/memrchr.c index 425fcb4..0b1e3a5 100644 --- a/memrchr.c +++ b/compat/memrchr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 Todd C. Miller + * Copyright (c) 2007, 2010-2011 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -25,10 +25,7 @@ * Find the last occurrence of 'c' in the buffer 's' of size 'n'. */ void * -memrchr(s, c, n) - const void *s; - int c; - size_t n; +memrchr(const void *s, int c, size_t n) { const unsigned char *cp; diff --git a/mksiglist.c b/compat/mksiglist.c similarity index 91% rename from mksiglist.c rename to compat/mksiglist.c index f5cfbc1..ce88919 100644 --- a/mksiglist.c +++ b/compat/mksiglist.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Todd C. Miller + * Copyright (c) 2010-2011 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -33,14 +33,12 @@ #include "missing.h" int -main(argc, argv) - int argc; - char *argv[]; +main(int argc, char *argv[]) { static char *my_sys_siglist[NSIG]; int i; -#include "mksiglist.h" +#include "compat/mksiglist.h" printf("#include \n"); printf("#include \n"); diff --git a/mksiglist.h b/compat/mksiglist.h similarity index 100% rename from mksiglist.h rename to compat/mksiglist.h diff --git a/mkstemps.c b/compat/mktemp.c similarity index 75% rename from mkstemps.c rename to compat/mktemp.c index b3b688d..ce7a4e5 100644 --- a/mkstemps.c +++ b/compat/mktemp.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2003, 2004, 2008-2010 + * Copyright (c) 2001, 2003, 2004, 2008-2011 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -36,10 +36,10 @@ # include #endif -#include "sudo.h" +#include "missing.h" -static unsigned int get_random __P((void)); -static void seed_random __P((void)); +#define MKTEMP_FILE 1 +#define MKTEMP_DIR 2 #define TEMPCHARS "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" #define NUM_CHARS (sizeof(TEMPCHARS) - 1) @@ -48,46 +48,6 @@ static void seed_random __P((void)); #define INT_MAX 0x7fffffff #endif -int -mkstemps(path, slen) - char *path; - int slen; -{ - char *start, *cp, *ep; - const char *tempchars = TEMPCHARS; - unsigned int r, tries; - int fd; - - for (ep = path; *ep; ep++) - ; - if (path + slen >= ep) { - errno = EINVAL; - return -1; - } - ep -= slen; - - tries = 1; - for (start = ep; start > path && start[-1] == 'X'; start--) { - if (tries < INT_MAX / NUM_CHARS) - tries *= NUM_CHARS; - } - tries *= 2; - - do { - for (cp = start; *cp; cp++) { - r = get_random() % NUM_CHARS; - *cp = tempchars[r]; - } - - fd = open(path, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR); - if (fd != -1 || errno != EEXIST) - return fd; - } while (--tries); - - errno = EEXIST; - return -1; -} - #ifdef HAVE_RANDOM # define RAND random # define SRAND srandom @@ -105,7 +65,7 @@ mkstemps(path, slen) #endif static void -seed_random() +seed_random(void) { SEED_T seed; struct timeval tv; @@ -113,14 +73,14 @@ seed_random() /* * Seed from time of day and process id multiplied by small primes. */ - (void) gettime(&tv); + (void) gettimeofday(&tv, NULL); seed = (tv.tv_sec % 10000) * 523 + tv.tv_usec * 13 + (getpid() % 1000) * 983; SRAND(seed); } static unsigned int -get_random() +get_random(void) { static int initialized; @@ -131,3 +91,69 @@ get_random() return RAND() & 0xffffffff; } + +static int +mktemp_internal(char *path, int slen, int mode) +{ + char *start, *cp, *ep; + const char *tempchars = TEMPCHARS; + unsigned int r, tries; + int fd; + + for (ep = path; *ep; ep++) + ; + if (path + slen >= ep) { + errno = EINVAL; + return -1; + } + ep -= slen; + + tries = 1; + for (start = ep; start > path && start[-1] == 'X'; start--) { + if (tries < INT_MAX / NUM_CHARS) + tries *= NUM_CHARS; + } + tries *= 2; + + do { + for (cp = start; *cp; cp++) { + r = get_random() % NUM_CHARS; + *cp = tempchars[r]; + } + + switch (mode) { + case MKTEMP_FILE: + fd = open(path, O_CREAT|O_EXCL|O_RDWR, S_IRUSR|S_IWUSR); + if (fd != -1 || errno != EEXIST) + return fd; + break; + case MKTEMP_DIR: + if (mkdir(path, S_IRWXU) == 0) + return 0; + if (errno != EEXIST) + return -1; + break; + } + } while (--tries); + + errno = EEXIST; + return -1; +} + +#ifndef HAVE_MKSTEMPS +int +mkstemps(char *path, int slen) +{ + return mktemp_internal(path, slen, MKTEMP_FILE); +} +#endif /* HAVE_MKSTEMPS */ + +#ifndef HAVE_MKDTEMP +char * +mkdtemp(char *path) +{ + if (mktemp_internal(path, 0, MKTEMP_DIR) == -1) + return NULL; + return path; +} +#endif /* HAVE_MKDTEMP */ diff --git a/nanosleep.c b/compat/nanosleep.c similarity index 89% rename from nanosleep.c rename to compat/nanosleep.c index 1849eb2..9490d72 100644 --- a/nanosleep.c +++ b/compat/nanosleep.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2010 Todd C. Miller + * Copyright (c) 2009-2011 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -25,16 +25,14 @@ # include #endif #ifndef HAVE_TIMESPEC -# include "emul/timespec.h" +# include "compat/timespec.h" #endif #include #include "missing.h" int -nanosleep(ts, rts) - const struct timespec *ts; - struct timespec *rts; +nanosleep(const struct timespec *ts, struct timespec *rts) { struct timeval timeout, endtime, now; int rval; diff --git a/compat/regress/fnmatch/fnm_test.c b/compat/regress/fnmatch/fnm_test.c new file mode 100644 index 0000000..2079e3b --- /dev/null +++ b/compat/regress/fnmatch/fnm_test.c @@ -0,0 +1,76 @@ +/* $OpenBSD: fnm_test.c,v 1.1 2008/10/01 23:04:58 millert Exp $ */ + +/* + * Public domain, 2008, Todd C. Miller + */ + +#include + +#include +#include +#ifdef HAVE_STRING_H +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#ifdef HAVE_FNMATCH +# include +#else +# include "compat/fnmatch.h" +#endif + +int +main(int argc, char *argv[]) +{ + FILE *fp = stdin; + char pattern[1024], string[1024], flagstr[1024]; + int errors = 0, tests = 0, flags, got, want; + + if (argc > 1) { + if ((fp = fopen(argv[1], "r")) == NULL) { + perror(argv[1]); + exit(1); + } + } + + /* + * Read in test file, which is formatted thusly: + * + * pattern string flags expected_result + * + */ + for (;;) { + got = fscanf(fp, "%s %s %s %d\n", pattern, string, flagstr, + &want); + if (got == EOF) + break; + if (got == 4) { + flags = 0; + if (strcmp(flagstr, "FNM_NOESCAPE") == 0) + flags |= FNM_NOESCAPE; + else if (strcmp(flagstr, "FNM_PATHNAME") == 0) + flags |= FNM_PATHNAME; + else if (strcmp(flagstr, "FNM_PERIOD") == 0) + flags |= FNM_PERIOD; + else if (strcmp(flagstr, "FNM_LEADING_DIR") == 0) + flags |= FNM_LEADING_DIR; + else if (strcmp(flagstr, "FNM_CASEFOLD") == 0) + flags |= FNM_CASEFOLD; + got = fnmatch(pattern, string, flags); + if (got != want) { + fprintf(stderr, + "fnmatch: %s %s %d: want %d, got %d\n", + pattern, string, flags, want, got); + errors++; + } + tests++; + } + } + if (tests != 0) { + printf("fnmatch: %d test%s run, %d errors, %d%% success rate\n", + tests, tests == 1 ? "" : "s", errors, + (tests - errors) * 100 / tests); + } + exit(errors); +} diff --git a/compat/regress/fnmatch/fnm_test.in b/compat/regress/fnmatch/fnm_test.in new file mode 100644 index 0000000..5d452ef --- /dev/null +++ b/compat/regress/fnmatch/fnm_test.in @@ -0,0 +1,5 @@ +/bin/[[:alpha:][:alnum:]]* /bin/ls FNM_PATHNAME 0 +/bin/[[:alpha:][:alnum:]]* /bin/LS FNM_CASEFOLD 0 +/bin/[[:opper:][:alnum:]]* /bin/ls NONE 1 +[[:alpha:][:alnum:]]*.c foo1.c FNM_PERIOD 0 +[[:upper:]]* FOO NONE 0 diff --git a/compat/regress/glob/files b/compat/regress/glob/files new file mode 100644 index 0000000..c5e92aa --- /dev/null +++ b/compat/regress/glob/files @@ -0,0 +1,47 @@ +fake/bin/[ +fake/bin/cat +fake/bin/chgrp +fake/bin/chio +fake/bin/chmod +fake/bin/cksum +fake/bin/cp +fake/bin/cpio +fake/bin/csh +fake/bin/date +fake/bin/dd +fake/bin/df +fake/bin/domainname +fake/bin/echo +fake/bin/ed +fake/bin/eject +fake/bin/expr +fake/bin/hostname +fake/bin/kill +fake/bin/ksh +fake/bin/ln +fake/bin/ls +fake/bin/md5 +fake/bin/mkdir +fake/bin/mt +fake/bin/mv +fake/bin/pax +fake/bin/ps +fake/bin/pwd +fake/bin/rcp +fake/bin/rksh +fake/bin/rm +fake/bin/rmail +fake/bin/rmd160 +fake/bin/rmdir +fake/bin/sh +fake/bin/sha1 +fake/bin/sha256 +fake/bin/sha384 +fake/bin/sha512 +fake/bin/sleep +fake/bin/stty +fake/bin/sum +fake/bin/sync +fake/bin/systrace +fake/bin/tar +fake/bin/test diff --git a/compat/regress/glob/globtest.c b/compat/regress/glob/globtest.c new file mode 100644 index 0000000..0c966fe --- /dev/null +++ b/compat/regress/glob/globtest.c @@ -0,0 +1,213 @@ +/* $OpenBSD: globtest.c,v 1.1 2008/10/01 23:04:36 millert Exp $ */ + +/* + * Public domain, 2008, Todd C. Miller + */ + +#include + +#include +#include +#ifdef HAVE_STRING_H +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#ifdef HAVE_EXTENDED_GLOB +# include +#else +# include "compat/glob.h" +#endif +#include + +#define MAX_RESULTS 256 + +#ifndef errno +extern int errno; +#endif + +struct gl_entry { + int flags; + int nresults; + char pattern[1024]; + char *results[MAX_RESULTS]; +}; + +int test_glob(struct gl_entry *); + +int +main(int argc, char **argv) +{ + FILE *fp = stdin; + char buf[2048], *cp, *ep; + int errors = 0, tests = 0, lineno; + struct gl_entry entry; + size_t len; + + if (argc > 1) { + if ((fp = fopen(argv[1], "r")) == NULL) { + perror(argv[1]); + exit(1); + } + } + + /* + * Read in test file, which is formatted thusly: + * + * [pattern] + * result1 + * result2 + * result3 + * ... + * + */ + lineno = 0; + memset(&entry, 0, sizeof(entry)); + while (fgets(buf, sizeof(buf), fp) != NULL) { + lineno++; + len = strlen(buf); + if (len > 0) { + if (buf[len - 1] != '\n') { + fprintf(stderr, + "globtest: missing newline at EOF\n"); + exit(1); + } + buf[--len] = '\0'; + } + if (len == 0) + continue; /* blank line */ + + if (buf[0] == '[') { + /* check previous pattern */ + if (entry.pattern[0]) { + errors += test_glob(&entry); + tests++; + } + + /* start new entry */ + if ((cp = strrchr(buf + 1, ']')) == NULL) { + fprintf(stderr, + "globtest: invalid entry on line %d\n", + lineno); + exit(1); + } + len = cp - buf - 1; + if (len >= sizeof(entry.pattern)) { + fprintf(stderr, + "globtest: pattern too big on line %d\n", + lineno); + exit(1); + } + memcpy(entry.pattern, buf + 1, len); + entry.pattern[len] = '\0'; + + cp += 2; + if (*cp++ != '<') { + fprintf(stderr, + "globtest: invalid entry on line %d\n", + lineno); + exit(1); + } + ep = strchr(cp, '>'); + if (ep == NULL) { + fprintf(stderr, + "globtest: invalid entry on line %d\n", + lineno); + exit(1); + } + *ep = '\0'; + entry.flags = 0; + for ((cp = strtok(cp, "|")); cp != NULL; (cp = strtok(NULL, "|"))) { + if (strcmp(cp, "GLOB_APPEND") == 0) + entry.flags |= GLOB_APPEND; + else if (strcmp(cp, "GLOB_DOOFFS") == 0) + entry.flags |= GLOB_DOOFFS; + else if (strcmp(cp, "GLOB_ERR") == 0) + entry.flags |= GLOB_ERR; + else if (strcmp(cp, "GLOB_MARK") == 0) + entry.flags |= GLOB_MARK; + else if (strcmp(cp, "GLOB_NOCHECK") == 0) + entry.flags |= GLOB_NOCHECK; + else if (strcmp(cp, "GLOB_NOSORT") == 0) + entry.flags |= GLOB_NOSORT; + else if (strcmp(cp, "GLOB_NOESCAPE") == 0) + entry.flags |= GLOB_NOESCAPE; + else if (strcmp(cp, "GLOB_BRACE") == 0) + entry.flags |= GLOB_BRACE; + else if (strcmp(cp, "GLOB_TILDE") == 0) + entry.flags |= GLOB_TILDE; + else if (strcmp(cp, "NONE") != 0) { + fprintf(stderr, + "globtest: invalid flags on line %d\n", + lineno); + exit(1); + } + } + entry.nresults = 0; + continue; + } + if (!entry.pattern[0]) { + fprintf(stderr, "globtest: missing entry on line %d\n", + lineno); + exit(1); + } + + if (entry.nresults + 1 > MAX_RESULTS) { + fprintf(stderr, + "globtest: too many results for %s, max %d\n", + entry.pattern, MAX_RESULTS); + exit(1); + } + entry.results[entry.nresults++] = strdup(buf); + } + if (entry.pattern[0]) { + errors += test_glob(&entry); /* test last pattern */ + tests++; + } + if (tests != 0) { + printf("glob: %d test%s run, %d errors, %d%% success rate\n", + tests, tests == 1 ? "" : "s", errors, + (tests - errors) * 100 / tests); + } + exit(errors); +} + +int test_glob(struct gl_entry *entry) +{ + glob_t gl; + char **ap; + int nmatches = 0, i = 0; + + if (glob(entry->pattern, entry->flags, NULL, &gl) != 0) { + fprintf(stderr, "glob failed: %s: %s\n", entry->pattern, + strerror(errno)); + exit(1); + } + + for (ap = gl.gl_pathv; *ap != NULL; ap++) + nmatches++; + + if (nmatches != entry->nresults) + goto mismatch; + + for (i = 0; i < entry->nresults; i++) { + if (strcmp(gl.gl_pathv[i], entry->results[i]) != 0) + goto mismatch; + free(entry->results[i]); + } + return 0; + mismatch: + if (nmatches != entry->nresults) { + fprintf(stderr, + "globtest: mismatch in number of results (found %d, expected %d) for pattern %s\n", + nmatches, entry->nresults, entry->pattern); + } else { + fprintf(stderr, "globtest: mismatch for pattern %s, flags 0x%x " + "(found \"%s\", expected \"%s\")\n", entry->pattern, entry->flags, + gl.gl_pathv[i], entry->results[i]); + while (i < entry->nresults) + free(entry->results[i++]); + } + return 1; +} diff --git a/compat/regress/glob/globtest.in b/compat/regress/glob/globtest.in new file mode 100644 index 0000000..20a86c1 --- /dev/null +++ b/compat/regress/glob/globtest.in @@ -0,0 +1,64 @@ +[fake/bin/[[:alpha:]]*] +fake/bin/cat +fake/bin/chgrp +fake/bin/chio +fake/bin/chmod +fake/bin/cksum +fake/bin/cp +fake/bin/cpio +fake/bin/csh +fake/bin/date +fake/bin/dd +fake/bin/df +fake/bin/domainname +fake/bin/echo +fake/bin/ed +fake/bin/eject +fake/bin/expr +fake/bin/hostname +fake/bin/kill +fake/bin/ksh +fake/bin/ln +fake/bin/ls +fake/bin/md5 +fake/bin/mkdir +fake/bin/mt +fake/bin/mv +fake/bin/pax +fake/bin/ps +fake/bin/pwd +fake/bin/rcp +fake/bin/rksh +fake/bin/rm +fake/bin/rmail +fake/bin/rmd160 +fake/bin/rmdir +fake/bin/sh +fake/bin/sha1 +fake/bin/sha256 +fake/bin/sha384 +fake/bin/sha512 +fake/bin/sleep +fake/bin/stty +fake/bin/sum +fake/bin/sync +fake/bin/systrace +fake/bin/tar +fake/bin/test + +[fake/bin/rm{,dir,ail}] +fake/bin/rm +fake/bin/rmdir +fake/bin/rmail + +[fake/bin/sha[[:digit:]]] +fake/bin/sha1 + +[fake/bin/sha[[:digit:]]*] +fake/bin/sha1 +fake/bin/sha256 +fake/bin/sha384 +fake/bin/sha512 + +[fake/bin/ca[a-z]] +fake/bin/cat diff --git a/compat/setenv.c b/compat/setenv.c new file mode 100644 index 0000000..cff0c26 --- /dev/null +++ b/compat/setenv.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2010 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include + +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS) +# include +#endif /* HAVE_MALLOC_H && !STDC_HEADERS */ +#include + +#include "missing.h" + +int +setenv(const char *var, const char *val, int overwrite) +{ + char *envstr, *dst; + const char *src; + size_t esize; + + if (!var || *var == '\0') { + errno = EINVAL; + return -1; + } + + /* + * POSIX says a var name with '=' is an error but BSD + * just ignores the '=' and anything after it. + */ + for (src = var; *src != '\0' && *src != '='; src++) + ; + esize = (size_t)(src - var) + 2; + if (val) { + esize += strlen(val); /* glibc treats a NULL val as "" */ + } + + /* Allocate and fill in envstr. */ + if ((envstr = malloc(esize)) == NULL) + return -1; + for (src = var, dst = envstr; *src != '\0' && *src != '=';) + *dst++ = *src++; + *dst++ = '='; + if (val) { + for (src = val; *src != '\0';) + *dst++ = *src++; + } + *dst = '\0'; + + if (!overwrite && getenv(var) != NULL) { + free(envstr); + return 0; + } + return putenv(envstr); +} diff --git a/siglist.in b/compat/siglist.in similarity index 100% rename from siglist.in rename to compat/siglist.in diff --git a/snprintf.c b/compat/snprintf.c similarity index 93% rename from snprintf.c rename to compat/snprintf.c index 3035232..8a77a5b 100644 --- a/snprintf.c +++ b/compat/snprintf.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005, 2008, 2010 + * Copyright (c) 1999-2005, 2008, 2010-2011 * Todd C. Miller * Copyright (c) 1990, 1993 * The Regents of the University of California. All rights reserved. @@ -69,16 +69,11 @@ # include #endif /* HAVE_MALLOC_H && !STDC_HEADERS */ #include - -#ifdef __STDC__ -# include -#else -# include -#endif +#include #include "missing.h" -static int xxxprintf __P((char **, size_t, int, const char *, va_list)); +static int xxxprintf(char **, size_t, int, const char *, va_list); /* * Some systems may not have these defined in @@ -127,25 +122,6 @@ static int xxxprintf __P((char **, size_t, int, const char *, va_list)); #define BUF 68 -#ifndef HAVE_MEMCHR -void * -memchr(s, c, n) - const void *s; - unsigned char c; - size_t n; -{ - if (n != 0) { - const unsigned char *p = s; - - do { - if (*p++ == c) - return (void *)(p - 1); - } while (--n != 0); - } - return NULL; -} -#endif /* !HAVE_MEMCHR */ - /* * Convert an unsigned long to ASCII for printf purposes, returning * a pointer to the first character of the string representation. @@ -153,11 +129,7 @@ memchr(s, c, n) * use the given digits. */ static char * -__ultoa(val, endp, base, octzero, xdigs) - unsigned long val; - char *endp; - int base, octzero; - char *xdigs; +__ultoa(unsigned long val, char *endp, int base, int octzero, char *xdigs) { char *cp = endp; long sval; @@ -217,11 +189,7 @@ __ultoa(val, endp, base, octzero, xdigs) # define __uqtoa(v, e, b, o, x) __ultoa((unsigned long)(v), (e), (b), (o), (x)) # else static char * -__uqtoa(val, endp, base, octzero, xdigs) - unsigned long long val; - char *endp; - int base, octzero; - char *xdigs; +__uqtoa(unsigned long long val, char *endp, int base, int octzero, char *xdigs) { char *cp = endp; long long sval; @@ -275,12 +243,7 @@ __uqtoa(val, endp, base, octzero, xdigs) * Actual printf innards. */ static int -xxxprintf(strp, strsize, alloc, fmt0, ap) - char **strp; - size_t strsize; - int alloc; - const char *fmt0; - va_list ap; +xxxprintf(char **strp, size_t strsize, int alloc, const char *fmt0, va_list ap) { char *fmt; /* format string */ int ch; /* character from fmt */ @@ -699,11 +662,7 @@ done: #ifndef HAVE_VSNPRINTF int -vsnprintf(str, n, fmt, ap) - char *str; - size_t n; - const char *fmt; - va_list ap; +vsnprintf(char *str, size_t n, const char *fmt, va_list ap) { return xxxprintf(&str, n, 0, fmt, ap); @@ -712,24 +671,12 @@ vsnprintf(str, n, fmt, ap) #ifndef HAVE_SNPRINTF int -#ifdef __STDC__ snprintf(char *str, size_t n, char const *fmt, ...) -#else -snprintf(str, n, fmt, va_alist) - char *str; - size_t n; - char const *fmt; - va_dcl -#endif { int ret; va_list ap; -#ifdef __STDC__ va_start(ap, fmt); -#else - va_start(ap); -#endif ret = xxxprintf(&str, n, 0, fmt, ap); va_end(ap); return ret; @@ -738,10 +685,7 @@ snprintf(str, n, fmt, va_alist) #ifndef HAVE_VASPRINTF int -vasprintf(str, fmt, ap) - char **str; - const char *fmt; - va_list ap; +vasprintf(char **str, const char *fmt, va_list ap) { return xxxprintf(str, 0, 1, fmt, ap); @@ -750,23 +694,12 @@ vasprintf(str, fmt, ap) #ifndef HAVE_ASPRINTF int -#ifdef __STDC__ asprintf(char **str, char const *fmt, ...) -#else -asprintf(str, fmt, va_alist) - char **str; - char const *fmt; - va_dcl -#endif { int ret; va_list ap; -#ifdef __STDC__ va_start(ap, fmt); -#else - va_start(ap); -#endif ret = xxxprintf(str, 0, 1, fmt, ap); va_end(ap); return ret; diff --git a/strlcat.c b/compat/strlcat.c similarity index 91% rename from strlcat.c rename to compat/strlcat.c index 77f6c86..57e3ca5 100644 --- a/strlcat.c +++ b/compat/strlcat.c @@ -1,7 +1,8 @@ /* $OpenBSD: strlcat.c,v 1.8 2001/05/13 15:40:15 deraadt Exp $ */ /* - * Copyright (c) 1998, 2003-2005 Todd C. Miller + * Copyright (c) 1998, 2003-2005, 2010-2011 + * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -31,10 +32,7 @@ * If retval >= siz, truncation occurred. */ size_t -strlcat(dst, src, siz) - char *dst; - const char *src; - size_t siz; +strlcat(char *dst, const char *src, size_t siz) { char *d = dst; const char *s = src; diff --git a/strlcpy.c b/compat/strlcpy.c similarity index 91% rename from strlcpy.c rename to compat/strlcpy.c index df2e677..89fb01b 100644 --- a/strlcpy.c +++ b/compat/strlcpy.c @@ -1,7 +1,8 @@ /* $OpenBSD: strlcpy.c,v 1.5 2001/05/13 15:40:16 deraadt Exp $ */ /* - * Copyright (c) 1998, 2003-2005 Todd C. Miller + * Copyright (c) 1998, 2003-2005, 2010-2011 + * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -28,10 +29,7 @@ * Returns strlen(src); if retval >= siz, truncation occurred. */ size_t -strlcpy(dst, src, siz) - char *dst; - const char *src; - size_t siz; +strlcpy(char *dst, const char *src, size_t siz) { char *d = dst; const char *s = src; diff --git a/strsignal.c b/compat/strsignal.c similarity index 93% rename from strsignal.c rename to compat/strsignal.c index a551429..1e5d791 100644 --- a/strsignal.c +++ b/compat/strsignal.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2010 Todd C. Miller + * Copyright (c) 2009-2011 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -37,8 +37,7 @@ extern const char *const my_sys_siglist[NSIG]; * Get signal description string */ char * -strsignal(signo) - int signo; +strsignal(int signo) { if (signo > 0 && signo < NSIG) return (char *)my_sys_siglist[signo]; diff --git a/emul/timespec.h b/compat/timespec.h similarity index 92% rename from emul/timespec.h rename to compat/timespec.h index 681c523..4c9dedc 100644 --- a/emul/timespec.h +++ b/compat/timespec.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005 Todd C. Miller + * Copyright (c) 2005, 2010 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above diff --git a/compat/unsetenv.c b/compat/unsetenv.c new file mode 100644 index 0000000..f7cfaa7 --- /dev/null +++ b/compat/unsetenv.c @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2010 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include + +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#include + +#include "missing.h" + +extern char **environ; /* global environment */ + +#ifdef UNSETENV_VOID +void +#else +int +#endif +unsetenv(const char *var) +{ + char **ep = environ; + size_t len; + + if (var == NULL || *var == '\0' || strchr(var, '=') != NULL) { + errno = EINVAL; +#ifdef UNSETENV_VOID + return; +#else + return -1; +#endif + } + + len = strlen(var); + while (*ep != NULL) { + if (strncmp(var, *ep, len) == 0 && (*ep)[len] == '=') { + /* Found it; shift remainder + NULL over by one. */ + char **cur = ep; + while ((*cur = *(cur + 1)) != NULL) + cur++; + /* Keep going, could be multiple instances of the var. */ + } else { + ep++; + } + } +#ifndef UNSETENV_VOID + return 0; +#endif +} diff --git a/emul/utime.h b/compat/utime.h similarity index 88% rename from emul/utime.h rename to compat/utime.h index e5c63a5..0a1eb86 100644 --- a/emul/utime.h +++ b/compat/utime.h @@ -1,5 +1,6 @@ /* - * Copyright (c) 1996, 1998-2005 Todd C. Miller + * Copyright (c) 1996, 1998-2005, 2010 + * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -22,10 +23,6 @@ struct utimbuf { time_t modtime; /* mod time */ }; -#ifdef __STDC__ int utime(const char *, const struct utimbuf *); -#else -int utime(); -#endif #endif /* _UTIME_H */ diff --git a/utimes.c b/compat/utimes.c similarity index 87% rename from utimes.c rename to compat/utimes.c index 5ff4379..455ecd2 100644 --- a/utimes.c +++ b/compat/utimes.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2004-2005, 2007 Todd C. Miller + * Copyright (c) 2004-2005, 2007, 2010-2011 + * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -26,7 +27,7 @@ #ifdef HAVE_UTIME_H # include #else -# include "emul/utime.h" +# include "compat/utime.h" #endif #include "missing.h" @@ -36,9 +37,7 @@ * Emulate utimes() via utime() */ int -utimes(file, times) - const char *file; - const struct timeval *times; +utimes(const char *file, const struct timeval *times) { if (times != NULL) { struct utimbuf utb; @@ -56,9 +55,7 @@ utimes(file, times) * Emulate futimes() via futime() */ int -futimes(fd, times) - int fd; - const struct timeval *times; +futimes(int fd, const struct timeval *times) { if (times != NULL) { struct utimbuf utb; diff --git a/config.h.in b/config.h.in index a4b000d..0f7384d 100644 --- a/config.h.in +++ b/config.h.in @@ -107,6 +107,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_DLFCN_H +/* Define to 1 if you have the `dlopen' function. */ +#undef HAVE_DLOPEN + /* Define to 1 if your glob.h defines the GLOB_BRACE and GLOB_TILDE flags. */ #undef HAVE_EXTENDED_GLOB @@ -173,6 +176,9 @@ passwords) */ #undef HAVE_GETPWANAM +/* Define to 1 if you have the `getresuid' function. */ +#undef HAVE_GETRESUID + /* Define to 1 if you have the `getspnam' function (SVR4-style shadow passwords) */ #undef HAVE_GETSPNAM @@ -181,8 +187,8 @@ passwords) */ #undef HAVE_GETSPWUID -/* Define to 1 if you have the `gettimeofday' function. */ -#undef HAVE_GETTIMEOFDAY +/* Define to 1 if you have the `getttyent' function. */ +#undef HAVE_GETTTYENT /* Define to 1 if you have the `getuserattr' function. */ #undef HAVE_GETUSERATTR @@ -304,9 +310,6 @@ /* Define to 1 if you have the `ldap_unbind_ext_s' function. */ #undef HAVE_LDAP_UNBIND_EXT_S -/* Define to 1 if you have the `dl' library (-ldl). */ -#undef HAVE_LIBDL - /* Define to 1 to enable Linux audit support. */ #undef HAVE_LINUX_AUDIT @@ -331,20 +334,14 @@ /* Define to 1 if you have the `mbr_check_membership' function. */ #undef HAVE_MBR_CHECK_MEMBERSHIP -/* Define to 1 if you have the `memchr' function. */ -#undef HAVE_MEMCHR - -/* Define to 1 if you have the `memcpy' function. */ -#undef HAVE_MEMCPY - /* Define to 1 if you have the header file. */ #undef HAVE_MEMORY_H /* Define to 1 if you have the `memrchr' function. */ #undef HAVE_MEMRCHR -/* Define to 1 if you have the `memset' function. */ -#undef HAVE_MEMSET +/* Define to 1 if you have the `mkdtemp' function. */ +#undef HAVE_MKDTEMP /* Define to 1 if you have the `mkstemps' function. */ #undef HAVE_MKSTEMPS @@ -385,6 +382,9 @@ /* Define to 1 if you have the `posix_openpt' function. */ #undef HAVE_POSIX_OPENPT +/* Define to 1 if you have the `priv_set' function. */ +#undef HAVE_PRIV_SET + /* Define to 1 if you have the header file. */ #undef HAVE_PROJECT_H @@ -400,6 +400,10 @@ /* Define to 1 if you have the `revoke' function. */ #undef HAVE_REVOKE +/* Define to 1 if the skeychallenge() function is RFC1938-compliant and takes + 4 arguments */ +#undef HAVE_RFC1938_SKEYCHALLENGE + /* Define to 1 if you have the header file. */ #undef HAVE_SASL_H @@ -439,24 +443,18 @@ /* Define to 1 if you have the `setreuid' function. */ #undef HAVE_SETREUID -/* Define to 1 if you have the `setrlimit' function. */ -#undef HAVE_SETRLIMIT - /* Define to 1 if you have the `setrlimit64' function. */ #undef HAVE_SETRLIMIT64 -/* Define to 1 if you have the `setsid' function. */ -#undef HAVE_SETSID - /* Define to 1 if you have the `set_auth_parameters' function. */ #undef HAVE_SET_AUTH_PARAMETERS +/* Define to 1 if you have the `shl_load' function. */ +#undef HAVE_SHL_LOAD + /* Define to 1 if you have the `sia_ses_init' function. */ #undef HAVE_SIA_SES_INIT -/* Define to 1 if you have the `sigaction' function. */ -#undef HAVE_SIGACTION - /* Define to 1 if has the sigaction_t typedef. */ #undef HAVE_SIGACTION_T @@ -475,15 +473,6 @@ /* Define to 1 if you have the header file. */ #undef HAVE_STDLIB_H -/* Define to 1 if you have the `strcasecmp' function. */ -#undef HAVE_STRCASECMP - -/* Define to 1 if you have the `strchr' function. */ -#undef HAVE_STRCHR - -/* Define to 1 if you have the `strerror' function. */ -#undef HAVE_STRERROR - /* Define to 1 if you have the `strftime' function. */ #undef HAVE_STRFTIME @@ -508,6 +497,51 @@ /* Define to 1 if the system has the type `struct in6_addr'. */ #undef HAVE_STRUCT_IN6_ADDR +/* Define to 1 if `ut_exit' is a member of `struct utmpx'. */ +#undef HAVE_STRUCT_UTMPX_UT_EXIT + +/* Define to 1 if `ut_exit.e_termination' is a member of `struct utmpx'. */ +#undef HAVE_STRUCT_UTMPX_UT_EXIT_E_TERMINATION + +/* Define to 1 if `ut_exit.__e_termination' is a member of `struct utmpx'. */ +#undef HAVE_STRUCT_UTMPX_UT_EXIT___E_TERMINATION + +/* Define to 1 if `ut_id' is a member of `struct utmpx'. */ +#undef HAVE_STRUCT_UTMPX_UT_ID + +/* Define to 1 if `ut_pid' is a member of `struct utmpx'. */ +#undef HAVE_STRUCT_UTMPX_UT_PID + +/* Define to 1 if `ut_tv' is a member of `struct utmpx'. */ +#undef HAVE_STRUCT_UTMPX_UT_TV + +/* Define to 1 if `ut_type' is a member of `struct utmpx'. */ +#undef HAVE_STRUCT_UTMPX_UT_TYPE + +/* Define to 1 if `ut_exit' is a member of `struct utmp'. */ +#undef HAVE_STRUCT_UTMP_UT_EXIT + +/* Define to 1 if `ut_exit.e_termination' is a member of `struct utmp'. */ +#undef HAVE_STRUCT_UTMP_UT_EXIT_E_TERMINATION + +/* Define to 1 if `ut_exit.__e_termination' is a member of `struct utmp'. */ +#undef HAVE_STRUCT_UTMP_UT_EXIT___E_TERMINATION + +/* Define to 1 if `ut_id' is a member of `struct utmp'. */ +#undef HAVE_STRUCT_UTMP_UT_ID + +/* Define to 1 if `ut_pid' is a member of `struct utmp'. */ +#undef HAVE_STRUCT_UTMP_UT_PID + +/* Define to 1 if `ut_tv' is a member of `struct utmp'. */ +#undef HAVE_STRUCT_UTMP_UT_TV + +/* Define to 1 if `ut_type' is a member of `struct utmp'. */ +#undef HAVE_STRUCT_UTMP_UT_TYPE + +/* Define to 1 if `ut_user' is a member of `struct utmp'. */ +#undef HAVE_STRUCT_UTMP_UT_USER + /* Define to 1 if your struct stat has an st_mtim member */ #undef HAVE_ST_MTIM @@ -552,19 +586,12 @@ /* Define to 1 if you have the header file. */ #undef HAVE_SYS_TYPES_H -/* Define to 1 if you have the `tcsetpgrp' function. */ -#undef HAVE_TCSETPGRP - -/* Define to 1 if you have the header file and the `tcgetattr' - function. */ -#undef HAVE_TERMIOS_H - -/* Define to 1 if you have the header file. */ -#undef HAVE_TERMIO_H - /* Define to 1 if you have struct timespec in sys/time.h */ #undef HAVE_TIMESPEC +/* Define to 1 if you have the `ttyslot' function. */ +#undef HAVE_TTYSLOT + /* Define to 1 if you have the `tzset' function. */ #undef HAVE_TZSET @@ -583,18 +610,15 @@ /* Define to 1 if you have the header file. */ #undef HAVE_UTIME_H +/* Define to 1 if you have the header file. */ +#undef HAVE_UTMPX_H + /* Define to 1 if you have the `vasprintf' function. */ #undef HAVE_VASPRINTF /* Define to 1 if you have the `vsnprintf' function. */ #undef HAVE_VSNPRINTF -/* Define to 1 if you have the `wait3' function. */ -#undef HAVE_WAIT3 - -/* Define to 1 if you have the `waitpid' function. */ -#undef HAVE_WAITPID - /* Define to 1 if you have the header file. */ #undef HAVE_ZLIB_H @@ -616,9 +640,6 @@ /* The message given when a bad password is entered. */ #undef INCORRECT_PASSWORD -/* The name of libvas.so */ -#undef LIBVAS_SO - /* The syslog facility sudo will use. */ #undef LOGFAC @@ -698,12 +719,6 @@ /* The syslog priority sudo will use for successful attempts. */ #undef PRI_SUCCESS -/* Define to 1 if the `putenv' has a const argument. */ -#undef PUTENV_CONST - -/* Define as the return type of signal handlers (`int' or `void'). */ -#undef RETSIGTYPE - /* The user sudo should run commands as by default. */ #undef RUNAS_DEFAULT @@ -720,9 +735,6 @@ /* Define to 1 to send mail when the user is not in the sudoers file. */ #undef SEND_MAIL_WHEN_NO_USER -/* Define to 1 if the `setpgrp' function takes no argument. */ -#undef SETPGRP_VOID - /* Define to 1 if you want sudo to start a shell if given no arguments. */ #undef SHELL_IF_NO_ARGS @@ -738,6 +750,9 @@ /* Define to 1 if the code in interfaces.c does not compile for you. */ #undef STUB_LOAD_INTERFACES +/* The name of the sudoers plugin, including extension. */ +#undef SUDOERS_PLUGIN + /* The umask that the sudo-run prog should use. */ #undef SUDO_UMASK @@ -768,9 +783,6 @@ /* Define to 1 if you use GNU stow packaging. */ #undef USE_STOW -/* Define to 1 if using a non-Unix group lookup implementation. */ -#undef USING_NONUNIX_GROUPS - /* Define to avoid using the passwd/shadow file for authentication. */ #undef WITHOUT_PASSWD @@ -841,17 +853,6 @@ # endif /* HAVE_ST_MTIMESPEC */ #endif /* HAVE_ST_MTIM */ -/* - * Emulate a subset of waitpid() if we don't have it. - */ -#ifdef HAVE_WAITPID -# define sudo_waitpid(p, s, o) waitpid(p, s, o) -#else -# ifdef HAVE_WAIT3 -# define sudo_waitpid(p, s, o) wait3(s, o, NULL) -# endif -#endif - /* GNU stow needs /etc/sudoers to be a symlink. */ #ifdef USE_STOW # define stat_sudoers stat diff --git a/configure b/configure index 4ac04df..cad0d5c 100755 --- a/configure +++ b/configure @@ -1,6 +1,6 @@ #! /bin/sh # Guess values for system-dependent variables and create Makefiles. -# Generated by GNU Autoconf 2.65 for sudo 1.7.6p1. +# Generated by GNU Autoconf 2.65 for sudo 1.8.1p2. # # Report bugs to . # @@ -173,6 +173,14 @@ test x\$exitcode = x0 || exit 1" as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" && test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1 + + test -n \"\${ZSH_VERSION+set}\${BASH_VERSION+set}\" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + ECHO=\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO\$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test \"X\`printf %s \$ECHO\`\" = \"X\$ECHO\" \\ + || test \"X\`print -r -- \$ECHO\`\" = \"X\$ECHO\" ) || exit 1 test \$(( 1 + 1 )) = 2 || exit 1" if (eval "$as_required") 2>/dev/null; then : as_have_required=yes @@ -528,155 +536,8 @@ as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'" # Sed expression to map a string onto a valid variable name. as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'" - - -# Check that we are running under the correct shell. SHELL=${CONFIG_SHELL-/bin/sh} -case X$lt_ECHO in -X*--fallback-echo) - # Remove one level of quotation (which was required for Make). - ECHO=`echo "$lt_ECHO" | sed 's,\\\\\$\\$0,'$0','` - ;; -esac - -ECHO=${lt_ECHO-echo} -if test "X$1" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift -elif test "X$1" = X--fallback-echo; then - # Avoid inline document here, it may be left over - : -elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then - # Yippee, $ECHO works! - : -else - # Restart under the correct shell. - exec $SHELL "$0" --no-reexec ${1+"$@"} -fi - -if test "X$1" = X--fallback-echo; then - # used as fallback echo - shift - cat <<_LT_EOF -$* -_LT_EOF - exit 0 -fi - -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -if test -z "$lt_ECHO"; then - if test "X${echo_test_string+set}" != Xset; then - # find a string as large as possible, as long as the shell can cope with it - for cmd in 'sed 50q "$0"' 'sed 20q "$0"' 'sed 10q "$0"' 'sed 2q "$0"' 'echo test'; do - # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... - if { echo_test_string=`eval $cmd`; } 2>/dev/null && - { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null - then - break - fi - done - fi - - if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && - echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - : - else - # The Solaris, AIX, and Digital Unix default echo programs unquote - # backslashes. This makes it impossible to quote backslashes using - # echo "$something" | sed 's/\\/\\\\/g' - # - # So, first we look for a working echo in the user's PATH. - - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for dir in $PATH /usr/ucb; do - IFS="$lt_save_ifs" - if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && - test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - ECHO="$dir/echo" - break - fi - done - IFS="$lt_save_ifs" - - if test "X$ECHO" = Xecho; then - # We didn't find a better echo, so look for alternatives. - if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' && - echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # This shell has a builtin print -r that does the trick. - ECHO='print -r' - elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } && - test "X$CONFIG_SHELL" != X/bin/ksh; then - # If we have ksh, try running configure again with it. - ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} - export ORIGINAL_CONFIG_SHELL - CONFIG_SHELL=/bin/ksh - export CONFIG_SHELL - exec $CONFIG_SHELL "$0" --no-reexec ${1+"$@"} - else - # Try using printf. - ECHO='printf %s\n' - if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && - echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # Cool, printf works - : - elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($ORIGINAL_CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL - export CONFIG_SHELL - SHELL="$CONFIG_SHELL" - export SHELL - ECHO="$CONFIG_SHELL $0 --fallback-echo" - elif echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($CONFIG_SHELL "$0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - ECHO="$CONFIG_SHELL $0 --fallback-echo" - else - # maybe with a smaller string... - prev=: - - for cmd in 'echo test' 'sed 2q "$0"' 'sed 10q "$0"' 'sed 20q "$0"' 'sed 50q "$0"'; do - if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null - then - break - fi - prev="$cmd" - done - - if test "$prev" != 'sed 50q "$0"'; then - echo_test_string=`eval $prev` - export echo_test_string - exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "$0" ${1+"$@"} - else - # Oops. We lost completely, so just stick with echo. - ECHO=echo - fi - fi - fi - fi - fi -fi - -# Copy echo and quote the copy suitably for passing to libtool from -# the Makefile, instead of quoting the original, which is used later. -lt_ECHO=$ECHO -if test "X$lt_ECHO" = "X$CONFIG_SHELL $0 --fallback-echo"; then - lt_ECHO="$CONFIG_SHELL \\\$\$0 --fallback-echo" -fi - - - test -n "$DJDIR" || exec 7<&0 &1 @@ -701,11 +562,12 @@ MAKEFLAGS= # Identity of this package. PACKAGE_NAME='sudo' PACKAGE_TARNAME='sudo' -PACKAGE_VERSION='1.7.6p1' -PACKAGE_STRING='sudo 1.7.6p1' +PACKAGE_VERSION='1.8.1p2' +PACKAGE_STRING='sudo 1.8.1p2' PACKAGE_BUGREPORT='http://www.sudo.ws/bugs/' PACKAGE_URL='' +ac_config_libobj_dir=compat # Factoring default headers for most tests. ac_includes_default="\ #include @@ -756,7 +618,7 @@ OTOOL LIPO NMEDIT DSYMUTIL -lt_ECHO +AWK STRIP OBJDUMP LN_S @@ -818,17 +680,22 @@ password_timeout timeout timedir iolog_dir +LT_STATIC +LIBDL CONFIGURE_ARGS -ZLIB_DEP +ac_config_libobj_dir +LIBTOOL_DEPS +ZLIB_SRC ZLIB LOGINCAP_USAGE -REPLAY LDAP SELINUX_USAGE BSDAUTH_USAGE DONT_LEAK_PATH_INFO INSTALL_NOEXEC noexec_file +SOEXT +PLUGINDIR NOEXECDIR NOEXECFILE mansrcdir @@ -847,12 +714,16 @@ MANTYPE AUTH_OBJS OSDEFS GETGROUPS_LIB +REPLAY_LIBS AFS_LIBS NET_LIBS +SUDOERS_LIBS SUDO_LIBS SUDO_OBJS -SUDO_LDFLAGS +SUDOERS_OBJS COMMON_OBJS +LTLDFLAGS +SUDOERS_LDFLAGS LDFLAGS CPPFLAGS PROGS @@ -975,8 +846,7 @@ with_secure_path with_interfaces with_stow with_askpass -with_libvas -with_libvas_rpath +with_plugindir enable_authentication enable_root_mailer enable_setreuid @@ -988,6 +858,7 @@ enable_noargs_shell enable_shell_sets_home enable_path_info enable_env_debug +enable_zlib enable_env_reset enable_warnings enable_admin_flag @@ -1005,7 +876,6 @@ enable_sia enable_largefile with_pam_login enable_pam_session -enable_zlib ' ac_precious_vars='build_alias host_alias @@ -1559,7 +1429,7 @@ if test "$ac_init_help" = "long"; then # Omit some internal or obsolete options to make the list less imposing. # This message is too long to be a string in the A/UX 3.1 sh. cat <<_ACEOF -\`configure' configures sudo 1.7.6p1 to adapt to many kinds of systems. +\`configure' configures sudo 1.8.1p2 to adapt to many kinds of systems. Usage: $0 [OPTION]... [VAR=VALUE]... @@ -1624,7 +1494,7 @@ fi if test -n "$ac_init_help"; then case $ac_init_help in - short | recursive ) echo "Configuration of sudo 1.7.6p1:";; + short | recursive ) echo "Configuration of sudo 1.8.1p2:";; esac cat <<\_ACEOF @@ -1645,6 +1515,7 @@ Optional Features: Set $HOME to target user in shell mode --disable-path-info Print 'command not allowed' not 'command not found' --enable-env-debug Whether to enable environment debugging. + --enable-zlib[=PATH] Whether to enable or disable zlib --enable-env-reset Whether to enable environment resetting by default. --enable-warnings Whether to enable compiler warnings --enable-admin-flag Whether to create a Ubuntu-style admin flag file @@ -1658,7 +1529,6 @@ Optional Features: --disable-sia Disable SIA on Digital UNIX --disable-largefile omit support for large files --disable-pam-session Disable PAM session support - --enable-zlib[=PATH] Whether to enable or disable zlib Optional Packages: --with-PACKAGE[=ARG] use PACKAGE [ARG=yes] @@ -1746,10 +1616,7 @@ Optional Packages: --without-interfaces don't try to read the ip addr of ether interfaces --with-stow properly handle GNU stow packaging --with-askpass=PATH Fully qualified pathname of askpass helper - --with-libvas=NAME Name of the libvas shared library - (default=libvas.so) - --with-libvas-rpath=PATH - Path to look for libvas in [default=/opt/quest/lib] + --with-plugindir set directory to load plugins from --with-selinux enable SELinux support --with-pic try to use only PIC/non-PIC objects [default=use both] @@ -1839,7 +1706,7 @@ fi test -n "$ac_init_help" && exit $ac_status if $ac_init_version; then cat <<\_ACEOF -sudo configure 1.7.6p1 +sudo configure 1.8.1p2 generated by GNU Autoconf 2.65 Copyright (C) 2009 Free Software Foundation, Inc. @@ -2538,7 +2405,7 @@ cat >config.log <<_ACEOF This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake. -It was created by sudo $as_me 1.7.6p1, which was +It was created by sudo $as_me 1.8.1p2, which was generated by GNU Autoconf 2.65. Invocation command line was $ $0 $@ @@ -2885,7 +2752,7 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ac_compiler_gnu=$ac_cv_c_compiler_gnu -ac_config_headers="$ac_config_headers config.h pathnames.h zlib/zconf.h" +ac_config_headers="$ac_config_headers config.h pathnames.h" { $as_echo "$as_me:${as_lineno-$LINENO}: Configuring Sudo version $PACKAGE_VERSION" >&5 $as_echo "$as_me: Configuring Sudo version $PACKAGE_VERSION" >&6;} @@ -2955,6 +2822,15 @@ $as_echo "$as_me: Configuring Sudo version $PACKAGE_VERSION" >&6;} + + + + + + + + + @@ -3009,7 +2885,7 @@ secure_path="not set" # INSTALL_NOEXEC= devdir='$(srcdir)' -PROGS="sudo visudo" +PROGS="sudo" : ${MANTYPE='man'} : ${mansrcdir='.'} : ${SUDOERS_MODE='0440'} @@ -3017,12 +2893,11 @@ PROGS="sudo visudo" : ${SUDOERS_GID='0'} DEV="#" LDAP="#" -REPLAY="#" BAMAN=0 LCMAN=0 SEMAN=0 ZLIB= -ZLIB_DEP= +ZLIB_SRC= AUTH_OBJS= AUTH_REG= AUTH_EXCL= @@ -3034,11 +2909,12 @@ shadow_defs= shadow_funcs= shadow_libs= shadow_libs_optional= - CONFIGURE_ARGS="$@" + + # Check whether --with-otp-only was given. if test "${with_otp_only+set}" = set; then : withval=$with_otp_only; case $with_otp_only in @@ -3069,7 +2945,6 @@ if test "${with_devel+set}" = set; then : withval=$with_devel; case $with_devel in yes) { $as_echo "$as_me:${as_lineno-$LINENO}: Setting up for development: -Wall, flex, yacc" >&5 $as_echo "$as_me: Setting up for development: -Wall, flex, yacc" >&6;} - PROGS="${PROGS} testsudoers" OSDEFS="${OSDEFS} -DSUDO_DEVEL" DEV="" devdir=. @@ -3125,8 +3000,8 @@ if test "${with_bsm_audit+set}" = set; then : withval=$with_bsm_audit; case $with_bsm_audit in yes) $as_echo "#define HAVE_BSM_AUDIT 1" >>confdefs.h - SUDO_LIBS="${SUDO_LIBS} -lbsm" - SUDO_OBJS="${SUDO_OBJS} bsm_audit.o" + SUDOERS_LIBS="${SUDOERS_LIBS} -lbsm" + SUDOERS_OBJS="${SUDOERS_OBJS} bsm_audit.lo" ;; no) ;; *) as_fn_error "\"--with-bsm-audit does not take an argument.\"" "$LINENO" 5 @@ -3947,7 +3822,8 @@ if ac_fn_c_try_compile "$LINENO"; then : $as_echo "#define HAVE_LINUX_AUDIT 1" >>confdefs.h SUDO_LIBS="${SUDO_LIBS} -laudit" - SUDO_OBJS="${SUDO_OBJS} linux_audit.o" + SUDOERS_LIBS="${SUDO_LIBS} -laudit" + SUDOERS_OBJS="${SUDOERS_OBJS} linux_audit.lo" else @@ -4685,8 +4561,9 @@ fi # Check whether --with-iologdir was given. if test "${with_iologdir+set}" = set; then : withval=$with_iologdir; case $with_iologdir in - yes) ;; - no) ;; + yes) ;; + no) as_fn_error "\"--without-iologdir not supported.\"" "$LINENO" 5 + ;; esac fi @@ -5279,77 +5156,15 @@ fi -# Check whether --with-libvas was given. -if test "${with_libvas+set}" = set; then : - withval=$with_libvas; case $with_libvas in - yes) with_libvas=libvas.so - ;; - no) ;; - *) -cat >>confdefs.h <<_ACEOF -#define LIBVAS_SO "$with_libvas" -_ACEOF - +# Check whether --with-plugindir was given. +if test "${with_plugindir+set}" = set; then : + withval=$with_plugindir; case $with_plugindir in + no) as_fn_error "\"illegal argument: --without-plugindir.\"" "$LINENO" 5 ;; + *) ;; esac -if test X"$with_libvas" != X"no"; then - -cat >>confdefs.h <<_ACEOF -#define LIBVAS_SO "$with_libvas" -_ACEOF - - $as_echo "#define USING_NONUNIX_GROUPS 1" >>confdefs.h - - COMMON_OBJS="$COMMON_OBJS vasgroups.o" - -# Check whether --with-libvas-rpath was given. -if test "${with_libvas_rpath+set}" = set; then : - withval=$with_libvas_rpath; LIBVAS_RPATH=$withval -else - LIBVAS_RPATH=/opt/quest/lib -fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -ldl" >&5 -$as_echo_n "checking for main in -ldl... " >&6; } -if test "${ac_cv_lib_dl_main+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldl $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - -int -main () -{ -return main (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_dl_main=yes else - ac_cv_lib_dl_main=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_main" >&5 -$as_echo "$ac_cv_lib_dl_main" >&6; } -if test "x$ac_cv_lib_dl_main" = x""yes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_LIBDL 1 -_ACEOF - - LIBS="-ldl $LIBS" - -fi - -fi - + with_plugindir="$libexecdir" fi @@ -5608,6 +5423,12 @@ $as_echo "no" >&6; } fi +# Check whether --enable-zlib was given. +if test "${enable_zlib+set}" = set; then : + enableval=$enable_zlib; +fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to enable environment resetting by default" >&5 $as_echo_n "checking whether to enable environment resetting by default... " >&6; } # Check whether --enable-env_reset was given. @@ -6117,6 +5938,10 @@ if test X"$AR" = X"false"; then as_fn_error "the \"ar\" utility is required to build sudo" "$LINENO" 5 fi +if test "x$ac_cv_prog_cc_c89" = "xno"; then + as_fn_error "Sudo version $PACKAGE_VERSION requires an ANSI C compiler to build." "$LINENO" 5 +fi + ac_aux_dir= for ac_dir in "$srcdir" "$srcdir/.." "$srcdir/../.."; do for ac_t in install-sh install.sh shtool; do @@ -6221,8 +6046,8 @@ esac -macro_version='2.2.6b' -macro_revision='1.3017' +macro_version='2.2.10' +macro_revision='1.3175' @@ -6238,6 +6063,75 @@ macro_revision='1.3017' ltmain="$ac_aux_dir/ltmain.sh" +# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\(["`$\\]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\(["`\\]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' + +ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to print strings" >&5 +$as_echo_n "checking how to print strings... " >&6; } +# Test print first, because it will be a builtin if present. +if test "X`print -r -- -n 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' +else + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' +fi + +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "" +} + +case "$ECHO" in + printf*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: printf" >&5 +$as_echo "printf" >&6; } ;; + print*) { $as_echo "$as_me:${as_lineno-$LINENO}: result: print -r" >&5 +$as_echo "print -r" >&6; } ;; + *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: cat" >&5 +$as_echo "cat" >&6; } ;; +esac + + + + + + + + + + + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for a sed that does not truncate output" >&5 $as_echo_n "checking for a sed that does not truncate output... " >&6; } if test "${ac_cv_path_SED+set}" = set; then : @@ -6703,8 +6597,11 @@ if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. - if test -n "$ac_tool_prefix"; then - for ac_prog in "dumpbin -symbols" "link -dump -symbols" + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + if test -n "$ac_tool_prefix"; then + for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args. set dummy $ac_tool_prefix$ac_prog; ac_word=$2 @@ -6748,7 +6645,7 @@ fi fi if test -z "$DUMPBIN"; then ac_ct_DUMPBIN=$DUMPBIN - for ac_prog in "dumpbin -symbols" "link -dump -symbols" + for ac_prog in dumpbin "link -dump" do # Extract the first word of "$ac_prog", so it can be a program name with args. set dummy $ac_prog; ac_word=$2 @@ -6803,6 +6700,15 @@ esac fi fi + case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols" + ;; + *) + DUMPBIN=: + ;; + esac + fi if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" @@ -6822,13 +6728,13 @@ if test "${lt_cv_nm_interface+set}" = set; then : else lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:6825: $ac_compile\"" >&5) + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&5) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&5 - (eval echo "\"\$as_me:6828: $NM \\\"conftest.$ac_objext\\\"\"" >&5) + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&5) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&5 - (eval echo "\"\$as_me:6831: output\"" >&5) + (eval echo "\"\$as_me:$LINENO: output\"" >&5) cat conftest.out >&5 if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" @@ -6885,6 +6791,11 @@ else lt_cv_sys_max_cmd_len=8192; ;; + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. @@ -6949,8 +6860,8 @@ else # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. - while { test "X"`$SHELL $0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \ - = "XX$teststring$teststring"; } >/dev/null 2>&1 && + while { test "X"`func_fallback_echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` @@ -7221,16 +7132,18 @@ mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. - if ( file / ) >/dev/null 2>&1; then + # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. + if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else - lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; -cegcc) +cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' @@ -7260,6 +7173,10 @@ gnu*) lt_cv_deplibs_check_method=pass_all ;; +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in @@ -7268,11 +7185,11 @@ hpux10.20* | hpux11*) lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]' + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]' lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) - lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9].[0-9]) shared library' + lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|PA-RISC[0-9]\.[0-9]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac @@ -7294,7 +7211,7 @@ irix5* | irix6* | nonstopux*) ;; # This must be Linux ELF. -linux* | k*bsd*-gnu) +linux* | k*bsd*-gnu | kopensolaris*-gnu) lt_cv_deplibs_check_method=pass_all ;; @@ -7710,6 +7627,17 @@ if test -n "$RANLIB"; then old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac + + + + + @@ -7725,6 +7653,49 @@ fi + +for ac_prog in gawk mawk nawk awk +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_prog_AWK+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$AWK"; then + ac_cv_prog_AWK="$AWK" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_prog_AWK="$ac_prog" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +AWK=$ac_cv_prog_AWK +if test -n "$AWK"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $AWK" >&5 +$as_echo "$AWK" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$AWK" && break +done + @@ -7879,8 +7850,8 @@ _LT_EOF test $ac_status = 0; }; then # Now try to grab the symbols. nlist=conftest.nm - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist\""; } >&5 - (eval $NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) 2>&5 + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist\""; } >&5 + (eval $NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } && test -s "$nlist"; then @@ -8033,7 +8004,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '#line 8036 "configure"' > conftest.$ac_ext + echo '#line '$LINENO' "configure"' > conftest.$ac_ext if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? @@ -8745,6 +8716,38 @@ rm -f core conftest.err conftest.$ac_objext \ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_exported_symbols_list" >&5 $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -force_load linker flag" >&5 +$as_echo_n "checking for -force_load linker flag... " >&6; } +if test "${lt_cv_ld_force_load+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&5 + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&5 + echo "$AR cru libconftest.a conftest.o" >&5 + $AR cru libconftest.a conftest.o 2>&5 + echo "$RANLIB libconftest.a" >&5 + $RANLIB libconftest.a 2>&5 + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&5 + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&5 + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_ld_force_load" >&5 +$as_echo "$lt_cv_ld_force_load" >&6; } case $host_os in rhapsody* | darwin1.[012]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; @@ -8772,7 +8775,7 @@ $as_echo "$lt_cv_ld_exported_symbols_list" >&6; } else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi - if test "$DSYMUTIL" != ":"; then + if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= @@ -8926,11 +8929,12 @@ done -# Set options +# Set options +enable_dlopen=yes + - enable_dlopen=no enable_win32_dll=no @@ -9076,6 +9080,7 @@ LIBTOOL='$(SHELL) $(top_builddir)/libtool' + test -z "$LN_S" && LN_S="ln -s" @@ -9127,19 +9132,6 @@ _ACEOF - - - - - - - - - - - - - case $host_os in aix3*) # AIX sometimes has problems with the GCC collect2 program. For some @@ -9152,32 +9144,15 @@ aix3*) ;; esac -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -sed_quote_subst='s/\(["`$\\]\)/\\\1/g' +# Global variables: +ofile=libtool +can_build_shared=yes -# Same as above, but do not quote variable references. -double_quote_subst='s/\(["`\\]\)/\\\1/g' +# All known linkers require a `.a' archive for static linking (except MSVC, +# which needs '.lib'). +libext=a -# Sed substitution to delay expansion of an escaped shell variable in a -# double_quote_subst'ed string. -delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' - -# Sed substitution to delay expansion of an escaped single quote. -delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' - -# Sed substitution to avoid accidental globbing in evaled expressions -no_glob_subst='s/\*/\\\*/g' - -# Global variables: -ofile=libtool -can_build_shared=yes - -# All known linkers require a `.a' archive for static linking (except MSVC, -# which needs '.lib'). -libext=a - -with_gnu_ld="$lt_cv_prog_gnu_ld" +with_gnu_ld="$lt_cv_prog_gnu_ld" old_CC="$CC" old_CFLAGS="$CFLAGS" @@ -9197,7 +9172,7 @@ for cc_temp in $compiler""; do *) break;; esac done -cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` # Only perform the check for file, if the check method requires it @@ -9406,7 +9381,12 @@ if test -n "$compiler"; then lt_prog_compiler_no_builtin_flag= if test "$GCC" = yes; then - lt_prog_compiler_no_builtin_flag=' -fno-builtin' + case $cc_basename in + nvcc*) + lt_prog_compiler_no_builtin_flag=' -Xcompiler -fno-builtin' ;; + *) + lt_prog_compiler_no_builtin_flag=' -fno-builtin' ;; + esac { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $compiler supports -fno-rtti -fno-exceptions" >&5 $as_echo_n "checking if $compiler supports -fno-rtti -fno-exceptions... " >&6; } @@ -9426,15 +9406,15 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:9429: $lt_compile\"" >&5) + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:9433: \$? = $ac_status" >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. - $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_rtti_exceptions=yes @@ -9512,6 +9492,12 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } lt_prog_compiler_pic='-fno-common' ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + lt_prog_compiler_static= + ;; + hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag @@ -9554,6 +9540,13 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } lt_prog_compiler_pic='-fPIC' ;; esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + lt_prog_compiler_wl='-Xlinker ' + lt_prog_compiler_pic='-Xcompiler -fPIC' + ;; + esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in @@ -9595,7 +9588,7 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } lt_prog_compiler_static='-non_shared' ;; - linux* | k*bsd*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) @@ -9616,7 +9609,7 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } lt_prog_compiler_pic='--shared' lt_prog_compiler_static='--static' ;; - pgcc* | pgf77* | pgf90* | pgf95*) + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) lt_prog_compiler_wl='-Wl,' @@ -9628,25 +9621,25 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } # All Alpha code is PIC. lt_prog_compiler_static='-non_shared' ;; - xl*) - # IBM XL C 8.0/Fortran 10.1 on PPC + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene lt_prog_compiler_wl='-Wl,' lt_prog_compiler_pic='-qpic' lt_prog_compiler_static='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C 5.9 + *Sun\ F* | *Sun*Fortran*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' - lt_prog_compiler_wl='-Wl,' + lt_prog_compiler_wl='' ;; - *Sun\ F*) - # Sun Fortran 8.3 passes all unrecognized flags to the linker + *Sun\ C*) + # Sun C 5.9 lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' - lt_prog_compiler_wl='' + lt_prog_compiler_wl='-Wl,' ;; esac ;; @@ -9678,7 +9671,7 @@ $as_echo_n "checking for $compiler option to produce PIC... " >&6; } lt_prog_compiler_pic='-KPIC' lt_prog_compiler_static='-Bstatic' case $cc_basename in - f77* | f90* | f95*) + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) lt_prog_compiler_wl='-Qoption ld ';; *) lt_prog_compiler_wl='-Wl,';; @@ -9765,15 +9758,15 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:9768: $lt_compile\"" >&5) + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&5 - echo "$as_me:9772: \$? = $ac_status" >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. - $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_pic_works=yes @@ -9821,7 +9814,7 @@ else if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&5 - $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then lt_cv_prog_compiler_static_works=yes @@ -9870,16 +9863,16 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:9873: $lt_compile\"" >&5) + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:9877: \$? = $ac_status" >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings - $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes @@ -9925,16 +9918,16 @@ else -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [^ ]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:9928: $lt_compile\"" >&5) + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&5) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&5 - echo "$as_me:9932: \$? = $ac_status" >&5 + echo "$as_me:$LINENO: \$? = $ac_status" >&5 if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings - $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then lt_cv_prog_compiler_c_o=yes @@ -10047,7 +10040,33 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie esac ld_shlibs=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[2-9]*) ;; + *\ \(GNU\ Binutils\)\ [3-9]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' @@ -10065,6 +10084,7 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie fi supports_anon_versioning=no case `$LD -v 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; *\ [01].* | *\ 2.[0-9].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... @@ -10080,11 +10100,12 @@ $as_echo_n "checking whether the $compiler linker ($LD) supports shared librarie ld_shlibs=no cat <<_LT_EOF 1>&2 -*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to modify your PATH -*** so that a non-GNU linker is found, and then restart. +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. _LT_EOF fi @@ -10120,6 +10141,7 @@ _LT_EOF # _LT_TAGVAR(hardcode_libdir_flag_spec, ) is actually meaningless, # as there is no search path for DLLs. hardcode_libdir_flag_spec='-L$libdir' + export_dynamic_flag_spec='${wl}--export-all-symbols' allow_undefined_flag=unsupported always_export_symbols=no enable_shared_with_static_runtimes=yes @@ -10141,6 +10163,11 @@ _LT_EOF fi ;; + haiku*) + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + link_all_deplibs=yes + ;; + interix[3-9]*) hardcode_direct=no hardcode_shlibpath_var=no @@ -10156,7 +10183,7 @@ _LT_EOF archive_expsym_cmds='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; - gnu* | linux* | tpf* | k*bsd*-gnu) + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in @@ -10170,11 +10197,12 @@ _LT_EOF tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler - whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; - pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers - whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; @@ -10185,13 +10213,17 @@ _LT_EOF lf95*) # Lahey Fortran 8.1 whole_archive_flag_spec= tmp_sharedflag='--shared' ;; - xl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) + xl[cC]* | bgxl[cC]* | mpixl[cC]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + whole_archive_flag_spec='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + compiler_needs_object=yes + ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 - whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + whole_archive_flag_spec='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' compiler_needs_object=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 @@ -10207,17 +10239,17 @@ _LT_EOF fi case $cc_basename in - xlf*) + xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself whole_archive_flag_spec='--whole-archive$convenience --no-whole-archive' hardcode_libdir_flag_spec= hardcode_libdir_flag_spec_ld='-rpath $libdir' - archive_cmds='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib' + archive_cmds='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then archive_expsym_cmds='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ - $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac @@ -10338,8 +10370,10 @@ _LT_EOF else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global + # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + export_symbols_cmds='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else export_symbols_cmds='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && (substr(\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi @@ -10457,7 +10491,7 @@ rm -f core conftest.err conftest.$ac_objext \ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_libdir_flag_spec='${wl}-blibpath:$libdir:'"$aix_libpath" - archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + archive_expsym_cmds='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then hardcode_libdir_flag_spec='${wl}-R $libdir:/usr/lib:/lib' @@ -10501,8 +10535,13 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # -berok will link without error, but may produce a broken library. no_undefined_flag=' ${wl}-bernotok' allow_undefined_flag=' ${wl}-berok' - # Exported symbols can be pulled into shared objects from archives - whole_archive_flag_spec='$convenience' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + whole_archive_flag_spec='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + whole_archive_flag_spec='$convenience' + fi archive_cmds_need_lc=yes # This is similar to how AIX traditionally builds its shared libraries. archive_expsym_cmds="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' @@ -10541,7 +10580,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. - archive_cmds='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames=' + archive_cmds='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. old_archive_from_new_cmds='true' # FIXME: Should let the user specify the lib program. @@ -10557,7 +10596,11 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi hardcode_direct=no hardcode_automatic=yes hardcode_shlibpath_var=unsupported - whole_archive_flag_spec='' + if test "$lt_cv_ld_force_load" = "yes"; then + whole_archive_flag_spec='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + else + whole_archive_flag_spec='' + fi link_all_deplibs=yes allow_undefined_flag="$_lt_dar_allow_undefined" case $cc_basename in @@ -10565,7 +10608,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then - output_verbose_link_cmd=echo + output_verbose_link_cmd=func_echo_all archive_cmds="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" module_cmds="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" archive_expsym_cmds="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" @@ -10631,7 +10674,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; hpux10*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then + if test "$GCC" = yes && test "$with_gnu_ld" = no; then archive_cmds='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' @@ -10650,7 +10693,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi ;; hpux11*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then + if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) archive_cmds='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' @@ -10671,7 +10714,46 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) - archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking if $CC understands -b" >&5 +$as_echo_n "checking if $CC understands -b... " >&6; } +if test "${lt_cv_prog_compiler__b+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_prog_compiler__b=no + save_LDFLAGS="$LDFLAGS" + LDFLAGS="$LDFLAGS -b" + echo "$lt_simple_link_test_code" > conftest.$ac_ext + if (eval $ac_link 2>conftest.err) && test -s conftest$ac_exeext; then + # The linker can only warn and ignore the option if not recognized + # So say no if there are warnings + if test -s conftest.err; then + # Append any errors to the config.log. + cat conftest.err 1>&5 + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp + $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 + if diff conftest.exp conftest.er2 >/dev/null; then + lt_cv_prog_compiler__b=yes + fi + else + lt_cv_prog_compiler__b=yes + fi + fi + $RM -r conftest* + LDFLAGS="$save_LDFLAGS" + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_prog_compiler__b" >&5 +$as_echo "$lt_cv_prog_compiler__b" >&6; } + +if test x"$lt_cv_prog_compiler__b" = xyes; then + archive_cmds='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' +else + archive_cmds='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' +fi + ;; esac fi @@ -10699,7 +10781,7 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. @@ -10710,15 +10792,15 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi int foo(void) {} _ACEOF if ac_fn_c_try_link "$LINENO"; then : - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext LDFLAGS="$save_LDFLAGS" else - archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' - archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + archive_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + archive_expsym_cmds='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' @@ -10780,17 +10862,17 @@ rm -f core conftest.err conftest.$ac_objext \ hardcode_libdir_flag_spec='-L$libdir' hardcode_minus_L=yes allow_undefined_flag=unsupported - archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + archive_cmds='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' old_archive_from_new_cmds='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi archive_cmds_need_lc='no' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' @@ -10800,13 +10882,13 @@ rm -f core conftest.err conftest.$ac_objext \ osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then allow_undefined_flag=' ${wl}-expect_unresolved ${wl}\*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' hardcode_libdir_flag_spec='${wl}-rpath ${wl}$libdir' else allow_undefined_flag=' -expect_unresolved \*' - archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + archive_cmds='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' archive_expsym_cmds='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ - $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly hardcode_libdir_flag_spec='-rpath $libdir' @@ -11009,44 +11091,50 @@ x|xyes) # to ld, don't add -lc before -lgcc. { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether -lc should be explicitly linked in" >&5 $as_echo_n "checking whether -lc should be explicitly linked in... " >&6; } - $RM conftest* - echo "$lt_simple_compile_test_code" > conftest.$ac_ext +if test "${lt_cv_archive_cmds_need_lc+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + $RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_compile\""; } >&5 (eval $ac_compile) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$lt_prog_compiler_wl - pic_flag=$lt_prog_compiler_pic - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$allow_undefined_flag - allow_undefined_flag= - if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$lt_prog_compiler_wl + pic_flag=$lt_prog_compiler_pic + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$allow_undefined_flag + allow_undefined_flag= + if { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1\""; } >&5 (eval $archive_cmds 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; } - then - archive_cmds_need_lc=no - else - archive_cmds_need_lc=yes - fi - allow_undefined_flag=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $RM conftest* - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $archive_cmds_need_lc" >&5 -$as_echo "$archive_cmds_need_lc" >&6; } + then + lt_cv_archive_cmds_need_lc=no + else + lt_cv_archive_cmds_need_lc=yes + fi + allow_undefined_flag=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $lt_cv_archive_cmds_need_lc" >&5 +$as_echo "$lt_cv_archive_cmds_need_lc" >&6; } + archive_cmds_need_lc=$lt_cv_archive_cmds_need_lc ;; esac fi @@ -11217,16 +11305,23 @@ if test "$GCC" = yes; then darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac - lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq="s,=\([A-Za-z]:\),\1,g" ;; + *) lt_sed_strip_eq="s,=/,/,g" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'` - else - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= @@ -11239,7 +11334,7 @@ if test "$GCC" = yes; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done - lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk ' + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; @@ -11259,7 +11354,13 @@ BEGIN {RS=" "; FS="/|\n";} { if (lt_foo != "") { lt_freq[lt_foo]++; } if (lt_freq[lt_foo] == 1) { print lt_foo; } }'` - sys_lib_search_path_spec=`$ECHO $lt_search_path_spec` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's,/\([A-Za-z]:\),\1,g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi @@ -11347,7 +11448,7 @@ amigaos*) m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([^/]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; @@ -11400,23 +11501,12 @@ cygwin* | mingw* | pw32* | cegcc*) cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" + + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api" ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[.]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if $ECHO "$sys_lib_search_path_spec" | $GREP ';[c-zC-Z]:/' >/dev/null; then - # It is most probably a Windows format PATH printed by - # mingw gcc, but we are running on Cygwin. Gcc prints its search - # path with ; separators, and with drive letters. We can handle the - # drive letters (cygwin fileutils understands them), so leave them, - # especially as we might pass files found there to a mingw objdump, - # which wouldn't understand a cygwinified path. Ahh. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' @@ -11516,6 +11606,19 @@ gnu*) hardcode_into_libs=yes ;; +haiku*) + version_type=linux + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. @@ -11558,8 +11661,10 @@ hpux9* | hpux10* | hpux11*) soname_spec='${libname}${release}${shared_ext}$major' ;; esac - # HP-UX runs *really* slowly unless shared libraries are mode 555. + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 ;; interix[3-9]*) @@ -11617,7 +11722,7 @@ linux*oldld* | linux*aout* | linux*coff*) ;; # This must be Linux ELF. -linux* | k*bsd*-gnu) +linux* | k*bsd*-gnu | kopensolaris*-gnu) version_type=linux need_lib_prefix=no need_version=no @@ -11626,12 +11731,17 @@ linux* | k*bsd*-gnu) finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no + # Some binutils ld are patched to set DT_RUNPATH - save_LDFLAGS=$LDFLAGS - save_libdir=$libdir - eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ - LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + if test "${lt_cv_shlibpath_overrides_runpath+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$lt_prog_compiler_wl\"; \ + LDFLAGS=\"\$LDFLAGS $hardcode_libdir_flag_spec\"" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ int @@ -11644,13 +11754,17 @@ main () _ACEOF if ac_fn_c_try_link "$LINENO"; then : if ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null; then : - shlibpath_overrides_runpath=yes + lt_cv_shlibpath_overrides_runpath=yes fi fi rm -f core conftest.err conftest.$ac_objext \ conftest$ac_exeext conftest.$ac_ext - LDFLAGS=$save_LDFLAGS - libdir=$save_libdir + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + +fi + + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install @@ -11659,7 +11773,7 @@ rm -f core conftest.err conftest.$ac_objext \ # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \$2)); skip = 1; } { if (!skip) print \$0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi @@ -11956,6 +12070,11 @@ fi + + + + + @@ -12292,7 +12411,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 12295 "configure" +#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -12333,7 +12452,13 @@ else # endif #endif -void fnord() { int i=42;} +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +void fnord () __attribute__((visibility("default"))); +#endif + +void fnord () { int i=42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); @@ -12342,7 +12467,11 @@ int main () if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } /* dlclose (self); */ } else @@ -12388,7 +12517,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -#line 12391 "configure" +#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -12429,7 +12558,13 @@ else # endif #endif -void fnord() { int i=42;} +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +void fnord () __attribute__((visibility("default"))); +#endif + +void fnord () { int i=42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); @@ -12438,7 +12573,11 @@ int main () if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } /* dlclose (self); */ } else @@ -12618,8 +12757,17 @@ CC="$lt_save_CC" if test "$enable_shared" = "no"; then with_noexec=no + enable_dlopen=no + lt_cv_dlopen=none + lt_cv_dlopen_libs= else eval _shrext="$shrext_cmds" + # Darwin uses .dylib for libraries but .so for modules + if test X"$_shrext" = X".dylib"; then + SOEXT=".so" + else + SOEXT="$_shrext" + fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking path to sudo_noexec.so" >&5 $as_echo_n "checking path to sudo_noexec.so... " >&6; } @@ -12824,11 +12972,22 @@ case "$host" in : ${mansectform='4'} : ${with_rpath='yes'} test -z "$with_pam" && AUTH_EXCL_DEF="PAM" + for ac_func in priv_set +do : + ac_fn_c_check_func "$LINENO" "priv_set" "ac_cv_func_priv_set" +if test "x$ac_cv_func_priv_set" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_PRIV_SET 1 +_ACEOF + +fi +done + ;; *-*-aix*) # To get all prototypes (so we pass -Wall) OSDEFS="${OSDEFS} -D_ALL_SOURCE -D_LINUX_SOURCE_COMPAT" - SUDO_LDFLAGS="${SUDO_LDFLAGS} -Wl,-bI:\$(srcdir)/aixcrypt.exp" + SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -Wl,-bI:\$(srcdir)/aixcrypt.exp" if test X"$with_blibpath" != X"no"; then { $as_echo "$as_me:${as_lineno-$LINENO}: checking if linker accepts -Wl,-blibpath" >&5 $as_echo_n "checking if linker accepts -Wl,-blibpath... " >&6; } @@ -12911,7 +13070,7 @@ _ACEOF fi done - COMMON_OBJS="$COMMON_OBJS aix.o" + COMMON_OBJS="$COMMON_OBJS aix.lo" ;; *-*-hiuxmpp*) : ${mansectsu='1m'} @@ -12926,11 +13085,6 @@ done : ${mansectform='4'} if test -z "$GCC"; then - # HP-UX bundled compiler can't generate shared objects - if test "x$ac_cv_prog_cc_c89" = "xno"; then - with_noexec=no - fi - # Use the +DAportable flag on hppa if it is supported case "$host_cpu" in hppa*) @@ -12976,13 +13130,6 @@ $as_echo "$sudo_cv_var_daportable" >&6; } *-*-hpux1-8.*) $as_echo "#define BROKEN_SYSLOG 1" >>confdefs.h - - # Not sure if setuid binaries are safe in < 9.x - if test -n "$GCC"; then - SUDO_LDFLAGS="${SUDO_LDFLAGS} -static" - else - SUDO_LDFLAGS="${SUDO_LDFLAGS} -Wl,-a,archive" - fi ;; *-*-hpux9.*) $as_echo "#define BROKEN_SYSLOG 1" >>confdefs.h @@ -12993,7 +13140,7 @@ $as_echo "$sudo_cv_var_daportable" >&6; } # DCE support (requires ANSI C compiler) if test "$with_DCE" = "yes"; then # order of libs in 9.X is important. -lc_r must be last - SUDO_LIBS="${SUDO_LIBS} -ldce -lM -lc_r" + SUDOERS_LIBS="${SUDOERS_LIBS} -ldce -lM -lc_r" LIBS="${LIBS} -ldce -lM -lc_r" CPPFLAGS="${CPPFLAGS} -D_REENTRANT -I/usr/include/reentrant" fi @@ -13013,7 +13160,7 @@ $as_echo "$sudo_cv_var_daportable" >&6; } ;; *-dec-osf*) # ignore envariables wrt dynamic lib path - SUDO_LDFLAGS="${SUDO_LDFLAGS} -Wl,-no_library_replacement" + SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -Wl,-no_library_replacement" : ${CHECKSIA='true'} { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to disable sia support on Digital UNIX" >&5 @@ -13186,8 +13333,7 @@ fi *-*-isc*) OSDEFS="${OSDEFS} -D_ISC" LIB_CRYPT=1 - SUDO_LIBS="${SUDO_LIBS} -lcrypt" - LIBS="${LIBS} -lcrypt" + SUDOERS_LIBS="${SUDOERS_LIBS} -lcrypt" shadow_funcs="getspnam" shadow_libs="-lsec" @@ -13252,8 +13398,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_c89_strcasecmp" >&5 $as_echo "$ac_cv_lib_c89_strcasecmp" >&6; } if test "x$ac_cv_lib_c89_strcasecmp" = x""yes; then : - $as_echo "#define HAVE_STRCASECMP 1" >>confdefs.h - LIBS="${LIBS} -lc89"; ac_cv_func_strcasecmp=yes + LIBS="${LIBS} -lc89" fi : ${mansectsu='1m'} @@ -13262,7 +13407,6 @@ fi ;; *-ccur-sysv4*|*-ccur-sysvr4*) LIBS="${LIBS} -lgen" - SUDO_LIBS="${SUDO_LIBS} -lgen" : ${mansectsu='1m'} : ${mansectform='4'} : ${with_rpath='yes'} @@ -13303,7 +13447,7 @@ done ;; esac if test "${with_skey-'no'}" = "yes"; then - SUDO_LIBS="${SUDO_LIBS} -lmd" + SUDOERS_LIBS="${SUDOERS_LIBS} -lmd" fi CHECKSHADOW="false" test -z "$with_pam" && AUTH_EXCL_DEF="PAM" @@ -13339,7 +13483,7 @@ done ;; *-*-dragonfly*) if test "${with_skey-'no'}" = "yes"; then - SUDO_LIBS="${SUDO_LIBS} -lmd" + SUDOERS_LIBS="${SUDOERS_LIBS} -lmd" fi CHECKSHADOW="false" test -z "$with_pam" && AUTH_EXCL_DEF="PAM" @@ -13581,6 +13725,9 @@ $as_echo "#define volatile /**/" >>confdefs.h fi +if test X"$with_gnu_ld" != "yes" -a -n "$GCC"; then + LTLDFLAGS="$LTLDFLAGS -Wc,-static-libgcc" +fi for ac_prog in 'bison -y' byacc do # Extract the first word of "$ac_prog", so it can be a program name with args. @@ -13727,8 +13874,7 @@ $as_echo "not found" >&6; } fi fi -if test -z "$with_editor"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for vi" >&5 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for vi" >&5 $as_echo_n "checking for vi... " >&6; } found=no for editor in "/usr/bin/vi" "/bin/vi" "/usr/ucb/vi" "/usr/bsd/vi" "/usr/local/bin/vi"; do @@ -13748,7 +13894,6 @@ if test X"$found" != X"yes"; then $as_echo "not found" >&6; } fi -fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking which syslog facility sudo should log with" >&5 $as_echo_n "checking which syslog facility sudo should log with... " >&6; } if test X"$with_logfac" = X""; then @@ -14081,7 +14226,7 @@ $as_echo "#define TIME_WITH_SYS_TIME 1" >>confdefs.h fi -for ac_header in malloc.h paths.h utime.h netgroup.h sys/sockio.h sys/bsdtypes.h sys/select.h sys/stropts.h sys/sysmacros.h +for ac_header in malloc.h paths.h utime.h netgroup.h utmpx.h sys/sockio.h sys/bsdtypes.h sys/select.h sys/stropts.h sys/sysmacros.h do : as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh` ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default" @@ -14381,22 +14526,8 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sys_posix_termios" >&5 $as_echo "$ac_cv_sys_posix_termios" >&6; } -if test "$ac_cv_sys_posix_termios" = "yes"; then - $as_echo "#define HAVE_TERMIOS_H 1" >>confdefs.h - -else - for ac_header in termio.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "termio.h" "ac_cv_header_termio_h" "$ac_includes_default" -if test "x$ac_cv_header_termio_h" = x""yes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_TERMIO_H 1 -_ACEOF - -fi - -done - +if test "$ac_cv_sys_posix_termios" != "yes"; then + as_fn_error "Must have POSIX termios to build sudo" "$LINENO" 5 fi maildir=no @@ -14469,8 +14600,10 @@ if test "x$ac_cv_header_login_cap_h" = x""yes; then : _ACEOF LOGINCAP_USAGE='[-c class|-] '; LCMAN=1 case "$OS" in - freebsd|netbsd) SUDO_LIBS="${SUDO_LIBS} -lutil" - ;; + freebsd|netbsd) + SUDO_LIBS="${SUDO_LIBS} -lutil" + SUDOERS_LIBS="${SUDOERS_LIBS} -lutil" + ;; esac fi @@ -14914,121 +15047,277 @@ $as_echo "#define HAVE_SA_LEN 1" >>confdefs.h fi -case "$DEFS" in - *"RETSIGTYPE"*) ;; - *) { $as_echo "$as_me:${as_lineno-$LINENO}: checking return type of signal handlers" >&5 -$as_echo_n "checking return type of signal handlers... " >&6; } -if test "${ac_cv_type_signal+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -#include +_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS $OSDEFS" +if test $ac_cv_header_utmpx_h = "yes"; then + ac_fn_c_check_member "$LINENO" "struct utmpx" "ut_id" "ac_cv_member_struct_utmpx_ut_id" " + #include + #include -int -main () -{ -return *(signal (0, 0)) (0) == 1; - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - ac_cv_type_signal=int -else - ac_cv_type_signal=void -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_signal" >&5 -$as_echo "$ac_cv_type_signal" >&6; } +" +if test "x$ac_cv_member_struct_utmpx_ut_id" = x""yes; then : cat >>confdefs.h <<_ACEOF -#define RETSIGTYPE $ac_cv_type_signal +#define HAVE_STRUCT_UTMPX_UT_ID 1 _ACEOF -;; -esac -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking type of array argument to getgroups" >&5 -$as_echo_n "checking type of array argument to getgroups... " >&6; } -if test "${ac_cv_type_getgroups+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test "$cross_compiling" = yes; then : - ac_cv_type_getgroups=cross -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -/* Thanks to Mike Rendell for this test. */ -$ac_includes_default -#define NGID 256 -#undef MAX -#define MAX(x, y) ((x) > (y) ? (x) : (y)) - -int -main () -{ - gid_t gidset[NGID]; - int i, n; - union { gid_t gval; long int lval; } val; - val.lval = -1; - for (i = 0; i < NGID; i++) - gidset[i] = val.gval; - n = getgroups (sizeof (gidset) / MAX (sizeof (int), sizeof (gid_t)) - 1, - gidset); - /* Exit non-zero if getgroups seems to require an array of ints. This - happens when gid_t is short int but getgroups modifies an array - of ints. */ - return n > 0 && gidset[n] != val.gval; -} -_ACEOF -if ac_fn_c_try_run "$LINENO"; then : - ac_cv_type_getgroups=gid_t -else - ac_cv_type_getgroups=int -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext fi +ac_fn_c_check_member "$LINENO" "struct utmpx" "ut_pid" "ac_cv_member_struct_utmpx_ut_pid" " + #include + #include -if test $ac_cv_type_getgroups = cross; then - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include +" +if test "x$ac_cv_member_struct_utmpx_ut_pid" = x""yes; then : +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_UTMPX_UT_PID 1 _ACEOF -if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | - $EGREP "getgroups.*int.*gid_t" >/dev/null 2>&1; then : - ac_cv_type_getgroups=gid_t -else - ac_cv_type_getgroups=int -fi -rm -f conftest* + fi -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_getgroups" >&5 -$as_echo "$ac_cv_type_getgroups" >&6; } +ac_fn_c_check_member "$LINENO" "struct utmpx" "ut_tv" "ac_cv_member_struct_utmpx_ut_tv" " + #include + #include + +" +if test "x$ac_cv_member_struct_utmpx_ut_tv" = x""yes; then : cat >>confdefs.h <<_ACEOF -#define GETGROUPS_T $ac_cv_type_getgroups +#define HAVE_STRUCT_UTMPX_UT_TV 1 _ACEOF -ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" -if test "x$ac_cv_type_size_t" = x""yes; then : +fi +ac_fn_c_check_member "$LINENO" "struct utmpx" "ut_type" "ac_cv_member_struct_utmpx_ut_type" " + #include + #include -else +" +if test "x$ac_cv_member_struct_utmpx_ut_type" = x""yes; then : cat >>confdefs.h <<_ACEOF -#define size_t unsigned int +#define HAVE_STRUCT_UTMPX_UT_TYPE 1 _ACEOF + fi -ac_fn_c_check_func "$LINENO" "getgroups" "ac_cv_func_getgroups" + ac_fn_c_check_member "$LINENO" "struct utmpx" "ut_exit.__e_termination" "ac_cv_member_struct_utmpx_ut_exit___e_termination" " + #include + #include + +" +if test "x$ac_cv_member_struct_utmpx_ut_exit___e_termination" = x""yes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_UTMPX_UT_EXIT___E_TERMINATION 1 +_ACEOF + +$as_echo "#define HAVE_STRUCT_UTMPX_UT_EXIT 1" >>confdefs.h + +else + + ac_fn_c_check_member "$LINENO" "struct utmpx" "ut_exit.e_termination" "ac_cv_member_struct_utmpx_ut_exit_e_termination" " + #include + #include + +" +if test "x$ac_cv_member_struct_utmpx_ut_exit_e_termination" = x""yes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_UTMPX_UT_EXIT_E_TERMINATION 1 +_ACEOF + +$as_echo "#define HAVE_STRUCT_UTMPX_UT_EXIT 1" >>confdefs.h + +fi + + +fi + +else + ac_fn_c_check_member "$LINENO" "struct utmp" "ut_id" "ac_cv_member_struct_utmp_ut_id" " + #include + #include + +" +if test "x$ac_cv_member_struct_utmp_ut_id" = x""yes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_UTMP_UT_ID 1 +_ACEOF + + +fi +ac_fn_c_check_member "$LINENO" "struct utmp" "ut_pid" "ac_cv_member_struct_utmp_ut_pid" " + #include + #include + +" +if test "x$ac_cv_member_struct_utmp_ut_pid" = x""yes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_UTMP_UT_PID 1 +_ACEOF + + +fi +ac_fn_c_check_member "$LINENO" "struct utmp" "ut_tv" "ac_cv_member_struct_utmp_ut_tv" " + #include + #include + +" +if test "x$ac_cv_member_struct_utmp_ut_tv" = x""yes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_UTMP_UT_TV 1 +_ACEOF + + +fi +ac_fn_c_check_member "$LINENO" "struct utmp" "ut_type" "ac_cv_member_struct_utmp_ut_type" " + #include + #include + +" +if test "x$ac_cv_member_struct_utmp_ut_type" = x""yes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_UTMP_UT_TYPE 1 +_ACEOF + + +fi +ac_fn_c_check_member "$LINENO" "struct utmp" "ut_user" "ac_cv_member_struct_utmp_ut_user" " + #include + #include + +" +if test "x$ac_cv_member_struct_utmp_ut_user" = x""yes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_UTMP_UT_USER 1 +_ACEOF + + +fi + + ac_fn_c_check_member "$LINENO" "struct utmp" "ut_exit.__e_termination" "ac_cv_member_struct_utmp_ut_exit___e_termination" " + #include + #include + +" +if test "x$ac_cv_member_struct_utmp_ut_exit___e_termination" = x""yes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_UTMP_UT_EXIT___E_TERMINATION 1 +_ACEOF + +$as_echo "#define HAVE_STRUCT_UTMP_UT_EXIT 1" >>confdefs.h + +else + + ac_fn_c_check_member "$LINENO" "struct utmp" "ut_exit.e_termination" "ac_cv_member_struct_utmp_ut_exit_e_termination" " + #include + #include + +" +if test "x$ac_cv_member_struct_utmp_ut_exit_e_termination" = x""yes; then : + +cat >>confdefs.h <<_ACEOF +#define HAVE_STRUCT_UTMP_UT_EXIT_E_TERMINATION 1 +_ACEOF + +$as_echo "#define HAVE_STRUCT_UTMP_UT_EXIT 1" >>confdefs.h + +fi + + +fi + +fi +CFLAGS="$_CFLAGS" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking type of array argument to getgroups" >&5 +$as_echo_n "checking type of array argument to getgroups... " >&6; } +if test "${ac_cv_type_getgroups+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + if test "$cross_compiling" = yes; then : + ac_cv_type_getgroups=cross +else + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +/* Thanks to Mike Rendell for this test. */ +$ac_includes_default +#define NGID 256 +#undef MAX +#define MAX(x, y) ((x) > (y) ? (x) : (y)) + +int +main () +{ + gid_t gidset[NGID]; + int i, n; + union { gid_t gval; long int lval; } val; + + val.lval = -1; + for (i = 0; i < NGID; i++) + gidset[i] = val.gval; + n = getgroups (sizeof (gidset) / MAX (sizeof (int), sizeof (gid_t)) - 1, + gidset); + /* Exit non-zero if getgroups seems to require an array of ints. This + happens when gid_t is short int but getgroups modifies an array + of ints. */ + return n > 0 && gidset[n] != val.gval; +} +_ACEOF +if ac_fn_c_try_run "$LINENO"; then : + ac_cv_type_getgroups=gid_t +else + ac_cv_type_getgroups=int +fi +rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ + conftest.$ac_objext conftest.beam conftest.$ac_ext +fi + +if test $ac_cv_type_getgroups = cross; then + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + +_ACEOF +if (eval "$ac_cpp conftest.$ac_ext") 2>&5 | + $EGREP "getgroups.*int.*gid_t" >/dev/null 2>&1; then : + ac_cv_type_getgroups=gid_t +else + ac_cv_type_getgroups=int +fi +rm -f conftest* + +fi +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_type_getgroups" >&5 +$as_echo "$ac_cv_type_getgroups" >&6; } + +cat >>confdefs.h <<_ACEOF +#define GETGROUPS_T $ac_cv_type_getgroups +_ACEOF + + +ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default" +if test "x$ac_cv_type_size_t" = x""yes; then : + +else + +cat >>confdefs.h <<_ACEOF +#define size_t unsigned int +_ACEOF + +fi + +ac_fn_c_check_func "$LINENO" "getgroups" "ac_cv_func_getgroups" if test "x$ac_cv_func_getgroups" = x""yes; then : fi @@ -15126,10 +15415,9 @@ $as_echo "#define HAVE_GETGROUPS 1" >>confdefs.h fi LIBS=$ac_save_LIBS -for ac_func in strchr strrchr memchr memcpy memset sysconf tzset \ - strftime setrlimit initgroups getgroups fstat gettimeofday \ - regcomp setlocale nl_langinfo getaddrinfo setenv \ - mbr_check_membership setrlimit64 +for ac_func in strrchr sysconf tzset strftime initgroups getgroups fstat \ + regcomp setlocale nl_langinfo getaddrinfo mbr_check_membership \ + setrlimit64 sysctl do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" @@ -15173,68 +15461,22 @@ done fi done -for ac_func in setsid +utmp_style=LEGACY +for ac_func in getutxid getutid do : - ac_fn_c_check_func "$LINENO" "setsid" "ac_cv_func_setsid" -if test "x$ac_cv_func_setsid" = x""yes; then : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +eval as_val=\$$as_ac_var + if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF -#define HAVE_SETSID 1 -_ACEOF - -else - - case " $LIBOBJS " in - *" setsid.$ac_objext "* ) ;; - *) LIBOBJS="$LIBOBJS setsid.$ac_objext" - ;; -esac - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether setpgrp takes no argument" >&5 -$as_echo_n "checking whether setpgrp takes no argument... " >&6; } -if test "${ac_cv_func_setpgrp_void+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - if test "$cross_compiling" = yes; then : - as_fn_error "cannot check setpgrp when cross compiling" "$LINENO" 5 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$ac_includes_default -int -main () -{ -/* If this system has a BSD-style setpgrp which takes arguments, - setpgrp(1, 1) will fail with ESRCH and return -1, in that case - exit successfully. */ - return setpgrp (1,1) != -1; - ; - return 0; -} +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF -if ac_fn_c_try_run "$LINENO"; then : - ac_cv_func_setpgrp_void=no -else - ac_cv_func_setpgrp_void=yes -fi -rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \ - conftest.$ac_objext conftest.beam conftest.$ac_ext -fi - -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_setpgrp_void" >&5 -$as_echo "$ac_cv_func_setpgrp_void" >&6; } -if test $ac_cv_func_setpgrp_void = yes; then - -$as_echo "#define SETPGRP_VOID 1" >>confdefs.h - -fi - - + utmp_style=POSIX; break fi done - -for ac_func in sysctl getutxid getutid +if test "$utmp_style" = "LEGACY"; then + for ac_func in getttyent ttyslot do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" @@ -15247,6 +15489,7 @@ _ACEOF fi done +fi for ac_func in openpty do : @@ -15323,7 +15566,10 @@ fi done - SUDO_LIBS="${SUDO_LIBS} -lutil" + case "$SUDO_LIBS" in + *-lutil*) ;; + *) SUDO_LIBS="${SUDO_LIBS} -lutil";; + esac $as_echo "#define HAVE_OPENPTY 1" >>confdefs.h @@ -15436,41 +15682,15 @@ $as_echo "#define UNSETENV_VOID 1" >>confdefs.h fi -fi -done - -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether putenv has a const argument" >&5 -$as_echo_n "checking whether putenv has a const argument... " >&6; } -if test "${sudo_cv_func_putenv_const+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -$ac_includes_default -int putenv(const char *string) {return 0;} -int -main () -{ - - ; - return 0; -} -_ACEOF -if ac_fn_c_try_compile "$LINENO"; then : - sudo_cv_func_putenv_const=yes else - sudo_cv_func_putenv_const=no -fi -rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + case " $LIBOBJS " in + *" unsetenv.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS unsetenv.$ac_objext" + ;; +esac fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $sudo_cv_func_putenv_const" >&5 -$as_echo "$sudo_cv_func_putenv_const" >&6; } - if test $sudo_cv_func_putenv_const = yes; then - -$as_echo "#define PUTENV_CONST 1" >>confdefs.h - - fi +done if test -z "$SKIP_SETRESUID"; then for ac_func in setresuid @@ -15480,7 +15700,20 @@ if test "x$ac_cv_func_setresuid" = x""yes; then : cat >>confdefs.h <<_ACEOF #define HAVE_SETRESUID 1 _ACEOF - SKIP_SETREUID=yes + + SKIP_SETREUID=yes + for ac_func in getresuid +do : + ac_fn_c_check_func "$LINENO" "getresuid" "ac_cv_func_getresuid" +if test "x$ac_cv_func_getresuid" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_GETRESUID 1 +_ACEOF + +fi +done + + fi done @@ -15614,19 +15847,6 @@ _ACEOF fi done -for ac_func in waitpid wait3 -do : - as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` -ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" -eval as_val=\$$as_ac_var - if test "x$as_val" = x""yes; then : - cat >>confdefs.h <<_ACEOF -#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 -_ACEOF - break -fi -done - for ac_func in innetgr _innetgr do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` @@ -15787,7 +16007,7 @@ esac fi -for ac_func in memrchr strerror strcasecmp sigaction strlcpy strlcat +for ac_func in memrchr strlcpy strlcat setenv do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" @@ -15856,7 +16076,7 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_rt_nanosleep" >&5 $as_echo "$ac_cv_lib_rt_nanosleep" >&6; } if test "x$ac_cv_lib_rt_nanosleep" = x""yes; then : - LIBS="${LIBS} -lrt" + REPLAY_LIBS="${REPLAY_LIBS} -lrt" else case " $LIBOBJS " in *" nanosleep.$ac_objext "* ) ;; @@ -15897,16 +16117,18 @@ fi fi done -for ac_func in mkstemps +for ac_func in mkstemps mkdtemp do : - ac_fn_c_check_func "$LINENO" "mkstemps" "ac_cv_func_mkstemps" -if test "x$ac_cv_func_mkstemps" = x""yes; then : + as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` +ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var" +eval as_val=\$$as_ac_var + if test "x$as_val" = x""yes; then : cat >>confdefs.h <<_ACEOF -#define HAVE_MKSTEMPS 1 +#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1 _ACEOF else - SUDO_OBJS="${SUDO_OBJS} mkstemps.o" + for ac_func in random lrand48 do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` @@ -15920,6 +16142,12 @@ _ACEOF fi done + case " $LIBOBJS " in + *" mktemp.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS mktemp.$ac_objext" + ;; +esac + fi done @@ -16453,6 +16681,108 @@ fi done +case ${enable_zlib-"yes"} in + yes) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gzdopen in -lz" >&5 +$as_echo_n "checking for gzdopen in -lz... " >&6; } +if test "${ac_cv_lib_z_gzdopen+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lz $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + +/* Override any GCC internal prototype to avoid an error. + Use char because int might match the return type of a GCC + builtin and then its argument prototype would still apply. */ +#ifdef __cplusplus +extern "C" +#endif +char gzdopen (); +int +main () +{ +return gzdopen (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_z_gzdopen=yes +else + ac_cv_lib_z_gzdopen=no +fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_gzdopen" >&5 +$as_echo "$ac_cv_lib_z_gzdopen" >&6; } +if test "x$ac_cv_lib_z_gzdopen" = x""yes; then : + + for ac_header in zlib.h +do : + ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" +if test "x$ac_cv_header_zlib_h" = x""yes; then : + cat >>confdefs.h <<_ACEOF +#define HAVE_ZLIB_H 1 +_ACEOF + ZLIB="-lz" +else + enable_zlib=builtin +fi + +done + + +fi + + ;; + no) + ;; + system) + $as_echo "#define HAVE_ZLIB_H 1" >>confdefs.h + + ZLIB="-lz" + ;; + builtin) + # handled below + ;; + *) + $as_echo "#define HAVE_ZLIB_H 1" >>confdefs.h + + CPPFLAGS="${CPPFLAGS} -I${enable_zlib}/include" + + if test X"$with_rpath" = X"yes"; then + case "$host" in + *-*-hpux*) ZLIB="${ZLIB} -L$enable_zlib/lib -Wl,+b,$enable_zlib/lib" + ;; + *) ZLIB="${ZLIB} -L$enable_zlib/lib -Wl,-R$enable_zlib/lib" + ;; + esac + else + ZLIB="${ZLIB} -L$enable_zlib/lib" + fi + if test X"$blibpath" != X"" -a "ZLIB" = "SUDO_LDFLAGS"; then + blibpath_add="${blibpath_add}:$enable_zlib/lib" + fi + + ZLIB="${ZLIB} -lz" + ;; +esac +if test X"$enable_zlib" = X"builtin"; then + $as_echo "#define HAVE_ZLIB_H 1" >>confdefs.h + + CPPFLAGS="${CPPFLAGS}"' -I$(top_srcdir)/zlib' + ZLIB="${ZLIB}"' $(top_builddir)/zlib/libz.la' + ZLIB_SRC=zlib + ac_config_headers="$ac_config_headers zlib/zconf.h" + + ac_config_files="$ac_config_files zlib/Makefile" + +fi + for ac_func in strsignal do : ac_fn_c_check_func "$LINENO" "strsignal" "ac_cv_func_strsignal" @@ -16571,48 +16901,8 @@ if test -z "${AUTH_EXCL}${AUTH_REG}" -a -n "$AUTH_EXCL_DEF"; then fi if test ${with_pam-"no"} != "no"; then - case "$LIBS" in - *-ldl*) SUDO_LIBS="${SUDO_LIBS} -lpam" - ;; - *) { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -ldl" >&5 -$as_echo_n "checking for main in -ldl... " >&6; } -if test "${ac_cv_lib_dl_main+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-ldl $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - - -int -main () -{ -return main (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_dl_main=yes -else - ac_cv_lib_dl_main=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_dl_main" >&5 -$as_echo "$ac_cv_lib_dl_main" >&6; } -if test "x$ac_cv_lib_dl_main" = x""yes; then : - SUDO_LIBS="${SUDO_LIBS} -lpam -ldl" -else - SUDO_LIBS="${SUDO_LIBS} -lpam" -fi - - ac_cv_lib_dl=ac_cv_lib_dl_main - ;; - esac + # Note: we already link the main sudo program with -ldl as needed + SUDOERS_LIBS="${SUDOERS_LIBS} -lpam" for ac_header in security/pam_appl.h pam/pam_appl.h do : @@ -16631,7 +16921,7 @@ done if test "$with_pam" = "yes"; then $as_echo "#define HAVE_PAM 1" >>confdefs.h - AUTH_OBJS="$AUTH_OBJS pam.o"; + AUTH_OBJS="$AUTH_OBJS pam.lo"; AUTH_EXCL=PAM @@ -16662,8 +16952,7 @@ $as_echo "yes" >&6; } ;; no) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - -$as_echo "#define NO_PAM_SESSION /**/" >>confdefs.h + $as_echo "#define NO_PAM_SESSION 1" >>confdefs.h ;; *) { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 @@ -16754,8 +17043,8 @@ if test ${with_aixauth-'no'} != "no"; then $as_echo "$as_me: using AIX general authentication" >&6;} $as_echo "#define HAVE_AIXAUTH 1" >>confdefs.h - AUTH_OBJS="$AUTH_OBJS aix_auth.o"; - SUDO_LIBS="${SUDO_LIBS} -ls" + AUTH_OBJS="$AUTH_OBJS aix_auth.lo"; + SUDOERS_LIBS="${SUDOERS_LIBS} -ls" AUTH_EXCL=AIX_AUTH fi fi @@ -16765,7 +17054,7 @@ if test ${with_bsdauth-'no'} != "no"; then if test "x$ac_cv_header_bsd_auth_h" = x""yes; then : $as_echo "#define HAVE_BSD_AUTH_H 1" >>confdefs.h - AUTH_OBJS="$AUTH_OBJS bsdauth.o" + AUTH_OBJS="$AUTH_OBJS bsdauth.lo" BSDAUTH_USAGE='[-a auth_type] ' AUTH_EXCL=BSD_AUTH; BAMAN=1 else @@ -16791,7 +17080,7 @@ done if test "$found" = "true"; then AUTH_EXCL=SIA - AUTH_OBJS="$AUTH_OBJS sia.o" + AUTH_OBJS="$AUTH_OBJS sia.lo" fi fi @@ -16800,23 +17089,23 @@ if test ${with_fwtk-'no'} != "no"; then if test X"$with_rpath" = X"yes"; then case "$host" in - *-*-hpux*) SUDO_LDFLAGS="${SUDO_LDFLAGS} -L${with_fwtk} -Wl,+b,${with_fwtk}" + *-*-hpux*) SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L${with_fwtk} -Wl,+b,${with_fwtk}" ;; - *) SUDO_LDFLAGS="${SUDO_LDFLAGS} -L${with_fwtk} -Wl,-R${with_fwtk}" + *) SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L${with_fwtk} -Wl,-R${with_fwtk}" ;; esac else - SUDO_LDFLAGS="${SUDO_LDFLAGS} -L${with_fwtk}" + SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L${with_fwtk}" fi - if test X"$blibpath" != X"" -a "SUDO_LDFLAGS" = "SUDO_LDFLAGS"; then + if test X"$blibpath" != X"" -a "SUDOERS_LDFLAGS" = "SUDO_LDFLAGS"; then blibpath_add="${blibpath_add}:${with_fwtk}" fi CPPFLAGS="${CPPFLAGS} -I${with_fwtk}" with_fwtk=yes fi - SUDO_LIBS="${SUDO_LIBS} -lauth -lfwall" - AUTH_OBJS="$AUTH_OBJS fwtk.o" + SUDOERS_LIBS="${SUDOERS_LIBS} -lauth -lfwall" + AUTH_OBJS="$AUTH_OBJS fwtk.lo" fi if test ${with_SecurID-'no'} != "no"; then @@ -16888,30 +17177,30 @@ fi $as_echo "$ac_cv_lib_aceclnt_SD_Init_______lpthread_______" >&6; } if test "x$ac_cv_lib_aceclnt_SD_Init_______lpthread_______" = x""yes; then : - AUTH_OBJS="$AUTH_OBJS securid5.o"; - SUDO_LIBS="${SUDO_LIBS} -laceclnt -lpthread" + AUTH_OBJS="$AUTH_OBJS securid5.lo"; + SUDOERS_LIBS="${SUDOERS_LIBS} -laceclnt -lpthread" if test X"$with_rpath" = X"yes"; then case "$host" in - *-*-hpux*) SUDO_LDFLAGS="${SUDO_LDFLAGS} -L${with_SecurID} -Wl,+b,${with_SecurID}" + *-*-hpux*) SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L${with_SecurID} -Wl,+b,${with_SecurID}" ;; - *) SUDO_LDFLAGS="${SUDO_LDFLAGS} -L${with_SecurID} -Wl,-R${with_SecurID}" + *) SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L${with_SecurID} -Wl,-R${with_SecurID}" ;; esac else - SUDO_LDFLAGS="${SUDO_LDFLAGS} -L${with_SecurID}" + SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L${with_SecurID}" fi - if test X"$blibpath" != X"" -a "SUDO_LDFLAGS" = "SUDO_LDFLAGS"; then + if test X"$blibpath" != X"" -a "SUDOERS_LDFLAGS" = "SUDO_LDFLAGS"; then blibpath_add="${blibpath_add}:${with_SecurID}" fi else - AUTH_OBJS="$AUTH_OBJS securid.o"; - SUDO_LIBS="${SUDO_LIBS} ${with_SecurID}/sdiclient.a" + AUTH_OBJS="$AUTH_OBJS securid.lo"; + SUDOERS_LIBS="${SUDOERS_LIBS} ${with_SecurID}/sdiclient.a" fi @@ -16965,15 +17254,15 @@ rm -f conftest.err conftest.$ac_ext if test X"$with_rpath" = X"yes"; then case "$host" in - *-*-hpux*) SUDO_LDFLAGS="${SUDO_LDFLAGS} -L${with_kerb4}/lib -Wl,+b,${with_kerb4}/lib" + *-*-hpux*) SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L${with_kerb4}/lib -Wl,+b,${with_kerb4}/lib" ;; - *) SUDO_LDFLAGS="${SUDO_LDFLAGS} -L${with_kerb4}/lib -Wl,-R${with_kerb4}/lib" + *) SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L${with_kerb4}/lib -Wl,-R${with_kerb4}/lib" ;; esac else - SUDO_LDFLAGS="${SUDO_LDFLAGS} -L${with_kerb4}/lib" + SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L${with_kerb4}/lib" fi - if test X"$blibpath" != X"" -a "SUDO_LDFLAGS" = "SUDO_LDFLAGS"; then + if test X"$blibpath" != X"" -a "SUDOERS_LDFLAGS" = "SUDO_LDFLAGS"; then blibpath_add="${blibpath_add}:${with_kerb4}/lib" fi @@ -17212,8 +17501,8 @@ eval as_val=\$$as_ac_Lib K4LIBS="-lkrb4 $K4LIBS" else K4LIBS="-lkrb $K4LIBS" - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to locate Kerberos IV libraries, you will have to edit the Makefile and add -L/path/to/krb/libs to SUDO_LDFLAGS and possibly add Kerberos libs to SUDO_LIBS" >&5 -$as_echo "$as_me: WARNING: Unable to locate Kerberos IV libraries, you will have to edit the Makefile and add -L/path/to/krb/libs to SUDO_LDFLAGS and possibly add Kerberos libs to SUDO_LIBS" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to locate Kerberos IV libraries, you will have to edit the Makefile and add -L/path/to/krb/libs to SUDOERS_LDFLAGS and possibly add Kerberos libs to SUDOERS_LIBS" >&5 +$as_echo "$as_me: WARNING: Unable to locate Kerberos IV libraries, you will have to edit the Makefile and add -L/path/to/krb/libs to SUDOERS_LDFLAGS and possibly add Kerberos libs to SUDOERS_LIBS" >&2;} fi @@ -17221,8 +17510,8 @@ fi fi LDFLAGS="$O_LDFLAGS" - SUDO_LIBS="${SUDO_LIBS} $K4LIBS" - AUTH_OBJS="$AUTH_OBJS kerb4.o" + SUDOERS_LIBS="${SUDOERS_LIBS} $K4LIBS" + AUTH_OBJS="$AUTH_OBJS kerb4.lo" fi if test ${with_kerb5-'no'} != "no"; then @@ -17267,9 +17556,9 @@ fi if test -n "$KRB5CONFIG"; then $as_echo "#define HAVE_KERB5 1" >>confdefs.h - AUTH_OBJS="$AUTH_OBJS kerb5.o" + AUTH_OBJS="$AUTH_OBJS kerb5.lo" CPPFLAGS="$CPPFLAGS `krb5-config --cflags`" - SUDO_LIBS="$SUDO_LIBS `krb5-config --libs`" + SUDOERS_LIBS="$SUDOERS_LIBS `krb5-config --libs`" { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using Heimdal" >&5 $as_echo_n "checking whether we are using Heimdal... " >&6; } cat confdefs.h - <<_ACEOF >conftest.$ac_ext @@ -17298,17 +17587,15 @@ $as_echo "no" >&6; } fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - fi -fi -if test ${with_kerb5-'no'} != "no" -a -z "$KRB5CONFIG"; then - $as_echo "#define HAVE_KERB5 1" >>confdefs.h + else + $as_echo "#define HAVE_KERB5 1" >>confdefs.h - if test "$with_kerb5" = "yes"; then - found=no - O_CPPFLAGS="$CPPFLAGS" - for dir in "" "kerberosV/" "krb5/" "kerberos5/" "kerberosv5/"; do - CPPFLAGS="$O_CPPFLAGS -I/usr/include/${dir}" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + if test "$with_kerb5" = "yes"; then + found=no + O_CPPFLAGS="$CPPFLAGS" + for dir in "" "kerberosV/" "krb5/" "kerberos5/" "kerberosv5/"; do + CPPFLAGS="$O_CPPFLAGS -I/usr/include/${dir}" + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include _ACEOF @@ -17316,34 +17603,34 @@ if ac_fn_c_try_cpp "$LINENO"; then : found=yes; break fi rm -f conftest.err conftest.$ac_ext - done - if test X"$found" = X"no"; then - CPPFLAGS="$O_CPPFLAGS" - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to locate Kerberos V include files, you will have to edit the Makefile and add -I/path/to/krb/includes to CPPFLAGS" >&5 + done + if test X"$found" = X"no"; then + CPPFLAGS="$O_CPPFLAGS" + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to locate Kerberos V include files, you will have to edit the Makefile and add -I/path/to/krb/includes to CPPFLAGS" >&5 $as_echo "$as_me: WARNING: Unable to locate Kerberos V include files, you will have to edit the Makefile and add -I/path/to/krb/includes to CPPFLAGS" >&2;} - fi - else + fi + else if test X"$with_rpath" = X"yes"; then case "$host" in - *-*-hpux*) SUDO_LDFLAGS="${SUDO_LDFLAGS} -L${with_kerb5}/lib -Wl,+b,${with_kerb5}/lib" + *-*-hpux*) SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L${with_kerb5}/lib -Wl,+b,${with_kerb5}/lib" ;; - *) SUDO_LDFLAGS="${SUDO_LDFLAGS} -L${with_kerb5}/lib -Wl,-R${with_kerb5}/lib" + *) SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L${with_kerb5}/lib -Wl,-R${with_kerb5}/lib" ;; esac else - SUDO_LDFLAGS="${SUDO_LDFLAGS} -L${with_kerb5}/lib" + SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L${with_kerb5}/lib" fi - if test X"$blibpath" != X"" -a "SUDO_LDFLAGS" = "SUDO_LDFLAGS"; then + if test X"$blibpath" != X"" -a "SUDOERS_LDFLAGS" = "SUDO_LDFLAGS"; then blibpath_add="${blibpath_add}:${with_kerb5}/lib" fi - CPPFLAGS="$CPPFLAGS -I${with_kerb5}/include" - fi + CPPFLAGS="$CPPFLAGS -I${with_kerb5}/include" + fi - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using Heimdal" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using Heimdal" >&5 $as_echo_n "checking whether we are using Heimdal... " >&6; } - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int @@ -17356,13 +17643,13 @@ const char *tmp = heimdal_version; _ACEOF if ac_fn_c_try_compile "$LINENO"; then : - { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - $as_echo "#define HAVE_HEIMDAL 1" >>confdefs.h + $as_echo "#define HAVE_HEIMDAL 1" >>confdefs.h - # XXX - need to check whether -lcrypo is needed! - SUDO_LIBS="${SUDO_LIBS} -lkrb5 -lcrypto -ldes -lcom_err -lasn1" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lroken" >&5 + # XXX - need to check whether -lcrypo is needed! + SUDOERS_LIBS="${SUDOERS_LIBS} -lkrb5 -lcrypto -ldes -lcom_err -lasn1" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lroken" >&5 $as_echo_n "checking for main in -lroken... " >&6; } if test "${ac_cv_lib_roken_main+set}" = set; then : $as_echo_n "(cached) " >&6 @@ -17393,16 +17680,16 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_roken_main" >&5 $as_echo "$ac_cv_lib_roken_main" >&6; } if test "x$ac_cv_lib_roken_main" = x""yes; then : - SUDO_LIBS="${SUDO_LIBS} -lroken" + SUDOERS_LIBS="${SUDOERS_LIBS} -lroken" fi else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } - SUDO_LIBS="${SUDO_LIBS} -lkrb5 -lk5crypto -lcom_err" - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lkrb5support" >&5 + SUDOERS_LIBS="${SUDOERS_LIBS} -lkrb5 -lk5crypto -lcom_err" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lkrb5support" >&5 $as_echo_n "checking for main in -lkrb5support... " >&6; } if test "${ac_cv_lib_krb5support_main+set}" = set; then : $as_echo_n "(cached) " >&6 @@ -17433,15 +17720,16 @@ fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_krb5support_main" >&5 $as_echo "$ac_cv_lib_krb5support_main" >&6; } if test "x$ac_cv_lib_krb5support_main" = x""yes; then : - SUDO_LIBS="${SUDO_LIBS} -lkrb5support" + SUDOERS_LIBS="${SUDOERS_LIBS} -lkrb5support" fi fi rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext - AUTH_OBJS="$AUTH_OBJS kerb5.o" + AUTH_OBJS="$AUTH_OBJS kerb5.lo" + fi _LIBS="$LIBS" - LIBS="${LIBS} ${SUDO_LIBS}" + LIBS="${LIBS} ${SUDOERS_LIBS}" for ac_func in krb5_verify_user krb5_init_secure_context do : as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` @@ -17469,7 +17757,7 @@ if test "${sudo_cv_krb5_get_init_creds_opt_free_two_args+set}" = set; then : $as_echo_n "(cached) " >&6 else - cat confdefs.h - <<_ACEOF >conftest.$ac_ext + cat confdefs.h - <<_ACEOF >conftest.$ac_ext /* end confdefs.h. */ #include int @@ -17513,15 +17801,15 @@ if test ${with_AFS-'no'} = "yes"; then if test X"$with_rpath" = X"yes"; then case "$host" in - *-*-hpux*) SUDO_LDFLAGS="${SUDO_LDFLAGS} -L$i -Wl,+b,$i" + *-*-hpux*) SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L$i -Wl,+b,$i" ;; - *) SUDO_LDFLAGS="${SUDO_LDFLAGS} -L$i -Wl,-R$i" + *) SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L$i -Wl,-R$i" ;; esac else - SUDO_LDFLAGS="${SUDO_LDFLAGS} -L$i" + SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L$i" fi - if test X"$blibpath" != X"" -a "SUDO_LDFLAGS" = "SUDO_LDFLAGS"; then + if test X"$blibpath" != X"" -a "SUDOERS_LDFLAGS" = "SUDO_LDFLAGS"; then blibpath_add="${blibpath_add}:$i" fi @@ -17529,8 +17817,8 @@ if test ${with_AFS-'no'} = "yes"; then fi done if test -z "$FOUND_AFSLIBDIR"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to locate AFS libraries, you will have to edit the Makefile and add -L/path/to/afs/libs to SUDO_LDFLAGS or rerun configure with the --with-libpath options." >&5 -$as_echo "$as_me: WARNING: Unable to locate AFS libraries, you will have to edit the Makefile and add -L/path/to/afs/libs to SUDO_LDFLAGS or rerun configure with the --with-libpath options." >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to locate AFS libraries, you will have to edit the Makefile and add -L/path/to/afs/libs to SUDOERS_LDFLAGS or rerun configure with the --with-libpath options." >&5 +$as_echo "$as_me: WARNING: Unable to locate AFS libraries, you will have to edit the Makefile and add -L/path/to/afs/libs to SUDOERS_LDFLAGS or rerun configure with the --with-libpath options." >&2;} fi # Order is important here. Note that we build AFS_LIBS from right to left @@ -17561,13 +17849,13 @@ $as_echo "$as_me: WARNING: Unable to locate AFS libraries, you will have to edit $as_echo "$as_me: WARNING: Unable to locate AFS include dir, you may have to edit the Makefile and add -I/path/to/afs/includes to CPPFLAGS or rerun configure with the --with-incpath options." >&2;} fi - AUTH_OBJS="$AUTH_OBJS afs.o" + AUTH_OBJS="$AUTH_OBJS afs.lo" fi if test ${with_DCE-'no'} = "yes"; then DCE_OBJS="${DCE_OBJS} dce_pwent.o" - SUDO_LIBS="${SUDO_LIBS} -ldce" - AUTH_OBJS="$AUTH_OBJS dce.o" + SUDOERS_LIBS="${SUDOERS_LIBS} -ldce" + AUTH_OBJS="$AUTH_OBJS dce.lo" fi if test "${with_skey-'no'}" = "yes"; then @@ -17592,41 +17880,39 @@ if test "${with_skey-'no'}" = "yes"; then if test X"$with_rpath" = X"yes"; then case "$host" in - *-*-hpux*) SUDO_LDFLAGS="${SUDO_LDFLAGS} -L${with_skey}/lib -Wl,+b,${with_skey}/lib" + *-*-hpux*) SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L${with_skey}/lib -Wl,+b,${with_skey}/lib" ;; - *) SUDO_LDFLAGS="${SUDO_LDFLAGS} -L${with_skey}/lib -Wl,-R${with_skey}/lib" + *) SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L${with_skey}/lib -Wl,-R${with_skey}/lib" ;; esac else - SUDO_LDFLAGS="${SUDO_LDFLAGS} -L${with_skey}/lib" + SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L${with_skey}/lib" fi - if test X"$blibpath" != X"" -a "SUDO_LDFLAGS" = "SUDO_LDFLAGS"; then + if test X"$blibpath" != X"" -a "SUDOERS_LDFLAGS" = "SUDO_LDFLAGS"; then blibpath_add="${blibpath_add}:${with_skey}/lib" fi - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : + ac_fn_c_check_header_compile "$LINENO" "skey.h" "ac_cv_header_skey_h" "#include +" +if test "x$ac_cv_header_skey_h" = x""yes; then : found=yes else found=no fi -rm -f conftest.err conftest.$ac_ext + + else found=no O_CPPFLAGS="$CPPFLAGS" for dir in "" "/usr/local" "/usr/contrib"; do test -n "$dir" && CPPFLAGS="$O_CPPFLAGS -I${dir}/include" - cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ -#include -_ACEOF -if ac_fn_c_try_cpp "$LINENO"; then : + ac_fn_c_check_header_compile "$LINENO" "skey.h" "ac_cv_header_skey_h" "#include +" +if test "x$ac_cv_header_skey_h" = x""yes; then : found=yes; break fi -rm -f conftest.err conftest.$ac_ext + + done if test "$found" = "no" -o -z "$dir"; then CPPFLAGS="$O_CPPFLAGS" @@ -17649,23 +17935,23 @@ rm -f conftest.err conftest.$ac_ext if test X"$with_rpath" = X"yes"; then case "$host" in - *-*-hpux*) SUDO_LDFLAGS="${SUDO_LDFLAGS} -L${dir}/lib -Wl,+b,${dir}/lib" + *-*-hpux*) SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L${dir}/lib -Wl,+b,${dir}/lib" ;; - *) SUDO_LDFLAGS="${SUDO_LDFLAGS} -L${dir}/lib -Wl,-R${dir}/lib" + *) SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L${dir}/lib -Wl,-R${dir}/lib" ;; esac else - SUDO_LDFLAGS="${SUDO_LDFLAGS} -L${dir}/lib" + SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L${dir}/lib" fi - if test X"$blibpath" != X"" -a "SUDO_LDFLAGS" = "SUDO_LDFLAGS"; then + if test X"$blibpath" != X"" -a "SUDOERS_LDFLAGS" = "SUDO_LDFLAGS"; then blibpath_add="${blibpath_add}:${dir}/lib" fi fi - fi - if test "$found" = "no"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to locate skey.h, you will have to edit the Makefile and add -I/path/to/skey/includes to CPPFLAGS" >&5 + if test "$found" = "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to locate skey.h, you will have to edit the Makefile and add -I/path/to/skey/includes to CPPFLAGS" >&5 $as_echo "$as_me: WARNING: Unable to locate skey.h, you will have to edit the Makefile and add -I/path/to/skey/includes to CPPFLAGS" >&2;} + fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lskey" >&5 $as_echo_n "checking for main in -lskey... " >&6; } @@ -17700,8 +17986,8 @@ $as_echo "$ac_cv_lib_skey_main" >&6; } if test "x$ac_cv_lib_skey_main" = x""yes; then : found=yes else - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to locate libskey.a, you will have to edit the Makefile and add -L/path/to/skey/lib to SUDO_LDFLAGS" >&5 -$as_echo "$as_me: WARNING: Unable to locate libskey.a, you will have to edit the Makefile and add -L/path/to/skey/lib to SUDO_LDFLAGS" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to locate libskey.a, you will have to edit the Makefile and add -L/path/to/skey/lib to SUDOERS_LDFLAGS" >&5 +$as_echo "$as_me: WARNING: Unable to locate libskey.a, you will have to edit the Makefile and add -L/path/to/skey/lib to SUDOERS_LDFLAGS" >&2;} fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for skeyaccess in -lskey" >&5 @@ -17745,9 +18031,41 @@ if test "x$ac_cv_lib_skey_skeyaccess" = x""yes; then : fi + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for RFC1938-compliant skeychallenge" >&5 +$as_echo_n "checking for RFC1938-compliant skeychallenge... " >&6; } + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include + #include +int +main () +{ +skeychallenge(NULL, NULL, NULL, 0); + + ; + return 0; +} +_ACEOF +if ac_fn_c_try_compile "$LINENO"; then : + + $as_echo "#define HAVE_RFC1938_SKEYCHALLENGE 1" >>confdefs.h + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + +else + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } + + +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + LDFLAGS="$O_LDFLAGS" - SUDO_LIBS="${SUDO_LIBS} -lskey" - AUTH_OBJS="$AUTH_OBJS rfc1938.o" + SUDOERS_LIBS="${SUDOERS_LIBS} -lskey" + AUTH_OBJS="$AUTH_OBJS rfc1938.lo" fi if test "${with_opie-'no'}" = "yes"; then @@ -17772,15 +18090,15 @@ if test "${with_opie-'no'}" = "yes"; then if test X"$with_rpath" = X"yes"; then case "$host" in - *-*-hpux*) SUDO_LDFLAGS="${SUDO_LDFLAGS} -L${with_opie}/lib -Wl,+b,${with_opie}/lib" + *-*-hpux*) SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L${with_opie}/lib -Wl,+b,${with_opie}/lib" ;; - *) SUDO_LDFLAGS="${SUDO_LDFLAGS} -L${with_opie}/lib -Wl,-R${with_opie}/lib" + *) SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L${with_opie}/lib -Wl,-R${with_opie}/lib" ;; esac else - SUDO_LDFLAGS="${SUDO_LDFLAGS} -L${with_opie}/lib" + SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L${with_opie}/lib" fi - if test X"$blibpath" != X"" -a "SUDO_LDFLAGS" = "SUDO_LDFLAGS"; then + if test X"$blibpath" != X"" -a "SUDOERS_LDFLAGS" = "SUDO_LDFLAGS"; then blibpath_add="${blibpath_add}:${with_opie}/lib" fi @@ -17829,23 +18147,23 @@ rm -f conftest.err conftest.$ac_ext if test X"$with_rpath" = X"yes"; then case "$host" in - *-*-hpux*) SUDO_LDFLAGS="${SUDO_LDFLAGS} -L${dir}/lib -Wl,+b,${dir}/lib" + *-*-hpux*) SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L${dir}/lib -Wl,+b,${dir}/lib" ;; - *) SUDO_LDFLAGS="${SUDO_LDFLAGS} -L${dir}/lib -Wl,-R${dir}/lib" + *) SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L${dir}/lib -Wl,-R${dir}/lib" ;; esac else - SUDO_LDFLAGS="${SUDO_LDFLAGS} -L${dir}/lib" + SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L${dir}/lib" fi - if test X"$blibpath" != X"" -a "SUDO_LDFLAGS" = "SUDO_LDFLAGS"; then + if test X"$blibpath" != X"" -a "SUDOERS_LDFLAGS" = "SUDO_LDFLAGS"; then blibpath_add="${blibpath_add}:${dir}/lib" fi fi - fi - if test "$found" = "no"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to locate opie.h, you will have to edit the Makefile and add -I/path/to/opie/includes to CPPFLAGS" >&5 + if test "$found" = "no"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to locate opie.h, you will have to edit the Makefile and add -I/path/to/opie/includes to CPPFLAGS" >&5 $as_echo "$as_me: WARNING: Unable to locate opie.h, you will have to edit the Makefile and add -I/path/to/opie/includes to CPPFLAGS" >&2;} + fi fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lopie" >&5 $as_echo_n "checking for main in -lopie... " >&6; } @@ -17880,17 +18198,18 @@ $as_echo "$ac_cv_lib_opie_main" >&6; } if test "x$ac_cv_lib_opie_main" = x""yes; then : found=yes else - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to locate libopie.a, you will have to edit the Makefile and add -L/path/to/opie/lib to SUDO_LDFLAGS" >&5 -$as_echo "$as_me: WARNING: Unable to locate libopie.a, you will have to edit the Makefile and add -L/path/to/opie/lib to SUDO_LDFLAGS" >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Unable to locate libopie.a, you will have to edit the Makefile and add -L/path/to/opie/lib to SUDOERS_LDFLAGS" >&5 +$as_echo "$as_me: WARNING: Unable to locate libopie.a, you will have to edit the Makefile and add -L/path/to/opie/lib to SUDOERS_LDFLAGS" >&2;} fi LDFLAGS="$O_LDFLAGS" - SUDO_LIBS="${SUDO_LIBS} -lopie" - AUTH_OBJS="$AUTH_OBJS rfc1938.o" + SUDOERS_LIBS="${SUDOERS_LIBS} -lopie" + AUTH_OBJS="$AUTH_OBJS rfc1938.lo" fi if test ${with_passwd-'no'} != "no"; then if test -z "$LIB_CRYPT"; then + _LIBS="$LIBS" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing crypt" >&5 $as_echo_n "checking for library containing crypt... " >&6; } if test "${ac_cv_search_crypt+set}" = set; then : @@ -17944,9 +18263,10 @@ $as_echo "$ac_cv_search_crypt" >&6; } ac_res=$ac_cv_search_crypt if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" - test -n "$ac_lib" && SUDO_LIBS="${SUDO_LIBS} $ac_res" + test -n "$ac_lib" && SUDOERS_LIBS="${SUDOERS_LIBS} $ac_res" fi + LIBS="$_LIBS" fi if test "$CHECKSHADOW" = "true" -a -n "$shadow_funcs"; then @@ -17967,7 +18287,7 @@ fi done if test "$found" = "yes"; then - SUDO_LIBS="$SUDO_LIBS $shadow_libs" + SUDOERS_LIBS="$SUDOERS_LIBS $shadow_libs" elif test -n "$shadow_libs_optional"; then LIBS="$LIBS $shadow_libs_optional" for ac_func in $shadow_funcs @@ -17984,7 +18304,7 @@ fi done if test "$found" = "yes"; then - SUDO_LIBS="$SUDO_LIBS $shadow_libs $shadow_libs_optional" + SUDOERS_LIBS="$SUDOERS_LIBS $shadow_libs $shadow_libs_optional" fi fi if test "$found" = "yes"; then @@ -18052,7 +18372,7 @@ ac_res=$ac_cv_search_getspnam if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" $as_echo "#define HAVE_GETSPNAM 1" >>confdefs.h - CHECKSHADOW=false; test -n "$ac_lib" && SUDO_LIBS="${SUDO_LIBS} $ac_res" + CHECKSHADOW=false; test -n "$ac_lib" && SUDOERS_LIBS="${SUDOERS_LIBS} $ac_res" fi fi @@ -18111,7 +18431,7 @@ ac_res=$ac_cv_search_getprpwnam if test "$ac_res" != no; then : test "$ac_res" = "none required" || LIBS="$ac_res $LIBS" $as_echo "#define HAVE_GETPRPWNAM 1" >>confdefs.h - CHECKSHADOW=false; SECUREWARE=1; test -n "$ac_lib" && SUDO_LIBS="${SUDO_LIBS} $ac_res" + CHECKSHADOW=false; SECUREWARE=1; test -n "$ac_lib" && SUDOERS_LIBS="${SUDOERS_LIBS} $ac_res" fi fi @@ -18129,7 +18449,7 @@ _ACEOF fi done - AUTH_OBJS="$AUTH_OBJS secureware.o" + AUTH_OBJS="$AUTH_OBJS secureware.lo" fi fi @@ -18139,15 +18459,15 @@ if test ${with_ldap-'no'} != "no"; then if test X"$with_rpath" = X"yes"; then case "$host" in - *-*-hpux*) SUDO_LDFLAGS="${SUDO_LDFLAGS} -L${with_ldap}/lib -Wl,+b,${with_ldap}/lib" + *-*-hpux*) SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L${with_ldap}/lib -Wl,+b,${with_ldap}/lib" ;; - *) SUDO_LDFLAGS="${SUDO_LDFLAGS} -L${with_ldap}/lib -Wl,-R${with_ldap}/lib" + *) SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L${with_ldap}/lib -Wl,-R${with_ldap}/lib" ;; esac else - SUDO_LDFLAGS="${SUDO_LDFLAGS} -L${with_ldap}/lib" + SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -L${with_ldap}/lib" fi - if test X"$blibpath" != X"" -a "SUDO_LDFLAGS" = "SUDO_LDFLAGS"; then + if test X"$blibpath" != X"" -a "SUDOERS_LDFLAGS" = "SUDO_LDFLAGS"; then blibpath_add="${blibpath_add}:${with_ldap}/lib" fi @@ -18169,7 +18489,7 @@ if test ${with_ldap-'no'} != "no"; then CPPFLAGS="${CPPFLAGS} -I${with_ldap}/include" with_ldap=yes fi - SUDO_OBJS="${SUDO_OBJS} ldap.o" + SUDOERS_OBJS="${SUDOERS_OBJS} ldap.lo" LDAP="" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LDAP libraries" >&5 @@ -18512,32 +18832,131 @@ $as_echo "$as_me: WARNING: Unable to locate gssapi.h, you will have to edit the fi fi - SUDO_LIBS="${SUDO_LIBS} ${LDAP_LIBS}" + SUDOERS_LIBS="${SUDOERS_LIBS} ${LDAP_LIBS}" LIBS="$_LIBS" LDFLAGS="$_LDFLAGS" fi -if test X"$LIBVAS_RPATH" != X""; then - if test -n "$blibpath"; then - blibpath_add="${blibpath_add}:$LIBVAS_RPATH" - else - case "$host" in - *-*-hpux*) LDFLAGS="$LDFLAGS -Wl,+b,$LIBVAS_RPATH" - ;; - *) LDFLAGS="$LDFLAGS -Wl,-R$LIBVAS_RPATH" - ;; - esac - fi +# +# How to do dynamic object loading. +# We support dlopen() and sh_load(), else fall back to static loading. +# +case "$lt_cv_dlopen" in + dlopen) + $as_echo "#define HAVE_DLOPEN 1" >>confdefs.h + + SUDOERS_OBJS="$SUDOERS_OBJS plugin_error.lo" + LT_STATIC="--tag=disable-static" + ;; + shl_load) + $as_echo "#define HAVE_SHL_LOAD 1" >>confdefs.h + + SUDOERS_OBJS="$SUDOERS_OBJS plugin_error.lo" + LT_STATIC="--tag=disable-static" + case " $LIBOBJS " in + *" dlopen.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS dlopen.$ac_objext" + ;; +esac + + ;; + *) + # Preload sudoers module symbols + SUDO_OBJS="${SUDO_OBJS} preload.o" + SUDO_LIBS="${SUDO_LIBS} \$(top_builddir)/plugins/sudoers/sudoers.la" + LT_STATIC="" + case " $LIBOBJS " in + *" dlopen.$ac_objext "* ) ;; + *) LIBOBJS="$LIBOBJS dlopen.$ac_objext" + ;; +esac + + ;; +esac + +# +# Add library needed for dynamic loading, if any. +# +LIBDL="$lt_cv_dlopen_libs" +if test X"$LIBDL" != X""; then + SUDO_LIBS="${SUDO_LIBS} $LIBDL" + SUDOERS_LIBS="${SUDOERS_LIBS} $LIBDL" +fi + +# On HP-UX, you cannot dlopen() a shared object that uses pthreads +# unless the main program is linked against -lpthread. Since we +# have no knowledge what libraries a plugin may depend on, we always +# link against -lpthread on HP-UX if it is available. +# This check should go after all other libraries tests. +case "$host" in + *-*-hpux*) + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for main in -lpthread" >&5 +$as_echo_n "checking for main in -lpthread... " >&6; } +if test "${ac_cv_lib_pthread_main+set}" = set; then : + $as_echo_n "(cached) " >&6 +else + ac_check_lib_save_LIBS=$LIBS +LIBS="-lpthread $LIBS" +cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ + + +int +main () +{ +return main (); + ; + return 0; +} +_ACEOF +if ac_fn_c_try_link "$LINENO"; then : + ac_cv_lib_pthread_main=yes +else + ac_cv_lib_pthread_main=no fi +rm -f core conftest.err conftest.$ac_objext \ + conftest$ac_exeext conftest.$ac_ext +LIBS=$ac_check_lib_save_LIBS +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pthread_main" >&5 +$as_echo "$ac_cv_lib_pthread_main" >&6; } +if test "x$ac_cv_lib_pthread_main" = x""yes; then : + SUDO_LIBS="${SUDO_LIBS} -lpthread" +fi + + ;; +esac if test -n "$blibpath"; then if test -n "$blibpath_add"; then - SUDO_LDFLAGS="$SUDO_LDFLAGS -Wl,-blibpath:${blibpath}${blibpath_add}" + SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS -Wl,-blibpath:${blibpath}${blibpath_add}" elif test -n "$with_blibpath" -a "$with_blibpath" != "yes"; then - SUDO_LDFLAGS="$SUDO_LDFLAGS -Wl,-blibpath:${blibpath}" + SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS -Wl,-blibpath:${blibpath}" + fi +fi + +if test "$utmp_style" = "LEGACY"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for utmp file path" >&5 +$as_echo_n "checking for utmp file path... " >&6; } +found=no +for p in "/var/run/utmp" "/var/adm/utmp" "/etc/utmp"; do + if test -r "$p"; then + found=yes + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $p" >&5 +$as_echo "$p" >&6; } + cat >>confdefs.h <&5 +$as_echo "not found" >&6; } fi +fi { $as_echo "$as_me:${as_lineno-$LINENO}: checking for log file location" >&5 $as_echo_n "checking for log file location... " >&6; } if test -n "$with_logpath"; then @@ -18613,137 +19032,9 @@ EOF $as_echo "$iolog_dir" >&6; } -if test "${with_iologdir-yes}" != "no"; then - # Require POSIX job control for I/O log support - for ac_func in tcsetpgrp -do : - ac_fn_c_check_func "$LINENO" "tcsetpgrp" "ac_cv_func_tcsetpgrp" -if test "x$ac_cv_func_tcsetpgrp" = x""yes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_TCSETPGRP 1 -_ACEOF - - SUDO_OBJS="${SUDO_OBJS} exec_pty.o get_pty.o iolog.o" - PROGS="$PROGS sudoreplay" - REPLAY="" - - # Check whether --enable-zlib was given. -if test "${enable_zlib+set}" = set; then : - enableval=$enable_zlib; -fi - - case ${enable_zlib-"yes"} in - yes) - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gzdopen in -lz" >&5 -$as_echo_n "checking for gzdopen in -lz... " >&6; } -if test "${ac_cv_lib_z_gzdopen+set}" = set; then : - $as_echo_n "(cached) " >&6 -else - ac_check_lib_save_LIBS=$LIBS -LIBS="-lz $LIBS" -cat confdefs.h - <<_ACEOF >conftest.$ac_ext -/* end confdefs.h. */ - -/* Override any GCC internal prototype to avoid an error. - Use char because int might match the return type of a GCC - builtin and then its argument prototype would still apply. */ -#ifdef __cplusplus -extern "C" -#endif -char gzdopen (); -int -main () -{ -return gzdopen (); - ; - return 0; -} -_ACEOF -if ac_fn_c_try_link "$LINENO"; then : - ac_cv_lib_z_gzdopen=yes -else - ac_cv_lib_z_gzdopen=no -fi -rm -f core conftest.err conftest.$ac_objext \ - conftest$ac_exeext conftest.$ac_ext -LIBS=$ac_check_lib_save_LIBS -fi -{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_z_gzdopen" >&5 -$as_echo "$ac_cv_lib_z_gzdopen" >&6; } -if test "x$ac_cv_lib_z_gzdopen" = x""yes; then : - - for ac_header in zlib.h -do : - ac_fn_c_check_header_mongrel "$LINENO" "zlib.h" "ac_cv_header_zlib_h" "$ac_includes_default" -if test "x$ac_cv_header_zlib_h" = x""yes; then : - cat >>confdefs.h <<_ACEOF -#define HAVE_ZLIB_H 1 -_ACEOF - ZLIB="-lz" -else - enable_zlib=builtin -fi - -done - - -fi - - ;; - no) - ;; - system) - $as_echo "#define HAVE_ZLIB_H 1" >>confdefs.h - - ZLIB="-lz" - ;; - builtin) - # handled below - ;; - *) - $as_echo "#define HAVE_ZLIB_H 1" >>confdefs.h - - CPPFLAGS="${CPPFLAGS} -I${enable_zlib}/include" - - if test X"$with_rpath" = X"yes"; then - case "$host" in - *-*-hpux*) ZLIB="${ZLIB} -L$enable_zlib/lib -Wl,+b,$enable_zlib/lib" - ;; - *) ZLIB="${ZLIB} -L$enable_zlib/lib -Wl,-R$enable_zlib/lib" - ;; - esac - else - ZLIB="${ZLIB} -L$enable_zlib/lib" - fi - if test X"$blibpath" != X"" -a "ZLIB" = "SUDO_LDFLAGS"; then - blibpath_add="${blibpath_add}:$enable_zlib/lib" - fi - - ZLIB="${ZLIB} -lz" - ;; - esac - if test X"$enable_zlib" = X"builtin"; then - $as_echo "#define HAVE_ZLIB_H 1" >>confdefs.h - - CPPFLAGS="${CPPFLAGS}"' -I$(srcdir)/zlib' - ZLIB="${ZLIB} libz.a" - ZLIB_DEP=libz.a - fi - -else - - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Disabling I/O log support due to lack of tcsetpgrp function" >&5 -$as_echo "$as_me: WARNING: Disabling I/O log support due to lack of tcsetpgrp function" >&2;} - with_iologdir=no - -fi -done - -fi - case "$with_passwd" in yes|maybe) - AUTH_OBJS="$AUTH_OBJS getspwuid.o passwd.o" + AUTH_OBJS="$AUTH_OBJS getspwuid.lo passwd.lo" ;; *) $as_echo "#define WITHOUT_PASSWD 1" >>confdefs.h @@ -18754,7 +19045,7 @@ yes|maybe) ;; esac AUTH_OBJS=${AUTH_OBJS# } -_AUTH=`echo "$AUTH_OBJS" | sed -e 's/\.o//g' -e 's/getspwuid *//'` +_AUTH=`echo "$AUTH_OBJS" | sed -e 's/\.lo//g' -e 's/getspwuid *//'` { $as_echo "$as_me:${as_lineno-$LINENO}: using the following authentication methods: $_AUTH" >&5 $as_echo "$as_me: using the following authentication methods: $_AUTH" >&6;} @@ -18763,7 +19054,7 @@ if test -n "$LIBS"; then LIBS= for l in ${L}; do dupe=0 - for sl in ${SUDO_LIBS} ${NET_LIBS}; do + for sl in ${SUDO_LIBS} ${SUDOERS_LIBS} ${NET_LIBS}; do test $l = $sl && dupe=1 done test $dupe = 0 && LIBS="${LIBS} $l" @@ -18798,6 +19089,15 @@ EOF EOF fi + eval PLUGINDIR="$with_plugindir" + cat >>confdefs.h <>confdefs.h <confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -19321,7 +19621,7 @@ cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1 # report actual input values of CONFIG_FILES etc. instead of their # values after options handling. ac_log=" -This file was extended by sudo $as_me 1.7.6p1, which was +This file was extended by sudo $as_me 1.8.1p2, which was generated by GNU Autoconf 2.65. Invocation command line was CONFIG_FILES = $CONFIG_FILES @@ -19387,7 +19687,7 @@ _ACEOF cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`" ac_cs_version="\\ -sudo config.status 1.7.6p1 +sudo config.status 1.8.1p2 configured by $0, generated by GNU Autoconf 2.65, with options \\"\$ac_cs_config\\" @@ -19397,6 +19697,7 @@ gives unlimited permission to copy, distribute and modify it." ac_pwd='$ac_pwd' srcdir='$srcdir' +AWK='$AWK' test -n "\$AWK" || AWK=awk _ACEOF @@ -19506,131 +19807,143 @@ cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1 sed_quote_subst='$sed_quote_subst' double_quote_subst='$double_quote_subst' delay_variable_subst='$delay_variable_subst' -macro_version='`$ECHO "X$macro_version" | $Xsed -e "$delay_single_quote_subst"`' -macro_revision='`$ECHO "X$macro_revision" | $Xsed -e "$delay_single_quote_subst"`' -enable_shared='`$ECHO "X$enable_shared" | $Xsed -e "$delay_single_quote_subst"`' -enable_static='`$ECHO "X$enable_static" | $Xsed -e "$delay_single_quote_subst"`' -pic_mode='`$ECHO "X$pic_mode" | $Xsed -e "$delay_single_quote_subst"`' -enable_fast_install='`$ECHO "X$enable_fast_install" | $Xsed -e "$delay_single_quote_subst"`' -host_alias='`$ECHO "X$host_alias" | $Xsed -e "$delay_single_quote_subst"`' -host='`$ECHO "X$host" | $Xsed -e "$delay_single_quote_subst"`' -host_os='`$ECHO "X$host_os" | $Xsed -e "$delay_single_quote_subst"`' -build_alias='`$ECHO "X$build_alias" | $Xsed -e "$delay_single_quote_subst"`' -build='`$ECHO "X$build" | $Xsed -e "$delay_single_quote_subst"`' -build_os='`$ECHO "X$build_os" | $Xsed -e "$delay_single_quote_subst"`' -SED='`$ECHO "X$SED" | $Xsed -e "$delay_single_quote_subst"`' -Xsed='`$ECHO "X$Xsed" | $Xsed -e "$delay_single_quote_subst"`' -GREP='`$ECHO "X$GREP" | $Xsed -e "$delay_single_quote_subst"`' -EGREP='`$ECHO "X$EGREP" | $Xsed -e "$delay_single_quote_subst"`' -FGREP='`$ECHO "X$FGREP" | $Xsed -e "$delay_single_quote_subst"`' -LD='`$ECHO "X$LD" | $Xsed -e "$delay_single_quote_subst"`' -NM='`$ECHO "X$NM" | $Xsed -e "$delay_single_quote_subst"`' -LN_S='`$ECHO "X$LN_S" | $Xsed -e "$delay_single_quote_subst"`' -max_cmd_len='`$ECHO "X$max_cmd_len" | $Xsed -e "$delay_single_quote_subst"`' -ac_objext='`$ECHO "X$ac_objext" | $Xsed -e "$delay_single_quote_subst"`' -exeext='`$ECHO "X$exeext" | $Xsed -e "$delay_single_quote_subst"`' -lt_unset='`$ECHO "X$lt_unset" | $Xsed -e "$delay_single_quote_subst"`' -lt_SP2NL='`$ECHO "X$lt_SP2NL" | $Xsed -e "$delay_single_quote_subst"`' -lt_NL2SP='`$ECHO "X$lt_NL2SP" | $Xsed -e "$delay_single_quote_subst"`' -reload_flag='`$ECHO "X$reload_flag" | $Xsed -e "$delay_single_quote_subst"`' -reload_cmds='`$ECHO "X$reload_cmds" | $Xsed -e "$delay_single_quote_subst"`' -OBJDUMP='`$ECHO "X$OBJDUMP" | $Xsed -e "$delay_single_quote_subst"`' -deplibs_check_method='`$ECHO "X$deplibs_check_method" | $Xsed -e "$delay_single_quote_subst"`' -file_magic_cmd='`$ECHO "X$file_magic_cmd" | $Xsed -e "$delay_single_quote_subst"`' -AR='`$ECHO "X$AR" | $Xsed -e "$delay_single_quote_subst"`' -AR_FLAGS='`$ECHO "X$AR_FLAGS" | $Xsed -e "$delay_single_quote_subst"`' -STRIP='`$ECHO "X$STRIP" | $Xsed -e "$delay_single_quote_subst"`' -RANLIB='`$ECHO "X$RANLIB" | $Xsed -e "$delay_single_quote_subst"`' -old_postinstall_cmds='`$ECHO "X$old_postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' -old_postuninstall_cmds='`$ECHO "X$old_postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' -old_archive_cmds='`$ECHO "X$old_archive_cmds" | $Xsed -e "$delay_single_quote_subst"`' -CC='`$ECHO "X$CC" | $Xsed -e "$delay_single_quote_subst"`' -CFLAGS='`$ECHO "X$CFLAGS" | $Xsed -e "$delay_single_quote_subst"`' -compiler='`$ECHO "X$compiler" | $Xsed -e "$delay_single_quote_subst"`' -GCC='`$ECHO "X$GCC" | $Xsed -e "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_pipe='`$ECHO "X$lt_cv_sys_global_symbol_pipe" | $Xsed -e "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_to_cdecl='`$ECHO "X$lt_cv_sys_global_symbol_to_cdecl" | $Xsed -e "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address" | $Xsed -e "$delay_single_quote_subst"`' -lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "X$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`' -objdir='`$ECHO "X$objdir" | $Xsed -e "$delay_single_quote_subst"`' -SHELL='`$ECHO "X$SHELL" | $Xsed -e "$delay_single_quote_subst"`' -ECHO='`$ECHO "X$ECHO" | $Xsed -e "$delay_single_quote_subst"`' -MAGIC_CMD='`$ECHO "X$MAGIC_CMD" | $Xsed -e "$delay_single_quote_subst"`' -lt_prog_compiler_no_builtin_flag='`$ECHO "X$lt_prog_compiler_no_builtin_flag" | $Xsed -e "$delay_single_quote_subst"`' -lt_prog_compiler_wl='`$ECHO "X$lt_prog_compiler_wl" | $Xsed -e "$delay_single_quote_subst"`' -lt_prog_compiler_pic='`$ECHO "X$lt_prog_compiler_pic" | $Xsed -e "$delay_single_quote_subst"`' -lt_prog_compiler_static='`$ECHO "X$lt_prog_compiler_static" | $Xsed -e "$delay_single_quote_subst"`' -lt_cv_prog_compiler_c_o='`$ECHO "X$lt_cv_prog_compiler_c_o" | $Xsed -e "$delay_single_quote_subst"`' -need_locks='`$ECHO "X$need_locks" | $Xsed -e "$delay_single_quote_subst"`' -DSYMUTIL='`$ECHO "X$DSYMUTIL" | $Xsed -e "$delay_single_quote_subst"`' -NMEDIT='`$ECHO "X$NMEDIT" | $Xsed -e "$delay_single_quote_subst"`' -LIPO='`$ECHO "X$LIPO" | $Xsed -e "$delay_single_quote_subst"`' -OTOOL='`$ECHO "X$OTOOL" | $Xsed -e "$delay_single_quote_subst"`' -OTOOL64='`$ECHO "X$OTOOL64" | $Xsed -e "$delay_single_quote_subst"`' -libext='`$ECHO "X$libext" | $Xsed -e "$delay_single_quote_subst"`' -shrext_cmds='`$ECHO "X$shrext_cmds" | $Xsed -e "$delay_single_quote_subst"`' -extract_expsyms_cmds='`$ECHO "X$extract_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`' -archive_cmds_need_lc='`$ECHO "X$archive_cmds_need_lc" | $Xsed -e "$delay_single_quote_subst"`' -enable_shared_with_static_runtimes='`$ECHO "X$enable_shared_with_static_runtimes" | $Xsed -e "$delay_single_quote_subst"`' -export_dynamic_flag_spec='`$ECHO "X$export_dynamic_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' -whole_archive_flag_spec='`$ECHO "X$whole_archive_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' -compiler_needs_object='`$ECHO "X$compiler_needs_object" | $Xsed -e "$delay_single_quote_subst"`' -old_archive_from_new_cmds='`$ECHO "X$old_archive_from_new_cmds" | $Xsed -e "$delay_single_quote_subst"`' -old_archive_from_expsyms_cmds='`$ECHO "X$old_archive_from_expsyms_cmds" | $Xsed -e "$delay_single_quote_subst"`' -archive_cmds='`$ECHO "X$archive_cmds" | $Xsed -e "$delay_single_quote_subst"`' -archive_expsym_cmds='`$ECHO "X$archive_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`' -module_cmds='`$ECHO "X$module_cmds" | $Xsed -e "$delay_single_quote_subst"`' -module_expsym_cmds='`$ECHO "X$module_expsym_cmds" | $Xsed -e "$delay_single_quote_subst"`' -with_gnu_ld='`$ECHO "X$with_gnu_ld" | $Xsed -e "$delay_single_quote_subst"`' -allow_undefined_flag='`$ECHO "X$allow_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`' -no_undefined_flag='`$ECHO "X$no_undefined_flag" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_libdir_flag_spec='`$ECHO "X$hardcode_libdir_flag_spec" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_libdir_flag_spec_ld='`$ECHO "X$hardcode_libdir_flag_spec_ld" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_libdir_separator='`$ECHO "X$hardcode_libdir_separator" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_direct='`$ECHO "X$hardcode_direct" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_direct_absolute='`$ECHO "X$hardcode_direct_absolute" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_minus_L='`$ECHO "X$hardcode_minus_L" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_shlibpath_var='`$ECHO "X$hardcode_shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_automatic='`$ECHO "X$hardcode_automatic" | $Xsed -e "$delay_single_quote_subst"`' -inherit_rpath='`$ECHO "X$inherit_rpath" | $Xsed -e "$delay_single_quote_subst"`' -link_all_deplibs='`$ECHO "X$link_all_deplibs" | $Xsed -e "$delay_single_quote_subst"`' -fix_srcfile_path='`$ECHO "X$fix_srcfile_path" | $Xsed -e "$delay_single_quote_subst"`' -always_export_symbols='`$ECHO "X$always_export_symbols" | $Xsed -e "$delay_single_quote_subst"`' -export_symbols_cmds='`$ECHO "X$export_symbols_cmds" | $Xsed -e "$delay_single_quote_subst"`' -exclude_expsyms='`$ECHO "X$exclude_expsyms" | $Xsed -e "$delay_single_quote_subst"`' -include_expsyms='`$ECHO "X$include_expsyms" | $Xsed -e "$delay_single_quote_subst"`' -prelink_cmds='`$ECHO "X$prelink_cmds" | $Xsed -e "$delay_single_quote_subst"`' -file_list_spec='`$ECHO "X$file_list_spec" | $Xsed -e "$delay_single_quote_subst"`' -variables_saved_for_relink='`$ECHO "X$variables_saved_for_relink" | $Xsed -e "$delay_single_quote_subst"`' -need_lib_prefix='`$ECHO "X$need_lib_prefix" | $Xsed -e "$delay_single_quote_subst"`' -need_version='`$ECHO "X$need_version" | $Xsed -e "$delay_single_quote_subst"`' -version_type='`$ECHO "X$version_type" | $Xsed -e "$delay_single_quote_subst"`' -runpath_var='`$ECHO "X$runpath_var" | $Xsed -e "$delay_single_quote_subst"`' -shlibpath_var='`$ECHO "X$shlibpath_var" | $Xsed -e "$delay_single_quote_subst"`' -shlibpath_overrides_runpath='`$ECHO "X$shlibpath_overrides_runpath" | $Xsed -e "$delay_single_quote_subst"`' -libname_spec='`$ECHO "X$libname_spec" | $Xsed -e "$delay_single_quote_subst"`' -library_names_spec='`$ECHO "X$library_names_spec" | $Xsed -e "$delay_single_quote_subst"`' -soname_spec='`$ECHO "X$soname_spec" | $Xsed -e "$delay_single_quote_subst"`' -postinstall_cmds='`$ECHO "X$postinstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' -postuninstall_cmds='`$ECHO "X$postuninstall_cmds" | $Xsed -e "$delay_single_quote_subst"`' -finish_cmds='`$ECHO "X$finish_cmds" | $Xsed -e "$delay_single_quote_subst"`' -finish_eval='`$ECHO "X$finish_eval" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_into_libs='`$ECHO "X$hardcode_into_libs" | $Xsed -e "$delay_single_quote_subst"`' -sys_lib_search_path_spec='`$ECHO "X$sys_lib_search_path_spec" | $Xsed -e "$delay_single_quote_subst"`' -sys_lib_dlsearch_path_spec='`$ECHO "X$sys_lib_dlsearch_path_spec" | $Xsed -e "$delay_single_quote_subst"`' -hardcode_action='`$ECHO "X$hardcode_action" | $Xsed -e "$delay_single_quote_subst"`' -enable_dlopen='`$ECHO "X$enable_dlopen" | $Xsed -e "$delay_single_quote_subst"`' -enable_dlopen_self='`$ECHO "X$enable_dlopen_self" | $Xsed -e "$delay_single_quote_subst"`' -enable_dlopen_self_static='`$ECHO "X$enable_dlopen_self_static" | $Xsed -e "$delay_single_quote_subst"`' -old_striplib='`$ECHO "X$old_striplib" | $Xsed -e "$delay_single_quote_subst"`' -striplib='`$ECHO "X$striplib" | $Xsed -e "$delay_single_quote_subst"`' +macro_version='`$ECHO "$macro_version" | $SED "$delay_single_quote_subst"`' +macro_revision='`$ECHO "$macro_revision" | $SED "$delay_single_quote_subst"`' +enable_shared='`$ECHO "$enable_shared" | $SED "$delay_single_quote_subst"`' +enable_static='`$ECHO "$enable_static" | $SED "$delay_single_quote_subst"`' +pic_mode='`$ECHO "$pic_mode" | $SED "$delay_single_quote_subst"`' +enable_fast_install='`$ECHO "$enable_fast_install" | $SED "$delay_single_quote_subst"`' +SHELL='`$ECHO "$SHELL" | $SED "$delay_single_quote_subst"`' +ECHO='`$ECHO "$ECHO" | $SED "$delay_single_quote_subst"`' +host_alias='`$ECHO "$host_alias" | $SED "$delay_single_quote_subst"`' +host='`$ECHO "$host" | $SED "$delay_single_quote_subst"`' +host_os='`$ECHO "$host_os" | $SED "$delay_single_quote_subst"`' +build_alias='`$ECHO "$build_alias" | $SED "$delay_single_quote_subst"`' +build='`$ECHO "$build" | $SED "$delay_single_quote_subst"`' +build_os='`$ECHO "$build_os" | $SED "$delay_single_quote_subst"`' +SED='`$ECHO "$SED" | $SED "$delay_single_quote_subst"`' +Xsed='`$ECHO "$Xsed" | $SED "$delay_single_quote_subst"`' +GREP='`$ECHO "$GREP" | $SED "$delay_single_quote_subst"`' +EGREP='`$ECHO "$EGREP" | $SED "$delay_single_quote_subst"`' +FGREP='`$ECHO "$FGREP" | $SED "$delay_single_quote_subst"`' +LD='`$ECHO "$LD" | $SED "$delay_single_quote_subst"`' +NM='`$ECHO "$NM" | $SED "$delay_single_quote_subst"`' +LN_S='`$ECHO "$LN_S" | $SED "$delay_single_quote_subst"`' +max_cmd_len='`$ECHO "$max_cmd_len" | $SED "$delay_single_quote_subst"`' +ac_objext='`$ECHO "$ac_objext" | $SED "$delay_single_quote_subst"`' +exeext='`$ECHO "$exeext" | $SED "$delay_single_quote_subst"`' +lt_unset='`$ECHO "$lt_unset" | $SED "$delay_single_quote_subst"`' +lt_SP2NL='`$ECHO "$lt_SP2NL" | $SED "$delay_single_quote_subst"`' +lt_NL2SP='`$ECHO "$lt_NL2SP" | $SED "$delay_single_quote_subst"`' +reload_flag='`$ECHO "$reload_flag" | $SED "$delay_single_quote_subst"`' +reload_cmds='`$ECHO "$reload_cmds" | $SED "$delay_single_quote_subst"`' +OBJDUMP='`$ECHO "$OBJDUMP" | $SED "$delay_single_quote_subst"`' +deplibs_check_method='`$ECHO "$deplibs_check_method" | $SED "$delay_single_quote_subst"`' +file_magic_cmd='`$ECHO "$file_magic_cmd" | $SED "$delay_single_quote_subst"`' +AR='`$ECHO "$AR" | $SED "$delay_single_quote_subst"`' +AR_FLAGS='`$ECHO "$AR_FLAGS" | $SED "$delay_single_quote_subst"`' +STRIP='`$ECHO "$STRIP" | $SED "$delay_single_quote_subst"`' +RANLIB='`$ECHO "$RANLIB" | $SED "$delay_single_quote_subst"`' +old_postinstall_cmds='`$ECHO "$old_postinstall_cmds" | $SED "$delay_single_quote_subst"`' +old_postuninstall_cmds='`$ECHO "$old_postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_cmds='`$ECHO "$old_archive_cmds" | $SED "$delay_single_quote_subst"`' +lock_old_archive_extraction='`$ECHO "$lock_old_archive_extraction" | $SED "$delay_single_quote_subst"`' +CC='`$ECHO "$CC" | $SED "$delay_single_quote_subst"`' +CFLAGS='`$ECHO "$CFLAGS" | $SED "$delay_single_quote_subst"`' +compiler='`$ECHO "$compiler" | $SED "$delay_single_quote_subst"`' +GCC='`$ECHO "$GCC" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_pipe='`$ECHO "$lt_cv_sys_global_symbol_pipe" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_cdecl='`$ECHO "$lt_cv_sys_global_symbol_to_cdecl" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address" | $SED "$delay_single_quote_subst"`' +lt_cv_sys_global_symbol_to_c_name_address_lib_prefix='`$ECHO "$lt_cv_sys_global_symbol_to_c_name_address_lib_prefix" | $SED "$delay_single_quote_subst"`' +objdir='`$ECHO "$objdir" | $SED "$delay_single_quote_subst"`' +MAGIC_CMD='`$ECHO "$MAGIC_CMD" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_no_builtin_flag='`$ECHO "$lt_prog_compiler_no_builtin_flag" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_wl='`$ECHO "$lt_prog_compiler_wl" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_pic='`$ECHO "$lt_prog_compiler_pic" | $SED "$delay_single_quote_subst"`' +lt_prog_compiler_static='`$ECHO "$lt_prog_compiler_static" | $SED "$delay_single_quote_subst"`' +lt_cv_prog_compiler_c_o='`$ECHO "$lt_cv_prog_compiler_c_o" | $SED "$delay_single_quote_subst"`' +need_locks='`$ECHO "$need_locks" | $SED "$delay_single_quote_subst"`' +DSYMUTIL='`$ECHO "$DSYMUTIL" | $SED "$delay_single_quote_subst"`' +NMEDIT='`$ECHO "$NMEDIT" | $SED "$delay_single_quote_subst"`' +LIPO='`$ECHO "$LIPO" | $SED "$delay_single_quote_subst"`' +OTOOL='`$ECHO "$OTOOL" | $SED "$delay_single_quote_subst"`' +OTOOL64='`$ECHO "$OTOOL64" | $SED "$delay_single_quote_subst"`' +libext='`$ECHO "$libext" | $SED "$delay_single_quote_subst"`' +shrext_cmds='`$ECHO "$shrext_cmds" | $SED "$delay_single_quote_subst"`' +extract_expsyms_cmds='`$ECHO "$extract_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds_need_lc='`$ECHO "$archive_cmds_need_lc" | $SED "$delay_single_quote_subst"`' +enable_shared_with_static_runtimes='`$ECHO "$enable_shared_with_static_runtimes" | $SED "$delay_single_quote_subst"`' +export_dynamic_flag_spec='`$ECHO "$export_dynamic_flag_spec" | $SED "$delay_single_quote_subst"`' +whole_archive_flag_spec='`$ECHO "$whole_archive_flag_spec" | $SED "$delay_single_quote_subst"`' +compiler_needs_object='`$ECHO "$compiler_needs_object" | $SED "$delay_single_quote_subst"`' +old_archive_from_new_cmds='`$ECHO "$old_archive_from_new_cmds" | $SED "$delay_single_quote_subst"`' +old_archive_from_expsyms_cmds='`$ECHO "$old_archive_from_expsyms_cmds" | $SED "$delay_single_quote_subst"`' +archive_cmds='`$ECHO "$archive_cmds" | $SED "$delay_single_quote_subst"`' +archive_expsym_cmds='`$ECHO "$archive_expsym_cmds" | $SED "$delay_single_quote_subst"`' +module_cmds='`$ECHO "$module_cmds" | $SED "$delay_single_quote_subst"`' +module_expsym_cmds='`$ECHO "$module_expsym_cmds" | $SED "$delay_single_quote_subst"`' +with_gnu_ld='`$ECHO "$with_gnu_ld" | $SED "$delay_single_quote_subst"`' +allow_undefined_flag='`$ECHO "$allow_undefined_flag" | $SED "$delay_single_quote_subst"`' +no_undefined_flag='`$ECHO "$no_undefined_flag" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec='`$ECHO "$hardcode_libdir_flag_spec" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_flag_spec_ld='`$ECHO "$hardcode_libdir_flag_spec_ld" | $SED "$delay_single_quote_subst"`' +hardcode_libdir_separator='`$ECHO "$hardcode_libdir_separator" | $SED "$delay_single_quote_subst"`' +hardcode_direct='`$ECHO "$hardcode_direct" | $SED "$delay_single_quote_subst"`' +hardcode_direct_absolute='`$ECHO "$hardcode_direct_absolute" | $SED "$delay_single_quote_subst"`' +hardcode_minus_L='`$ECHO "$hardcode_minus_L" | $SED "$delay_single_quote_subst"`' +hardcode_shlibpath_var='`$ECHO "$hardcode_shlibpath_var" | $SED "$delay_single_quote_subst"`' +hardcode_automatic='`$ECHO "$hardcode_automatic" | $SED "$delay_single_quote_subst"`' +inherit_rpath='`$ECHO "$inherit_rpath" | $SED "$delay_single_quote_subst"`' +link_all_deplibs='`$ECHO "$link_all_deplibs" | $SED "$delay_single_quote_subst"`' +fix_srcfile_path='`$ECHO "$fix_srcfile_path" | $SED "$delay_single_quote_subst"`' +always_export_symbols='`$ECHO "$always_export_symbols" | $SED "$delay_single_quote_subst"`' +export_symbols_cmds='`$ECHO "$export_symbols_cmds" | $SED "$delay_single_quote_subst"`' +exclude_expsyms='`$ECHO "$exclude_expsyms" | $SED "$delay_single_quote_subst"`' +include_expsyms='`$ECHO "$include_expsyms" | $SED "$delay_single_quote_subst"`' +prelink_cmds='`$ECHO "$prelink_cmds" | $SED "$delay_single_quote_subst"`' +file_list_spec='`$ECHO "$file_list_spec" | $SED "$delay_single_quote_subst"`' +variables_saved_for_relink='`$ECHO "$variables_saved_for_relink" | $SED "$delay_single_quote_subst"`' +need_lib_prefix='`$ECHO "$need_lib_prefix" | $SED "$delay_single_quote_subst"`' +need_version='`$ECHO "$need_version" | $SED "$delay_single_quote_subst"`' +version_type='`$ECHO "$version_type" | $SED "$delay_single_quote_subst"`' +runpath_var='`$ECHO "$runpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_var='`$ECHO "$shlibpath_var" | $SED "$delay_single_quote_subst"`' +shlibpath_overrides_runpath='`$ECHO "$shlibpath_overrides_runpath" | $SED "$delay_single_quote_subst"`' +libname_spec='`$ECHO "$libname_spec" | $SED "$delay_single_quote_subst"`' +library_names_spec='`$ECHO "$library_names_spec" | $SED "$delay_single_quote_subst"`' +soname_spec='`$ECHO "$soname_spec" | $SED "$delay_single_quote_subst"`' +install_override_mode='`$ECHO "$install_override_mode" | $SED "$delay_single_quote_subst"`' +postinstall_cmds='`$ECHO "$postinstall_cmds" | $SED "$delay_single_quote_subst"`' +postuninstall_cmds='`$ECHO "$postuninstall_cmds" | $SED "$delay_single_quote_subst"`' +finish_cmds='`$ECHO "$finish_cmds" | $SED "$delay_single_quote_subst"`' +finish_eval='`$ECHO "$finish_eval" | $SED "$delay_single_quote_subst"`' +hardcode_into_libs='`$ECHO "$hardcode_into_libs" | $SED "$delay_single_quote_subst"`' +sys_lib_search_path_spec='`$ECHO "$sys_lib_search_path_spec" | $SED "$delay_single_quote_subst"`' +sys_lib_dlsearch_path_spec='`$ECHO "$sys_lib_dlsearch_path_spec" | $SED "$delay_single_quote_subst"`' +hardcode_action='`$ECHO "$hardcode_action" | $SED "$delay_single_quote_subst"`' +enable_dlopen='`$ECHO "$enable_dlopen" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self='`$ECHO "$enable_dlopen_self" | $SED "$delay_single_quote_subst"`' +enable_dlopen_self_static='`$ECHO "$enable_dlopen_self_static" | $SED "$delay_single_quote_subst"`' +old_striplib='`$ECHO "$old_striplib" | $SED "$delay_single_quote_subst"`' +striplib='`$ECHO "$striplib" | $SED "$delay_single_quote_subst"`' LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + # Quote evaled strings. -for var in SED \ +for var in SHELL \ +ECHO \ +SED \ GREP \ EGREP \ FGREP \ @@ -19654,8 +19967,6 @@ lt_cv_sys_global_symbol_pipe \ lt_cv_sys_global_symbol_to_cdecl \ lt_cv_sys_global_symbol_to_c_name_address \ lt_cv_sys_global_symbol_to_c_name_address_lib_prefix \ -SHELL \ -ECHO \ lt_prog_compiler_no_builtin_flag \ lt_prog_compiler_wl \ lt_prog_compiler_pic \ @@ -19685,12 +19996,13 @@ variables_saved_for_relink \ libname_spec \ library_names_spec \ soname_spec \ +install_override_mode \ finish_eval \ old_striplib \ striplib; do - case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -19717,9 +20029,9 @@ postuninstall_cmds \ finish_cmds \ sys_lib_search_path_spec \ sys_lib_dlsearch_path_spec; do - case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[\\\\\\\`\\"\\\$]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -19727,12 +20039,6 @@ sys_lib_dlsearch_path_spec; do esac done -# Fix-up fallback echo if it was mangled by the above quoting rules. -case \$lt_ECHO in -*'\\\$0 --fallback-echo"') lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\$0 --fallback-echo"\$/\$0 --fallback-echo"/'\` - ;; -esac - ac_aux_dir='$ac_aux_dir' xsi_shell='$xsi_shell' lt_shell_append='$lt_shell_append' @@ -19763,16 +20069,20 @@ do case $ac_config_target in "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;; "pathnames.h") CONFIG_HEADERS="$CONFIG_HEADERS pathnames.h" ;; - "zlib/zconf.h") CONFIG_HEADERS="$CONFIG_HEADERS zlib/zconf.h" ;; "libtool") CONFIG_COMMANDS="$CONFIG_COMMANDS libtool" ;; + "zlib/zconf.h") CONFIG_HEADERS="$CONFIG_HEADERS zlib/zconf.h" ;; + "zlib/Makefile") CONFIG_FILES="$CONFIG_FILES zlib/Makefile" ;; "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;; - "sudo.man") CONFIG_FILES="$CONFIG_FILES sudo.man" ;; - "visudo.man") CONFIG_FILES="$CONFIG_FILES visudo.man" ;; - "sudoers.man") CONFIG_FILES="$CONFIG_FILES sudoers.man" ;; - "sudoers.ldap.man") CONFIG_FILES="$CONFIG_FILES sudoers.ldap.man" ;; - "sudoreplay.man") CONFIG_FILES="$CONFIG_FILES sudoreplay.man" ;; - "sudo_usage.h") CONFIG_FILES="$CONFIG_FILES sudo_usage.h" ;; - "sudoers") CONFIG_FILES="$CONFIG_FILES sudoers" ;; + "common/Makefile") CONFIG_FILES="$CONFIG_FILES common/Makefile" ;; + "compat/Makefile") CONFIG_FILES="$CONFIG_FILES compat/Makefile" ;; + "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;; + "include/Makefile") CONFIG_FILES="$CONFIG_FILES include/Makefile" ;; + "src/sudo_usage.h") CONFIG_FILES="$CONFIG_FILES src/sudo_usage.h" ;; + "src/Makefile") CONFIG_FILES="$CONFIG_FILES src/Makefile" ;; + "plugins/sample/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/sample/Makefile" ;; + "plugins/sample_group/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/sample_group/Makefile" ;; + "plugins/sudoers/Makefile") CONFIG_FILES="$CONFIG_FILES plugins/sudoers/Makefile" ;; + "plugins/sudoers/sudoers") CONFIG_FILES="$CONFIG_FILES plugins/sudoers/sudoers" ;; *) as_fn_error "invalid argument: \`$ac_config_target'" "$LINENO" 5;; esac @@ -20333,7 +20643,8 @@ $as_echo "$as_me: executing $ac_file commands" >&6;} # NOTE: Changes made to this file will be lost: look at ltmain.sh. # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, -# 2006, 2007, 2008 Free Software Foundation, Inc. +# 2006, 2007, 2008, 2009, 2010 Free Software Foundation, +# Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. @@ -20381,6 +20692,12 @@ pic_mode=$pic_mode # Whether or not to optimize for fast installation. fast_install=$enable_fast_install +# Shell to use when invoking shell scripts. +SHELL=$lt_SHELL + +# An echo program that protects backslashes. +ECHO=$lt_ECHO + # The host system. host_alias=$host_alias host=$host @@ -20430,10 +20747,6 @@ SP2NL=$lt_lt_SP2NL # turn newlines into spaces. NL2SP=$lt_lt_NL2SP -# How to create reloadable object files. -reload_flag=$lt_reload_flag -reload_cmds=$lt_reload_cmds - # An object symbol dumper. OBJDUMP=$lt_OBJDUMP @@ -20455,6 +20768,9 @@ RANLIB=$lt_RANLIB old_postinstall_cmds=$lt_old_postinstall_cmds old_postuninstall_cmds=$lt_old_postuninstall_cmds +# Whether to use a lock for old archive extraction. +lock_old_archive_extraction=$lock_old_archive_extraction + # A C compiler. LTCC=$lt_CC @@ -20476,12 +20792,6 @@ global_symbol_to_c_name_address_lib_prefix=$lt_lt_cv_sys_global_symbol_to_c_name # The name of the directory that contains temporary libtool files. objdir=$objdir -# Shell to use when invoking shell scripts. -SHELL=$lt_SHELL - -# An echo program that does not interpret backslashes. -ECHO=$lt_ECHO - # Used to examine libraries when file_magic_cmd begins with "file". MAGIC_CMD=$MAGIC_CMD @@ -20544,6 +20854,9 @@ library_names_spec=$lt_library_names_spec # The coded name of the library, if different from the real name. soname_spec=$lt_soname_spec +# Permission mode override for installation of shared libraries. +install_override_mode=$lt_install_override_mode + # Command to use after installation of a shared archive. postinstall_cmds=$lt_postinstall_cmds @@ -20583,6 +20896,10 @@ striplib=$lt_striplib # The linker used to build libraries. LD=$lt_LD +# How to create reloadable object files. +reload_flag=$lt_reload_flag +reload_cmds=$lt_reload_cmds + # Commands used to build an old-style archive. old_archive_cmds=$lt_old_archive_cmds @@ -20842,7 +21159,7 @@ _LT_EOF func_dirname () { # Extract subdirectory from the argument. - func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` + func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else @@ -20853,7 +21170,7 @@ func_dirname () # func_basename file func_basename () { - func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` + func_basename_result=`$ECHO "${1}" | $SED "$basename"` } @@ -20866,10 +21183,8 @@ func_basename () func_stripname () { case ${2} in - .*) func_stripname_result=`$ECHO "X${3}" \ - | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;; - *) func_stripname_result=`$ECHO "X${3}" \ - | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;; + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } @@ -20880,20 +21195,20 @@ my_sed_long_arg='1s/^-[^=]*=//' # func_opt_split func_opt_split () { - func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"` - func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"` + func_opt_split_opt=`$ECHO "${1}" | $SED "$my_sed_long_opt"` + func_opt_split_arg=`$ECHO "${1}" | $SED "$my_sed_long_arg"` } # func_lo2o object func_lo2o () { - func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"` + func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` } # func_xform libobj-or-source func_xform () { - func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[^.]*$/.lo/'` + func_xform_result=`$ECHO "${1}" | $SED 's/\.[^.]*$/.lo/'` } # func_arith arithmetic-term... @@ -21078,6 +21393,10 @@ fi + + + + diff --git a/configure.in b/configure.in index 29d7f28..d180df4 100644 --- a/configure.in +++ b/configure.in @@ -3,8 +3,8 @@ dnl Process this file with GNU autoconf to produce a configure script. dnl dnl Copyright (c) 1994-1996,1998-2011 Todd C. Miller dnl -AC_INIT([sudo], [1.7.6p1], [http://www.sudo.ws/bugs/], [sudo]) -AC_CONFIG_HEADER(config.h pathnames.h zlib/zconf.h) +AC_INIT([sudo], [1.8.1p2], [http://www.sudo.ws/bugs/], [sudo]) +AC_CONFIG_HEADER([config.h pathnames.h]) dnl dnl Note: this must come after AC_INIT dnl @@ -19,13 +19,17 @@ AC_SUBST([CFLAGS]) AC_SUBST([PROGS]) AC_SUBST([CPPFLAGS]) AC_SUBST([LDFLAGS]) +AC_SUBST([SUDOERS_LDFLAGS]) +AC_SUBST([LTLDFLAGS]) AC_SUBST([COMMON_OBJS]) -AC_SUBST([SUDO_LDFLAGS]) +AC_SUBST([SUDOERS_OBJS]) AC_SUBST([SUDO_OBJS]) AC_SUBST([LIBS]) AC_SUBST([SUDO_LIBS]) +AC_SUBST([SUDOERS_LIBS]) AC_SUBST([NET_LIBS]) AC_SUBST([AFS_LIBS]) +AC_SUBST([REPLAY_LIBS]) AC_SUBST([GETGROUPS_LIB]) AC_SUBST([OSDEFS]) AC_SUBST([AUTH_OBJS]) @@ -44,17 +48,22 @@ AC_SUBST([mansectform]) AC_SUBST([mansrcdir]) AC_SUBST([NOEXECFILE]) AC_SUBST([NOEXECDIR]) +AC_SUBST([PLUGINDIR]) +AC_SUBST([SOEXT]) AC_SUBST([noexec_file]) AC_SUBST([INSTALL_NOEXEC]) AC_SUBST([DONT_LEAK_PATH_INFO]) AC_SUBST([BSDAUTH_USAGE]) AC_SUBST([SELINUX_USAGE]) AC_SUBST([LDAP]) -AC_SUBST([REPLAY]) AC_SUBST([LOGINCAP_USAGE]) AC_SUBST([ZLIB]) -AC_SUBST([ZLIB_DEP]) +AC_SUBST([ZLIB_SRC]) +AC_SUBST([LIBTOOL_DEPS]) +AC_SUBST([ac_config_libobj_dir]) AC_SUBST([CONFIGURE_ARGS]) +AC_SUBST([LIBDL]) +AC_SUBST([LT_STATIC]) dnl dnl Variables that get substituted in docs (not overridden by environment) dnl @@ -141,7 +150,7 @@ dnl May be overridden by environment variables.. dnl INSTALL_NOEXEC= devdir='$(srcdir)' -PROGS="sudo visudo" +PROGS="sudo" : ${MANTYPE='man'} : ${mansrcdir='.'} : ${SUDOERS_MODE='0440'} @@ -149,12 +158,11 @@ PROGS="sudo visudo" : ${SUDOERS_GID='0'} DEV="#" LDAP="#" -REPLAY="#" BAMAN=0 LCMAN=0 SEMAN=0 ZLIB= -ZLIB_DEP= +ZLIB_SRC= AUTH_OBJS= AUTH_REG= AUTH_EXCL= @@ -169,9 +177,13 @@ shadow_defs= shadow_funcs= shadow_libs= shadow_libs_optional= - CONFIGURE_ARGS="$@" +dnl +dnl libc replacement functions live in compat +dnl +AC_CONFIG_LIBOBJ_DIR(compat) + dnl dnl Deprecated --with options (these all warn or generate an error) dnl @@ -197,7 +209,6 @@ dnl AC_ARG_WITH(devel, [AS_HELP_STRING([--with-devel], [add development options])], [case $with_devel in yes) AC_MSG_NOTICE([Setting up for development: -Wall, flex, yacc]) - PROGS="${PROGS} testsudoers" OSDEFS="${OSDEFS} -DSUDO_DEVEL" DEV="" devdir=. @@ -237,8 +248,8 @@ dnl AC_ARG_WITH(bsm-audit, [AS_HELP_STRING([--with-bsm-audit], [enable BSM audit support])], [case $with_bsm_audit in yes) AC_DEFINE(HAVE_BSM_AUDIT) - SUDO_LIBS="${SUDO_LIBS} -lbsm" - SUDO_OBJS="${SUDO_OBJS} bsm_audit.o" + SUDOERS_LIBS="${SUDOERS_LIBS} -lbsm" + SUDOERS_OBJS="${SUDOERS_OBJS} bsm_audit.lo" ;; no) ;; *) AC_MSG_ERROR(["--with-bsm-audit does not take an argument."]) @@ -253,7 +264,8 @@ AC_ARG_WITH(linux-audit, [AS_HELP_STRING([--with-linux-audit], [enable Linux aud yes) AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[int i = AUDIT_USER_CMD; (void)i;]])], [ AC_DEFINE(HAVE_LINUX_AUDIT) SUDO_LIBS="${SUDO_LIBS} -laudit" - SUDO_OBJS="${SUDO_OBJS} linux_audit.o" + SUDOERS_LIBS="${SUDO_LIBS} -laudit" + SUDOERS_OBJS="${SUDOERS_OBJS} linux_audit.lo" ], [ AC_MSG_ERROR([unable to find AUDIT_USER_CMD in libaudit.h for --with-linux-audit]) ]) @@ -721,8 +733,9 @@ esac]) AC_ARG_WITH(iologdir, [AS_HELP_STRING([--with-iologdir=DIR], [directory to store sudo I/O log files in])], [case $with_iologdir in - yes) ;; - no) ;; + yes) ;; + no) AC_MSG_ERROR(["--without-iologdir not supported."]) + ;; esac]) AC_ARG_WITH(sendmail, [AS_HELP_STRING([--with-sendmail], [set path to sendmail]) @@ -1084,32 +1097,12 @@ AC_ARG_WITH(askpass, [AS_HELP_STRING([--with-askpass=PATH], [Fully qualified pat ;; esac], AC_MSG_RESULT(no)) -dnl -dnl If enabled, set LIBVAS_SO, LIBVAS_RPATH and USING_NONUNIX_GROUPS -dnl -AC_ARG_WITH(libvas, [AS_HELP_STRING([--with-libvas=NAME], [Name of the libvas shared library (default=libvas.so)])], -[case $with_libvas in - yes) with_libvas=libvas.so - ;; - no) ;; - *) AC_DEFINE_UNQUOTED([LIBVAS_SO], ["$with_libvas"], [The name of libvas.so]) +AC_ARG_WITH(plugindir, [AS_HELP_STRING([--with-plugindir], [set directory to load plugins from])], +[case $with_plugindir in + no) AC_MSG_ERROR(["illegal argument: --without-plugindir."]) ;; -esac -if test X"$with_libvas" != X"no"; then - AC_DEFINE_UNQUOTED([LIBVAS_SO], ["$with_libvas"], [The name of libvas.so]) - AC_DEFINE(USING_NONUNIX_GROUPS) - COMMON_OBJS="$COMMON_OBJS vasgroups.o" - AC_ARG_WITH([libvas-rpath], - [AS_HELP_STRING([--with-libvas-rpath=PATH], - [Path to look for libvas in [default=/opt/quest/lib]])], - [LIBVAS_RPATH=$withval], - [LIBVAS_RPATH=/opt/quest/lib]) - dnl - dnl Some platforms require libdl for dlopen() - dnl - AC_CHECK_LIB([dl], [main]) -fi -]) + *) ;; +esac], [with_plugindir="$libexecdir"]) dnl dnl Options for --enable @@ -1269,6 +1262,10 @@ AC_ARG_ENABLE(env_debug, esac ], AC_MSG_RESULT(no)) +AC_ARG_ENABLE(zlib, +[AS_HELP_STRING([--enable-zlib[[=PATH]]], [Whether to enable or disable zlib])], +[]) + AC_MSG_CHECKING(whether to enable environment resetting by default) AC_ARG_ENABLE(env_reset, [AS_HELP_STRING([--enable-env-reset], [Whether to enable environment resetting by default.])], @@ -1348,21 +1345,34 @@ if test X"$AR" = X"false"; then AC_MSG_ERROR([the "ar" utility is required to build sudo]) fi +if test "x$ac_cv_prog_cc_c89" = "xno"; then + AC_MSG_ERROR([Sudo version $PACKAGE_VERSION requires an ANSI C compiler to build.]) +fi + dnl dnl Libtool setup, we require libtool 2.2.6b or higher dnl AC_CANONICAL_HOST AC_CONFIG_MACRO_DIR([m4]) LT_PREREQ([2.2.6b]) -LT_INIT +LT_INIT([dlopen]) dnl dnl Defer with_noexec until after libtool magic runs dnl if test "$enable_shared" = "no"; then with_noexec=no + enable_dlopen=no + lt_cv_dlopen=none + lt_cv_dlopen_libs= else eval _shrext="$shrext_cmds" + # Darwin uses .dylib for libraries but .so for modules + if test X"$_shrext" = X".dylib"; then + SOEXT=".so" + else + SOEXT="$_shrext" + fi fi AC_MSG_CHECKING(path to sudo_noexec.so) AC_ARG_WITH(noexec, [AS_HELP_STRING([--with-noexec[=PATH]], [fully qualified pathname of sudo_noexec.so])], @@ -1447,11 +1457,12 @@ case "$host" in : ${mansectform='4'} : ${with_rpath='yes'} test -z "$with_pam" && AUTH_EXCL_DEF="PAM" + AC_CHECK_FUNCS(priv_set) ;; *-*-aix*) # To get all prototypes (so we pass -Wall) OSDEFS="${OSDEFS} -D_ALL_SOURCE -D_LINUX_SOURCE_COMPAT" - SUDO_LDFLAGS="${SUDO_LDFLAGS} -Wl,-bI:\$(srcdir)/aixcrypt.exp" + SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -Wl,-bI:\$(srcdir)/aixcrypt.exp" if test X"$with_blibpath" != X"no"; then AC_MSG_CHECKING([if linker accepts -Wl,-blibpath]) O_LDFLAGS="$LDFLAGS" @@ -1488,7 +1499,7 @@ case "$host" in # AIX-specific functions AC_CHECK_FUNCS(getuserattr setauthdb) - COMMON_OBJS="$COMMON_OBJS aix.o" + COMMON_OBJS="$COMMON_OBJS aix.lo" ;; *-*-hiuxmpp*) : ${mansectsu='1m'} @@ -1503,11 +1514,6 @@ case "$host" in : ${mansectform='4'} if test -z "$GCC"; then - # HP-UX bundled compiler can't generate shared objects - if test "x$ac_cv_prog_cc_c89" = "xno"; then - with_noexec=no - fi - # Use the +DAportable flag on hppa if it is supported case "$host_cpu" in hppa*) @@ -1532,13 +1538,6 @@ case "$host" in case "$host" in *-*-hpux[1-8].*) AC_DEFINE(BROKEN_SYSLOG) - - # Not sure if setuid binaries are safe in < 9.x - if test -n "$GCC"; then - SUDO_LDFLAGS="${SUDO_LDFLAGS} -static" - else - SUDO_LDFLAGS="${SUDO_LDFLAGS} -Wl,-a,archive" - fi ;; *-*-hpux9.*) AC_DEFINE(BROKEN_SYSLOG) @@ -1548,7 +1547,7 @@ case "$host" in # DCE support (requires ANSI C compiler) if test "$with_DCE" = "yes"; then # order of libs in 9.X is important. -lc_r must be last - SUDO_LIBS="${SUDO_LIBS} -ldce -lM -lc_r" + SUDOERS_LIBS="${SUDOERS_LIBS} -ldce -lM -lc_r" LIBS="${LIBS} -ldce -lM -lc_r" CPPFLAGS="${CPPFLAGS} -D_REENTRANT -I/usr/include/reentrant" fi @@ -1568,7 +1567,7 @@ case "$host" in ;; *-dec-osf*) # ignore envariables wrt dynamic lib path - SUDO_LDFLAGS="${SUDO_LDFLAGS} -Wl,-no_library_replacement" + SUDOERS_LDFLAGS="${SUDOERS_LDFLAGS} -Wl,-no_library_replacement" : ${CHECKSIA='true'} AC_MSG_CHECKING(whether to disable sia support on Digital UNIX) @@ -1673,8 +1672,7 @@ case "$host" in *-*-isc*) OSDEFS="${OSDEFS} -D_ISC" LIB_CRYPT=1 - SUDO_LIBS="${SUDO_LIBS} -lcrypt" - LIBS="${LIBS} -lcrypt" + SUDOERS_LIBS="${SUDOERS_LIBS} -lcrypt" shadow_funcs="getspnam" shadow_libs="-lsec" @@ -1702,14 +1700,13 @@ case "$host" in : ${with_rpath='yes'} ;; *-ncr-sysv4*|*-ncr-sysvr4*) - AC_CHECK_LIB(c89, strcasecmp, AC_DEFINE(HAVE_STRCASECMP) [LIBS="${LIBS} -lc89"; ac_cv_func_strcasecmp=yes]) + AC_CHECK_LIB(c89, strcasecmp, [LIBS="${LIBS} -lc89"]) : ${mansectsu='1m'} : ${mansectform='4'} : ${with_rpath='yes'} ;; *-ccur-sysv4*|*-ccur-sysvr4*) LIBS="${LIBS} -lgen" - SUDO_LIBS="${SUDO_LIBS} -lgen" : ${mansectsu='1m'} : ${mansectform='4'} : ${with_rpath='yes'} @@ -1739,7 +1736,7 @@ case "$host" in ;; esac if test "${with_skey-'no'}" = "yes"; then - SUDO_LIBS="${SUDO_LIBS} -lmd" + SUDOERS_LIBS="${SUDOERS_LIBS} -lmd" fi CHECKSHADOW="false" test -z "$with_pam" && AUTH_EXCL_DEF="PAM" @@ -1775,7 +1772,7 @@ case "$host" in ;; *-*-dragonfly*) if test "${with_skey-'no'}" = "yes"; then - SUDO_LIBS="${SUDO_LIBS} -lmd" + SUDOERS_LIBS="${SUDOERS_LIBS} -lmd" fi CHECKSHADOW="false" test -z "$with_pam" && AUTH_EXCL_DEF="PAM" @@ -1865,6 +1862,9 @@ dnl AC_PROG_GCC_TRADITIONAL AC_C_CONST AC_C_VOLATILE +if test X"$with_gnu_ld" != "yes" -a -n "$GCC"; then + LTLDFLAGS="$LTLDFLAGS -Wc,-static-libgcc" +fi dnl dnl Program checks dnl @@ -1875,9 +1875,7 @@ SUDO_PROG_BSHELL if test -z "$with_sendmail"; then SUDO_PROG_SENDMAIL fi -if test -z "$with_editor"; then - SUDO_PROG_VI -fi +SUDO_PROG_VI dnl dnl Check for authpriv support in syslog dnl @@ -1893,7 +1891,7 @@ dnl AC_HEADER_STDC AC_HEADER_DIRENT AC_HEADER_TIME -AC_CHECK_HEADERS(malloc.h paths.h utime.h netgroup.h sys/sockio.h sys/bsdtypes.h sys/select.h sys/stropts.h sys/sysmacros.h) +AC_CHECK_HEADERS(malloc.h paths.h utime.h netgroup.h utmpx.h sys/sockio.h sys/bsdtypes.h sys/select.h sys/stropts.h sys/sysmacros.h) dnl dnl Check for large file support. HP-UX 11.23 has a broken sys/type.h dnl when large files support is enabled so work around it. @@ -1916,17 +1914,17 @@ case "$host" in ;; esac AC_SYS_POSIX_TERMIOS -if test "$ac_cv_sys_posix_termios" = "yes"; then - AC_DEFINE(HAVE_TERMIOS_H) -else - AC_CHECK_HEADERS(termio.h) +if test "$ac_cv_sys_posix_termios" != "yes"; then + AC_MSG_ERROR([Must have POSIX termios to build sudo]) fi SUDO_MAILDIR if test ${with_logincap-'no'} != "no"; then AC_CHECK_HEADERS(login_cap.h, [LOGINCAP_USAGE='[[-c class|-]] '; LCMAN=1 case "$OS" in - freebsd|netbsd) SUDO_LIBS="${SUDO_LIBS} -lutil" - ;; + freebsd|netbsd) + SUDO_LIBS="${SUDO_LIBS} -lutil" + SUDOERS_LIBS="${SUDOERS_LIBS} -lutil" + ;; esac ]) fi @@ -1960,35 +1958,73 @@ SUDO_TYPE_INO_T SUDO_UID_T_LEN SUDO_SOCK_SA_LEN dnl -dnl only set RETSIGTYPE if it is not set already +dnl Check for utmp/utmpx struct members. +dnl We need to include OSDEFS for glibc which only has __e_termination +dnl visible when _GNU_SOURCE is *not* defined. dnl -case "$DEFS" in - *"RETSIGTYPE"*) ;; - *) AC_TYPE_SIGNAL;; -esac +_CFLAGS="$CFLAGS" +CFLAGS="$CFLAGS $OSDEFS" +if test $ac_cv_header_utmpx_h = "yes"; then + AC_CHECK_MEMBERS([struct utmpx.ut_id, struct utmpx.ut_pid, struct utmpx.ut_tv, struct utmpx.ut_type], [], [], [ + #include + #include + ]) + dnl + dnl Check for ut_exit.__e_termination first, then ut_exit.e_termination + dnl + AC_CHECK_MEMBERS([struct utmpx.ut_exit.__e_termination], [AC_DEFINE(HAVE_STRUCT_UTMPX_UT_EXIT)], [ + AC_CHECK_MEMBERS([struct utmpx.ut_exit.e_termination], [AC_DEFINE(HAVE_STRUCT_UTMPX_UT_EXIT)], [], [ + #include + #include + ]) + ], [ + #include + #include + ]) +else + AC_CHECK_MEMBERS([struct utmp.ut_id, struct utmp.ut_pid, struct utmp.ut_tv, struct utmp.ut_type, struct utmp.ut_user], [], [], [ + #include + #include + ]) + dnl + dnl Check for ut_exit.__e_termination first, then ut_exit.e_termination + dnl + AC_CHECK_MEMBERS([struct utmp.ut_exit.__e_termination], [AC_DEFINE(HAVE_STRUCT_UTMP_UT_EXIT)], [ + AC_CHECK_MEMBERS([struct utmp.ut_exit.e_termination], [AC_DEFINE(HAVE_STRUCT_UTMP_UT_EXIT)], [], [ + #include + #include + ]) + ], [ + #include + #include + ]) +fi +CFLAGS="$_CFLAGS" + dnl dnl Function checks dnl AC_FUNC_GETGROUPS -AC_CHECK_FUNCS(strchr strrchr memchr memcpy memset sysconf tzset \ - strftime setrlimit initgroups getgroups fstat gettimeofday \ - regcomp setlocale nl_langinfo getaddrinfo setenv \ - mbr_check_membership setrlimit64) +AC_CHECK_FUNCS(strrchr sysconf tzset strftime initgroups getgroups fstat \ + regcomp setlocale nl_langinfo getaddrinfo mbr_check_membership \ + setrlimit64 sysctl) AC_CHECK_FUNCS(getline, [], [ AC_LIBOBJ(getline) AC_CHECK_FUNCS(fgetln) ]) -AC_CHECK_FUNCS(setsid, [], [ - AC_LIBOBJ(setsid) - AC_FUNC_SETPGRP -]) - -AC_CHECK_FUNCS(sysctl getutxid getutid, [break]) +utmp_style=LEGACY +AC_CHECK_FUNCS(getutxid getutid, [utmp_style=POSIX; break]) +if test "$utmp_style" = "LEGACY"; then + AC_CHECK_FUNCS(getttyent ttyslot, [break]) +fi AC_CHECK_FUNCS(openpty, [AC_CHECK_HEADERS(util.h pty.h, [break])], [ AC_CHECK_LIB(util, openpty, [ AC_CHECK_HEADERS(util.h pty.h, [break]) - SUDO_LIBS="${SUDO_LIBS} -lutil" + case "$SUDO_LIBS" in + *-lutil*) ;; + *) SUDO_LIBS="${SUDO_LIBS} -lutil";; + esac AC_DEFINE(HAVE_OPENPTY) ], [ AC_CHECK_FUNCS(_getpty, [], [ @@ -2000,10 +2036,12 @@ AC_CHECK_FUNCS(openpty, [AC_CHECK_HEADERS(util.h pty.h, [break])], [ ]) ]) ]) -AC_CHECK_FUNCS(unsetenv, SUDO_FUNC_UNSETENV_VOID) -SUDO_FUNC_PUTENV_CONST +AC_CHECK_FUNCS(unsetenv, [SUDO_FUNC_UNSETENV_VOID], [AC_LIBOBJ(unsetenv)]) if test -z "$SKIP_SETRESUID"; then - AC_CHECK_FUNCS(setresuid, [SKIP_SETREUID=yes]) + AC_CHECK_FUNCS(setresuid, [ + SKIP_SETREUID=yes + AC_CHECK_FUNCS(getresuid) + ]) fi if test -z "$SKIP_SETREUID"; then AC_CHECK_FUNCS(setreuid, [SKIP_SETEUID=yes]) @@ -2022,24 +2060,24 @@ AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[int i = GLOB_BRACE | AC_MSG_RESULT(yes)], [AC_LIBOBJ(glob) AC_MSG_RESULT(no)])], [AC_LIBOBJ(glob)]) AC_CHECK_FUNCS(lockf flock, [break]) -AC_CHECK_FUNCS(waitpid wait3, [break]) AC_CHECK_FUNCS(innetgr _innetgr, [AC_CHECK_FUNCS(getdomainname) [break]]) AC_CHECK_FUNCS(utimes, [AC_CHECK_FUNCS(futimes futimesat, [break])], [AC_CHECK_FUNCS(futime) AC_LIBOBJ(utimes)]) AC_CHECK_FUNCS(killpg, [], [AC_LIBOBJ(killpg)]) SUDO_FUNC_FNMATCH([AC_DEFINE(HAVE_FNMATCH)], [AC_LIBOBJ(fnmatch)]) SUDO_FUNC_ISBLANK -AC_REPLACE_FUNCS(memrchr strerror strcasecmp sigaction strlcpy strlcat) +AC_REPLACE_FUNCS(memrchr strlcpy strlcat setenv) AC_CHECK_FUNCS(nanosleep, [], [ # On Solaris, nanosleep is in librt - AC_CHECK_LIB(rt, nanosleep, [LIBS="${LIBS} -lrt"], [AC_LIBOBJ(nanosleep)]) + AC_CHECK_LIB(rt, nanosleep, [REPLAY_LIBS="${REPLAY_LIBS} -lrt"], [AC_LIBOBJ(nanosleep)]) ]) AC_CHECK_FUNCS(closefrom, [], [AC_LIBOBJ(closefrom) AC_CHECK_DECL(F_CLOSEM, AC_DEFINE(HAVE_FCNTL_CLOSEM), [], [ #include #include ]) ]) -AC_CHECK_FUNCS(mkstemps, [], [SUDO_OBJS="${SUDO_OBJS} mkstemps.o" +AC_CHECK_FUNCS(mkstemps mkdtemp, [], [ AC_CHECK_FUNCS(random lrand48, [break]) + AC_LIBOBJ(mktemp) ]) AC_CHECK_FUNCS(snprintf vsnprintf asprintf vasprintf, , [NEED_SNPRINTF=1]) if test X"$ac_cv_type_struct_timespec" != X"no"; then @@ -2092,6 +2130,41 @@ AC_CHECK_FUNCS(getprogname, , [ AC_MSG_RESULT($sudo_cv___progname) ]) +dnl +dnl Deferred zlib option processing. +dnl By default we use the system zlib if it is present. +dnl +case ${enable_zlib-"yes"} in + yes) + AC_CHECK_LIB(z, gzdopen, [ + AC_CHECK_HEADERS(zlib.h, [ZLIB="-lz"], [enable_zlib=builtin]) + ]) + ;; + no) + ;; + system) + AC_DEFINE(HAVE_ZLIB_H) + ZLIB="-lz" + ;; + builtin) + # handled below + ;; + *) + AC_DEFINE(HAVE_ZLIB_H) + CPPFLAGS="${CPPFLAGS} -I${enable_zlib}/include" + SUDO_APPEND_LIBPATH(ZLIB, [$enable_zlib/lib]) + ZLIB="${ZLIB} -lz" + ;; +esac +if test X"$enable_zlib" = X"builtin"; then + AC_DEFINE(HAVE_ZLIB_H) + CPPFLAGS="${CPPFLAGS}"' -I$(top_srcdir)/zlib' + ZLIB="${ZLIB}"' $(top_builddir)/zlib/libz.la' + ZLIB_SRC=zlib + AC_CONFIG_HEADER([zlib/zconf.h]) + AC_CONFIG_FILES([zlib/Makefile]) +fi + dnl dnl Check for strsignal() or sys_siglist dnl @@ -2146,16 +2219,8 @@ dnl PAM support. Systems that use PAM by default set with_pam=default dnl and we do the actual tests here. dnl if test ${with_pam-"no"} != "no"; then - dnl - dnl Some platforms need libdl for dlopen - dnl - case "$LIBS" in - *-ldl*) SUDO_LIBS="${SUDO_LIBS} -lpam" - ;; - *) AC_CHECK_LIB([dl], [main], [SUDO_LIBS="${SUDO_LIBS} -lpam -ldl"], [SUDO_LIBS="${SUDO_LIBS} -lpam"]) - ac_cv_lib_dl=ac_cv_lib_dl_main - ;; - esac + # Note: we already link the main sudo program with -ldl as needed + SUDOERS_LIBS="${SUDOERS_LIBS} -lpam" dnl dnl Some PAM implementations (MacOS X for example) put the PAM headers @@ -2164,7 +2229,7 @@ if test ${with_pam-"no"} != "no"; then AC_CHECK_HEADERS([security/pam_appl.h] [pam/pam_appl.h], [with_pam=yes; break]) if test "$with_pam" = "yes"; then AC_DEFINE(HAVE_PAM) - AUTH_OBJS="$AUTH_OBJS pam.o"; + AUTH_OBJS="$AUTH_OBJS pam.lo"; AUTH_EXCL=PAM AC_ARG_WITH(pam-login, [AS_HELP_STRING([--with-pam-login], [enable specific PAM session for sudo -i])], @@ -2185,7 +2250,7 @@ if test ${with_pam-"no"} != "no"; then yes) AC_MSG_RESULT(yes) ;; no) AC_MSG_RESULT(no) - AC_DEFINE([NO_PAM_SESSION], [], [PAM session support disabled]) + AC_DEFINE(NO_PAM_SESSION) ;; *) AC_MSG_RESULT(no) AC_MSG_WARN([Ignoring unknown argument to --enable-pam-session: $enableval]) @@ -2215,8 +2280,8 @@ if test ${with_aixauth-'no'} != "no"; then if test X"$with_aixauth" != X"maybe" -o X"$AUTH_EXCL" = X""; then AC_MSG_NOTICE([using AIX general authentication]) AC_DEFINE(HAVE_AIXAUTH) - AUTH_OBJS="$AUTH_OBJS aix_auth.o"; - SUDO_LIBS="${SUDO_LIBS} -ls" + AUTH_OBJS="$AUTH_OBJS aix_auth.lo"; + SUDOERS_LIBS="${SUDOERS_LIBS} -ls" AUTH_EXCL=AIX_AUTH fi fi @@ -2227,7 +2292,7 @@ dnl If set to "maybe" only enable if no other exclusive method in use. dnl if test ${with_bsdauth-'no'} != "no"; then AC_CHECK_HEADER(bsd_auth.h, AC_DEFINE(HAVE_BSD_AUTH_H) - [AUTH_OBJS="$AUTH_OBJS bsdauth.o"] + [AUTH_OBJS="$AUTH_OBJS bsdauth.lo"] [BSDAUTH_USAGE='[[-a auth_type]] '] [AUTH_EXCL=BSD_AUTH; BAMAN=1], [AC_MSG_ERROR([BSD authentication was specified but bsd_auth.h could not be found])]) @@ -2240,7 +2305,7 @@ if test ${CHECKSIA-'false'} = "true"; then AC_CHECK_FUNCS(sia_ses_init, [found=true], [found=false]) if test "$found" = "true"; then AUTH_EXCL=SIA - AUTH_OBJS="$AUTH_OBJS sia.o" + AUTH_OBJS="$AUTH_OBJS sia.lo" fi fi @@ -2249,12 +2314,12 @@ dnl extra FWTK libs + includes dnl if test ${with_fwtk-'no'} != "no"; then if test "$with_fwtk" != "yes"; then - SUDO_APPEND_LIBPATH(SUDO_LDFLAGS, [${with_fwtk}]) + SUDO_APPEND_LIBPATH(SUDOERS_LDFLAGS, [${with_fwtk}]) CPPFLAGS="${CPPFLAGS} -I${with_fwtk}" with_fwtk=yes fi - SUDO_LIBS="${SUDO_LIBS} -lauth -lfwall" - AUTH_OBJS="$AUTH_OBJS fwtk.o" + SUDOERS_LIBS="${SUDOERS_LIBS} -lauth -lfwall" + AUTH_OBJS="$AUTH_OBJS fwtk.lo" fi dnl @@ -2276,14 +2341,14 @@ if test ${with_SecurID-'no'} != "no"; then # AC_CHECK_LIB(aceclnt, SD_Init, [ - AUTH_OBJS="$AUTH_OBJS securid5.o"; - SUDO_LIBS="${SUDO_LIBS} -laceclnt -lpthread" + AUTH_OBJS="$AUTH_OBJS securid5.lo"; + SUDOERS_LIBS="${SUDOERS_LIBS} -laceclnt -lpthread" ] [ - SUDO_APPEND_LIBPATH(SUDO_LDFLAGS, [${with_SecurID}]) + SUDO_APPEND_LIBPATH(SUDOERS_LDFLAGS, [${with_SecurID}]) ], [ - AUTH_OBJS="$AUTH_OBJS securid.o"; - SUDO_LIBS="${SUDO_LIBS} ${with_SecurID}/sdiclient.a" + AUTH_OBJS="$AUTH_OBJS securid.lo"; + SUDOERS_LIBS="${SUDOERS_LIBS} ${with_SecurID}/sdiclient.a" ], [ -lpthread @@ -2328,7 +2393,7 @@ if test ${with_kerb4-'no'} != "no"; then test X"$found" = X"no" && CPPFLAGS="$O_CPPFLAGS" else SUDO_APPEND_LIBPATH(LDFLAGS, [${with_kerb4}/lib]) - SUDO_APPEND_LIBPATH(SUDO_LDFLAGS, [${with_kerb4}/lib]) + SUDO_APPEND_LIBPATH(SUDOERS_LDFLAGS, [${with_kerb4}/lib]) CPPFLAGS="$CPPFLAGS -I${with_kerb4}/include" AC_CHECK_HEADER([krb.h], [found=yes], [found=no]) fi @@ -2360,12 +2425,12 @@ if test ${with_kerb4-'no'} != "no"; then AC_CHECK_LIB(krb, main, [K4LIBS="-lkrb $K4LIBS"], [ AC_CHECK_LIB(krb4, main, [K4LIBS="-lkrb4 $K4LIBS"], [K4LIBS="-lkrb $K4LIBS"] - [AC_MSG_WARN([Unable to locate Kerberos IV libraries, you will have to edit the Makefile and add -L/path/to/krb/libs to SUDO_LDFLAGS and possibly add Kerberos libs to SUDO_LIBS])] + [AC_MSG_WARN([Unable to locate Kerberos IV libraries, you will have to edit the Makefile and add -L/path/to/krb/libs to SUDOERS_LDFLAGS and possibly add Kerberos libs to SUDOERS_LIBS])] , [$K4LIBS]) ], [$K4LIBS]) LDFLAGS="$O_LDFLAGS" - SUDO_LIBS="${SUDO_LIBS} $K4LIBS" - AUTH_OBJS="$AUTH_OBJS kerb4.o" + SUDOERS_LIBS="${SUDOERS_LIBS} $K4LIBS" + AUTH_OBJS="$AUTH_OBJS kerb4.lo" fi dnl @@ -2376,9 +2441,9 @@ if test ${with_kerb5-'no'} != "no"; then AC_CHECK_PROG(KRB5CONFIG, krb5-config, yes, "") if test -n "$KRB5CONFIG"; then AC_DEFINE(HAVE_KERB5) - AUTH_OBJS="$AUTH_OBJS kerb5.o" + AUTH_OBJS="$AUTH_OBJS kerb5.lo" CPPFLAGS="$CPPFLAGS `krb5-config --cflags`" - SUDO_LIBS="$SUDO_LIBS `krb5-config --libs`" + SUDOERS_LIBS="$SUDOERS_LIBS `krb5-config --libs`" dnl dnl Try to determine whether we have Heimdal or MIT Kerberos dnl @@ -2390,57 +2455,56 @@ if test ${with_kerb5-'no'} != "no"; then AC_MSG_RESULT(no) ] ) - fi -fi -if test ${with_kerb5-'no'} != "no" -a -z "$KRB5CONFIG"; then - AC_DEFINE(HAVE_KERB5) - dnl - dnl Use the specified directory, if any, else search for correct inc dir - dnl - if test "$with_kerb5" = "yes"; then - found=no - O_CPPFLAGS="$CPPFLAGS" - for dir in "" "kerberosV/" "krb5/" "kerberos5/" "kerberosv5/"; do - CPPFLAGS="$O_CPPFLAGS -I/usr/include/${dir}" - AC_PREPROC_IFELSE([#include ], [found=yes; break]) - done - if test X"$found" = X"no"; then - CPPFLAGS="$O_CPPFLAGS" - AC_MSG_WARN([Unable to locate Kerberos V include files, you will have to edit the Makefile and add -I/path/to/krb/includes to CPPFLAGS]) - fi else - dnl XXX - try to include krb5.h here too - SUDO_APPEND_LIBPATH(SUDO_LDFLAGS, [${with_kerb5}/lib]) - CPPFLAGS="$CPPFLAGS -I${with_kerb5}/include" - fi + AC_DEFINE(HAVE_KERB5) + dnl + dnl Use the specified directory, if any, else search for correct inc dir + dnl + if test "$with_kerb5" = "yes"; then + found=no + O_CPPFLAGS="$CPPFLAGS" + for dir in "" "kerberosV/" "krb5/" "kerberos5/" "kerberosv5/"; do + CPPFLAGS="$O_CPPFLAGS -I/usr/include/${dir}" + AC_PREPROC_IFELSE([#include ], [found=yes; break]) + done + if test X"$found" = X"no"; then + CPPFLAGS="$O_CPPFLAGS" + AC_MSG_WARN([Unable to locate Kerberos V include files, you will have to edit the Makefile and add -I/path/to/krb/includes to CPPFLAGS]) + fi + else + dnl XXX - try to include krb5.h here too + SUDO_APPEND_LIBPATH(SUDOERS_LDFLAGS, [${with_kerb5}/lib]) + CPPFLAGS="$CPPFLAGS -I${with_kerb5}/include" + fi - dnl - dnl Try to determine whether we have Heimdal or MIT Kerberos - dnl - AC_MSG_CHECKING(whether we are using Heimdal) - AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[const char *tmp = heimdal_version;]])], [ - AC_MSG_RESULT(yes) - AC_DEFINE(HAVE_HEIMDAL) - # XXX - need to check whether -lcrypo is needed! - SUDO_LIBS="${SUDO_LIBS} -lkrb5 -lcrypto -ldes -lcom_err -lasn1" - AC_CHECK_LIB(roken, main, [SUDO_LIBS="${SUDO_LIBS} -lroken"]) - ], [ - AC_MSG_RESULT(no) - SUDO_LIBS="${SUDO_LIBS} -lkrb5 -lk5crypto -lcom_err" - AC_CHECK_LIB(krb5support, main, [SUDO_LIBS="${SUDO_LIBS} -lkrb5support"]) - ]) - AUTH_OBJS="$AUTH_OBJS kerb5.o" + dnl + dnl Try to determine whether we have Heimdal or MIT Kerberos + dnl + AC_MSG_CHECKING(whether we are using Heimdal) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include ]], [[const char *tmp = heimdal_version;]])], [ + AC_MSG_RESULT(yes) + AC_DEFINE(HAVE_HEIMDAL) + # XXX - need to check whether -lcrypo is needed! + SUDOERS_LIBS="${SUDOERS_LIBS} -lkrb5 -lcrypto -ldes -lcom_err -lasn1" + AC_CHECK_LIB(roken, main, [SUDOERS_LIBS="${SUDOERS_LIBS} -lroken"]) + ], [ + AC_MSG_RESULT(no) + SUDOERS_LIBS="${SUDOERS_LIBS} -lkrb5 -lk5crypto -lcom_err" + AC_CHECK_LIB(krb5support, main, [SUDOERS_LIBS="${SUDOERS_LIBS} -lkrb5support"]) + ]) + AUTH_OBJS="$AUTH_OBJS kerb5.lo" + fi _LIBS="$LIBS" - LIBS="${LIBS} ${SUDO_LIBS}" + LIBS="${LIBS} ${SUDOERS_LIBS}" AC_CHECK_FUNCS(krb5_verify_user krb5_init_secure_context) AC_CHECK_FUNCS(krb5_get_init_creds_opt_alloc, [ AC_CACHE_CHECK([whether krb5_get_init_creds_opt_free takes a context], sudo_cv_krb5_get_init_creds_opt_free_two_args, [ - AC_COMPILE_IFELSE( - [AC_LANG_PROGRAM( - [[#include ]], - [[krb5_get_init_creds_opt_free(NULL, NULL);]] - )], + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include ]], + [[krb5_get_init_creds_opt_free(NULL, NULL);]] + )], [sudo_cv_krb5_get_init_creds_opt_free_two_args=yes], [sudo_cv_krb5_get_init_creds_opt_free_two_args=no] ) @@ -2462,12 +2526,12 @@ if test ${with_AFS-'no'} = "yes"; then AFSLIBDIRS="/usr/lib/afs /usr/afsws/lib /usr/afsws/lib/afs" for i in $AFSLIBDIRS; do if test -d ${i}; then - SUDO_APPEND_LIBPATH(SUDO_LDFLAGS, [$i]) + SUDO_APPEND_LIBPATH(SUDOERS_LDFLAGS, [$i]) FOUND_AFSLIBDIR=true fi done if test -z "$FOUND_AFSLIBDIR"; then - AC_MSG_WARN([Unable to locate AFS libraries, you will have to edit the Makefile and add -L/path/to/afs/libs to SUDO_LDFLAGS or rerun configure with the --with-libpath options.]) + AC_MSG_WARN([Unable to locate AFS libraries, you will have to edit the Makefile and add -L/path/to/afs/libs to SUDOERS_LDFLAGS or rerun configure with the --with-libpath options.]) fi # Order is important here. Note that we build AFS_LIBS from right to left @@ -2497,7 +2561,7 @@ if test ${with_AFS-'no'} = "yes"; then AC_MSG_WARN([Unable to locate AFS include dir, you may have to edit the Makefile and add -I/path/to/afs/includes to CPPFLAGS or rerun configure with the --with-incpath options.]) fi - AUTH_OBJS="$AUTH_OBJS afs.o" + AUTH_OBJS="$AUTH_OBJS afs.lo" fi dnl @@ -2506,8 +2570,8 @@ dnl Order of libs in HP-UX 10.x is important, -ldce must be last. dnl if test ${with_DCE-'no'} = "yes"; then DCE_OBJS="${DCE_OBJS} dce_pwent.o" - SUDO_LIBS="${SUDO_LIBS} -ldce" - AUTH_OBJS="$AUTH_OBJS dce.o" + SUDOERS_LIBS="${SUDOERS_LIBS} -ldce" + AUTH_OBJS="$AUTH_OBJS dce.lo" fi dnl @@ -2518,30 +2582,46 @@ if test "${with_skey-'no'}" = "yes"; then if test "$with_skey" != "yes"; then CPPFLAGS="${CPPFLAGS} -I${with_skey}/include" SUDO_APPEND_LIBPATH(LDFLAGS, [${with_skey}/lib]) - SUDO_APPEND_LIBPATH(SUDO_LDFLAGS, [${with_skey}/lib]) - AC_PREPROC_IFELSE([#include ], [found=yes], [found=no]) + SUDO_APPEND_LIBPATH(SUDOERS_LDFLAGS, [${with_skey}/lib]) + AC_CHECK_HEADER([skey.h], [found=yes], [found=no], [#include ]) else found=no O_CPPFLAGS="$CPPFLAGS" for dir in "" "/usr/local" "/usr/contrib"; do test -n "$dir" && CPPFLAGS="$O_CPPFLAGS -I${dir}/include" - AC_PREPROC_IFELSE([#include ], [found=yes; break]) + AC_CHECK_HEADER([skey.h], [found=yes; break], [], + [#include ]) done if test "$found" = "no" -o -z "$dir"; then CPPFLAGS="$O_CPPFLAGS" else SUDO_APPEND_LIBPATH(LDFLAGS, [${dir}/lib]) - SUDO_APPEND_LIBPATH(SUDO_LDFLAGS, [${dir}/lib]) + SUDO_APPEND_LIBPATH(SUDOERS_LDFLAGS, [${dir}/lib]) + fi + if test "$found" = "no"; then + AC_MSG_WARN([Unable to locate skey.h, you will have to edit the Makefile and add -I/path/to/skey/includes to CPPFLAGS]) fi fi - if test "$found" = "no"; then - AC_MSG_WARN([Unable to locate skey.h, you will have to edit the Makefile and add -I/path/to/skey/includes to CPPFLAGS]) - fi - AC_CHECK_LIB(skey, main, [found=yes], [AC_MSG_WARN([Unable to locate libskey.a, you will have to edit the Makefile and add -L/path/to/skey/lib to SUDO_LDFLAGS])]) + AC_CHECK_LIB(skey, main, [found=yes], [AC_MSG_WARN([Unable to locate libskey.a, you will have to edit the Makefile and add -L/path/to/skey/lib to SUDOERS_LDFLAGS])]) AC_CHECK_LIB(skey, skeyaccess, AC_DEFINE(HAVE_SKEYACCESS)) + + AC_MSG_CHECKING([for RFC1938-compliant skeychallenge]) + AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + #include ]], + [[skeychallenge(NULL, NULL, NULL, 0);]] + )], [ + AC_DEFINE(HAVE_RFC1938_SKEYCHALLENGE) + AC_MSG_RESULT([yes]) + ], [ + AC_MSG_RESULT([no]) + ] + ) + LDFLAGS="$O_LDFLAGS" - SUDO_LIBS="${SUDO_LIBS} -lskey" - AUTH_OBJS="$AUTH_OBJS rfc1938.o" + SUDOERS_LIBS="${SUDOERS_LIBS} -lskey" + AUTH_OBJS="$AUTH_OBJS rfc1938.lo" fi dnl @@ -2552,7 +2632,7 @@ if test "${with_opie-'no'}" = "yes"; then if test "$with_opie" != "yes"; then CPPFLAGS="${CPPFLAGS} -I${with_opie}/include" SUDO_APPEND_LIBPATH(LDFLAGS, [${with_opie}/lib]) - SUDO_APPEND_LIBPATH(SUDO_LDFLAGS, [${with_opie}/lib]) + SUDO_APPEND_LIBPATH(SUDOERS_LDFLAGS, [${with_opie}/lib]) AC_PREPROC_IFELSE([#include ], [found=yes], [found=no]) else found=no @@ -2565,16 +2645,16 @@ if test "${with_opie-'no'}" = "yes"; then CPPFLAGS="$O_CPPFLAGS" else SUDO_APPEND_LIBPATH(LDFLAGS, [${dir}/lib]) - SUDO_APPEND_LIBPATH(SUDO_LDFLAGS, [${dir}/lib]) + SUDO_APPEND_LIBPATH(SUDOERS_LDFLAGS, [${dir}/lib]) + fi + if test "$found" = "no"; then + AC_MSG_WARN([Unable to locate opie.h, you will have to edit the Makefile and add -I/path/to/opie/includes to CPPFLAGS]) fi fi - if test "$found" = "no"; then - AC_MSG_WARN([Unable to locate opie.h, you will have to edit the Makefile and add -I/path/to/opie/includes to CPPFLAGS]) - fi - AC_CHECK_LIB(opie, main, [found=yes], [AC_MSG_WARN([Unable to locate libopie.a, you will have to edit the Makefile and add -L/path/to/opie/lib to SUDO_LDFLAGS])]) + AC_CHECK_LIB(opie, main, [found=yes], [AC_MSG_WARN([Unable to locate libopie.a, you will have to edit the Makefile and add -L/path/to/opie/lib to SUDOERS_LDFLAGS])]) LDFLAGS="$O_LDFLAGS" - SUDO_LIBS="${SUDO_LIBS} -lopie" - AUTH_OBJS="$AUTH_OBJS rfc1938.o" + SUDOERS_LIBS="${SUDOERS_LIBS} -lopie" + AUTH_OBJS="$AUTH_OBJS rfc1938.lo" fi dnl @@ -2587,7 +2667,9 @@ if test ${with_passwd-'no'} != "no"; then dnl if crypt(3) not in libc, look elsewhere dnl if test -z "$LIB_CRYPT"; then - AC_SEARCH_LIBS([crypt], [crypt crypt_d ufc], [test -n "$ac_lib" && SUDO_LIBS="${SUDO_LIBS} $ac_res"]) + _LIBS="$LIBS" + AC_SEARCH_LIBS([crypt], [crypt crypt_d ufc], [test -n "$ac_lib" && SUDOERS_LIBS="${SUDOERS_LIBS} $ac_res"]) + LIBS="$_LIBS" fi if test "$CHECKSHADOW" = "true" -a -n "$shadow_funcs"; then @@ -2596,12 +2678,12 @@ if test ${with_passwd-'no'} != "no"; then found=no AC_CHECK_FUNCS($shadow_funcs, [found=yes]) if test "$found" = "yes"; then - SUDO_LIBS="$SUDO_LIBS $shadow_libs" + SUDOERS_LIBS="$SUDOERS_LIBS $shadow_libs" elif test -n "$shadow_libs_optional"; then LIBS="$LIBS $shadow_libs_optional" AC_CHECK_FUNCS($shadow_funcs, [found=yes]) if test "$found" = "yes"; then - SUDO_LIBS="$SUDO_LIBS $shadow_libs $shadow_libs_optional" + SUDOERS_LIBS="$SUDOERS_LIBS $shadow_libs $shadow_libs_optional" fi fi if test "$found" = "yes"; then @@ -2615,14 +2697,14 @@ if test ${with_passwd-'no'} != "no"; then CHECKSHADOW=false fi if test "$CHECKSHADOW" = "true"; then - AC_SEARCH_LIBS([getspnam], [gen], [AC_DEFINE(HAVE_GETSPNAM)] [CHECKSHADOW=false; test -n "$ac_lib" && SUDO_LIBS="${SUDO_LIBS} $ac_res"]) + AC_SEARCH_LIBS([getspnam], [gen], [AC_DEFINE(HAVE_GETSPNAM)] [CHECKSHADOW=false; test -n "$ac_lib" && SUDOERS_LIBS="${SUDOERS_LIBS} $ac_res"]) fi if test "$CHECKSHADOW" = "true"; then - AC_SEARCH_LIBS([getprpwnam], [sec security prot], [AC_DEFINE(HAVE_GETPRPWNAM)] [CHECKSHADOW=false; SECUREWARE=1; test -n "$ac_lib" && SUDO_LIBS="${SUDO_LIBS} $ac_res"]) + AC_SEARCH_LIBS([getprpwnam], [sec security prot], [AC_DEFINE(HAVE_GETPRPWNAM)] [CHECKSHADOW=false; SECUREWARE=1; test -n "$ac_lib" && SUDOERS_LIBS="${SUDOERS_LIBS} $ac_res"]) fi if test -n "$SECUREWARE"; then AC_CHECK_FUNCS(bigcrypt set_auth_parameters initprivs) - AUTH_OBJS="$AUTH_OBJS secureware.o" + AUTH_OBJS="$AUTH_OBJS secureware.lo" fi fi @@ -2632,12 +2714,12 @@ dnl if test ${with_ldap-'no'} != "no"; then _LDFLAGS="$LDFLAGS" if test "$with_ldap" != "yes"; then - SUDO_APPEND_LIBPATH(SUDO_LDFLAGS, [${with_ldap}/lib]) + SUDO_APPEND_LIBPATH(SUDOERS_LDFLAGS, [${with_ldap}/lib]) SUDO_APPEND_LIBPATH(LDFLAGS, [${with_ldap}/lib]) CPPFLAGS="${CPPFLAGS} -I${with_ldap}/include" with_ldap=yes fi - SUDO_OBJS="${SUDO_OBJS} ldap.o" + SUDOERS_OBJS="${SUDOERS_OBJS} ldap.lo" LDAP="" AC_MSG_CHECKING([for LDAP libraries]) @@ -2704,99 +2786,84 @@ if test ${with_ldap-'no'} != "no"; then fi fi - SUDO_LIBS="${SUDO_LIBS} ${LDAP_LIBS}" + SUDOERS_LIBS="${SUDOERS_LIBS} ${LDAP_LIBS}" LIBS="$_LIBS" LDFLAGS="$_LDFLAGS" fi -dnl -dnl Add LIBVAS_RPATH to LDFLAGS -dnl GNU ld accepts -R/path/ as an alias for -rpath /path/ -dnl -if test X"$LIBVAS_RPATH" != X""; then - if test -n "$blibpath"; then - blibpath_add="${blibpath_add}:$LIBVAS_RPATH" - else - case "$host" in - *-*-hpux*) LDFLAGS="$LDFLAGS -Wl,+b,$LIBVAS_RPATH" - ;; - *) LDFLAGS="$LDFLAGS -Wl,-R$LIBVAS_RPATH" - ;; - esac - fi +# +# How to do dynamic object loading. +# We support dlopen() and sh_load(), else fall back to static loading. +# +case "$lt_cv_dlopen" in + dlopen) + AC_DEFINE(HAVE_DLOPEN) + SUDOERS_OBJS="$SUDOERS_OBJS plugin_error.lo" + LT_STATIC="--tag=disable-static" + ;; + shl_load) + AC_DEFINE(HAVE_SHL_LOAD) + SUDOERS_OBJS="$SUDOERS_OBJS plugin_error.lo" + LT_STATIC="--tag=disable-static" + AC_LIBOBJ(dlopen) + ;; + *) + # Preload sudoers module symbols + SUDO_OBJS="${SUDO_OBJS} preload.o" + SUDO_LIBS="${SUDO_LIBS} \$(top_builddir)/plugins/sudoers/sudoers.la" + LT_STATIC="" + AC_LIBOBJ(dlopen) + ;; +esac + +# +# Add library needed for dynamic loading, if any. +# +LIBDL="$lt_cv_dlopen_libs" +if test X"$LIBDL" != X""; then + SUDO_LIBS="${SUDO_LIBS} $LIBDL" + SUDOERS_LIBS="${SUDOERS_LIBS} $LIBDL" fi +# On HP-UX, you cannot dlopen() a shared object that uses pthreads +# unless the main program is linked against -lpthread. Since we +# have no knowledge what libraries a plugin may depend on, we always +# link against -lpthread on HP-UX if it is available. +# This check should go after all other libraries tests. +case "$host" in + *-*-hpux*) + AC_CHECK_LIB(pthread, main, [SUDO_LIBS="${SUDO_LIBS} -lpthread"]) + ;; +esac + dnl -dnl Add $blibpath to SUDO_LDFLAGS if specified by the user or if we -dnl added -L dirpaths to SUDO_LDFLAGS. +dnl Add $blibpath to SUDOERS_LDFLAGS if specified by the user or if we +dnl added -L dirpaths to SUDOERS_LDFLAGS. dnl if test -n "$blibpath"; then if test -n "$blibpath_add"; then - SUDO_LDFLAGS="$SUDO_LDFLAGS -Wl,-blibpath:${blibpath}${blibpath_add}" + SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS -Wl,-blibpath:${blibpath}${blibpath_add}" elif test -n "$with_blibpath" -a "$with_blibpath" != "yes"; then - SUDO_LDFLAGS="$SUDO_LDFLAGS -Wl,-blibpath:${blibpath}" + SUDOERS_LDFLAGS="$SUDOERS_LDFLAGS -Wl,-blibpath:${blibpath}" fi fi dnl dnl Check for log file, timestamp and iolog locations dnl +if test "$utmp_style" = "LEGACY"; then + SUDO_PATH_UTMP +fi SUDO_LOGFILE SUDO_TIMEDIR SUDO_IO_LOGDIR -dnl -dnl If I/O logging is enabled, build sudoreplay and exec_pty get_pty.o iolog.o -dnl -if test "${with_iologdir-yes}" != "no"; then - # Require POSIX job control for I/O log support - AC_CHECK_FUNCS(tcsetpgrp, [ - SUDO_OBJS="${SUDO_OBJS} exec_pty.o get_pty.o iolog.o" - PROGS="$PROGS sudoreplay" - REPLAY="" - - AC_ARG_ENABLE(zlib, - [AS_HELP_STRING([--enable-zlib[[=PATH]]], [Whether to enable or disable zlib])], []) - case ${enable_zlib-"yes"} in - yes) - AC_CHECK_LIB(z, gzdopen, [ - AC_CHECK_HEADERS(zlib.h, [ZLIB="-lz"], [enable_zlib=builtin]) - ]) - ;; - no) - ;; - system) - AC_DEFINE(HAVE_ZLIB_H) - ZLIB="-lz" - ;; - builtin) - # handled below - ;; - *) - AC_DEFINE(HAVE_ZLIB_H) - CPPFLAGS="${CPPFLAGS} -I${enable_zlib}/include" - SUDO_APPEND_LIBPATH(ZLIB, [$enable_zlib/lib]) - ZLIB="${ZLIB} -lz" - ;; - esac - if test X"$enable_zlib" = X"builtin"; then - AC_DEFINE(HAVE_ZLIB_H) - CPPFLAGS="${CPPFLAGS}"' -I$(srcdir)/zlib' - ZLIB="${ZLIB} libz.a" - ZLIB_DEP=libz.a - fi - ], [ - AC_MSG_WARN([Disabling I/O log support due to lack of tcsetpgrp function]) - with_iologdir=no - ]) -fi - dnl dnl Use passwd auth module? dnl case "$with_passwd" in yes|maybe) - AUTH_OBJS="$AUTH_OBJS getspwuid.o passwd.o" + AUTH_OBJS="$AUTH_OBJS getspwuid.lo passwd.lo" ;; *) AC_DEFINE(WITHOUT_PASSWD) @@ -2806,18 +2873,18 @@ yes|maybe) ;; esac AUTH_OBJS=${AUTH_OBJS# } -_AUTH=`echo "$AUTH_OBJS" | sed -e 's/\.o//g' -e 's/getspwuid *//'` +_AUTH=`echo "$AUTH_OBJS" | sed -e 's/\.lo//g' -e 's/getspwuid *//'` AC_MSG_NOTICE([using the following authentication methods: $_AUTH]) dnl -dnl LIBS may contain duplicates from SUDO_LIBS or NET_LIBS so prune it. +dnl LIBS may contain duplicates from SUDO_LIBS, SUDOERS_LIBS, or NET_LIBS dnl if test -n "$LIBS"; then L="$LIBS" LIBS= for l in ${L}; do dupe=0 - for sl in ${SUDO_LIBS} ${NET_LIBS}; do + for sl in ${SUDO_LIBS} ${SUDOERS_LIBS} ${NET_LIBS}; do test $l = $sl && dupe=1 done test $dupe = 0 && LIBS="${LIBS} $l" @@ -2853,6 +2920,9 @@ if test X"$with_noexec" != X"no" -o X"$with_selinux" != X"no"; then eval sesh_file="$libexecdir/sesh" SUDO_DEFINE_UNQUOTED(_PATH_SUDO_SESH, "$sesh_file", [The fully qualified pathname of sesh]) fi + eval PLUGINDIR="$with_plugindir" + SUDO_DEFINE_UNQUOTED(_PATH_SUDO_PLUGIN_DIR, "$PLUGINDIR/") + SUDO_DEFINE_UNQUOTED(SUDOERS_PLUGIN, "sudoers${SOEXT}") exec_prefix="$oexec_prefix" fi @@ -2875,7 +2945,8 @@ test "$sysconfdir" = '${prefix}/etc' -a X"$with_stow" != X"yes" && sysconfdir='/ dnl dnl Substitute into the Makefile and man pages dnl -AC_CONFIG_FILES([Makefile sudo.man visudo.man sudoers.man sudoers.ldap.man sudoreplay.man sudo_usage.h sudoers]) +dnl AC_CONFIG_FILES([doc/sudo.man doc/visudo.man doc/sudoers.man doc/sudoers.ldap.man doc/sudoreplay.man src/Makefile src/sudo_usage.h]) +AC_CONFIG_FILES([Makefile common/Makefile compat/Makefile doc/Makefile include/Makefile src/sudo_usage.h src/Makefile plugins/sample/Makefile plugins/sample_group/Makefile plugins/sudoers/Makefile plugins/sudoers/sudoers]) AC_OUTPUT dnl @@ -2895,11 +2966,12 @@ dnl AH_TEMPLATE(BROKEN_SYSLOG, [Define to 1 if the `syslog' function returns a non-zero int to denote failure.]) AH_TEMPLATE(CLASSIC_INSULTS, [Define to 1 if you want the insults from the "classic" version sudo.]) AH_TEMPLATE(CSOPS_INSULTS, [Define to 1 if you want insults culled from the twisted minds of CSOps.]) +AH_TEMPLATE(SUDOERS_PLUGIN, [The name of the sudoers plugin, including extension.]) AH_TEMPLATE(DONT_LEAK_PATH_INFO, [Define to 1 if you want sudo to display "command not allowed" instead of "command not found" when a command cannot be found.]) -AH_TEMPLATE(ENV_EDITOR, [Define to 1 if you want visudo to honor the EDITOR and VISUAL env variables.]) AH_TEMPLATE(ENV_DEBUG, [Define to 1 to enable environment function debugging.]) -AH_TEMPLATE(ENV_RESET, [Define to 1 to enable environment resetting by default.]) +AH_TEMPLATE(ENV_EDITOR, [Define to 1 if you want visudo to honor the EDITOR and VISUAL env variables.]) AH_TEMPLATE(FQDN, [Define to 1 if you want to require fully qualified hosts in sudoers.]) +AH_TEMPLATE(ENV_RESET, [Define to 1 to enable environment resetting by default.]) AH_TEMPLATE(GOONS_INSULTS, [Define to 1 if you want insults from the "Goon Show".]) AH_TEMPLATE(HAL_INSULTS, [Define to 1 if you want 2001-like insults.]) AH_TEMPLATE(HAVE_AFS, [Define to 1 if you use AFS.]) @@ -2911,6 +2983,7 @@ AH_TEMPLATE(HAVE_DD_FD, [Define to 1 if your `DIR' contains dd_fd.]) AH_TEMPLATE(HAVE_DIRFD, [Define to 1 if you have the `dirfd' function or macro.]) AH_TEMPLATE(HAVE_DGETTEXT, [Define to 1 if you have the `dgettext' function.]) AH_TEMPLATE(HAVE_DISPCRYPT, [Define to 1 if you have the `dispcrypt' function.]) +AH_TEMPLATE(HAVE_DLOPEN, [Define to 1 if you have the `dlopen' function.]) AH_TEMPLATE(HAVE_EXTENDED_GLOB, [Define to 1 if your glob.h defines the GLOB_BRACE and GLOB_TILDE flags.]) AH_TEMPLATE(HAVE_FCNTL_CLOSEM, [Define to 1 if your system has the F_CLOSEM fcntl.]) AH_TEMPLATE(HAVE_FNMATCH, [Define to 1 if you have the `fnmatch' function.]) @@ -2941,13 +3014,14 @@ AH_TEMPLATE(HAVE_PROJECT_H, [Define to 1 if you have the header file AH_TEMPLATE(HAVE_SECURID, [Define to 1 if you use SecurID for authentication.]) AH_TEMPLATE(HAVE_SELINUX, [Define to 1 to enable SELinux RBAC support.]) AH_TEMPLATE(HAVE_SETKEYCREATECON, [Define to 1 if you have the `setkeycreatecon' function.]) +AH_TEMPLATE(HAVE_SHL_LOAD, [Define to 1 if you have the `shl_load' function.]) AH_TEMPLATE(HAVE_SIGACTION_T, [Define to 1 if has the sigaction_t typedef.]) AH_TEMPLATE(HAVE_SKEY, [Define to 1 if you use S/Key.]) AH_TEMPLATE(HAVE_SKEYACCESS, [Define to 1 if your S/Key library has skeyaccess().]) +AH_TEMPLATE(HAVE_RFC1938_SKEYCHALLENGE, [Define to 1 if the skeychallenge() function is RFC1938-compliant and takes 4 arguments]) AH_TEMPLATE(HAVE_ST__TIM, [Define to 1 if your struct stat uses an st__tim union]) AH_TEMPLATE(HAVE_ST_MTIM, [Define to 1 if your struct stat has an st_mtim member]) AH_TEMPLATE(HAVE_ST_MTIMESPEC, [Define to 1 if your struct stat has an st_mtimespec member]) -AH_TEMPLATE(HAVE_TERMIOS_H, [Define to 1 if you have the header file and the `tcgetattr' function.]) AH_TEMPLATE(HAVE_TIMESPEC, [Define to 1 if you have struct timespec in sys/time.h]) AH_TEMPLATE(HAVE___PROGNAME, [Define to 1 if your crt0.o defines the __progname symbol for you.]) AH_TEMPLATE(HOST_IN_LOG, [Define to 1 if you want the hostname to be entered into the log file.]) @@ -2975,7 +3049,8 @@ AH_TEMPLATE(USE_STOW, [Define to 1 if you use GNU stow packaging.]) AH_TEMPLATE(WITHOUT_PASSWD, [Define to avoid using the passwd/shadow file for authentication.]) AH_TEMPLATE(sig_atomic_t, [Define to `int' if does not define.]) AH_TEMPLATE(__signed, [Define to `signed' or nothing if compiler does not support a signed type qualifier.]) -AH_TEMPLATE(USING_NONUNIX_GROUPS, [Define to 1 if using a non-Unix group lookup implementation.]) +AH_TEMPLATE(HAVE_STRUCT_UTMP_UT_EXIT, [Define to 1 if `ut_exit' is a member of `struct utmp'.]) +AH_TEMPLATE(HAVE_STRUCT_UTMPX_UT_EXIT, [Define to 1 if `ut_exit' is a member of `struct utmpx'.]) dnl dnl Bits to copy verbatim into config.h.in @@ -3009,17 +3084,6 @@ AH_BOTTOM([/* # endif /* HAVE_ST_MTIMESPEC */ #endif /* HAVE_ST_MTIM */ -/* - * Emulate a subset of waitpid() if we don't have it. - */ -#ifdef HAVE_WAITPID -# define sudo_waitpid(p, s, o) waitpid(p, s, o) -#else -# ifdef HAVE_WAIT3 -# define sudo_waitpid(p, s, o) wait3(s, o, NULL) -# endif -#endif - /* GNU stow needs /etc/sudoers to be a symlink. */ #ifdef USE_STOW # define stat_sudoers stat diff --git a/HISTORY b/doc/HISTORY similarity index 83% rename from HISTORY rename to doc/HISTORY index 63c7f9f..b265144 100644 --- a/HISTORY +++ b/doc/HISTORY @@ -1,4 +1,6 @@ -A brief history of sudo: +A Brief History of Sudo: + +The Early Years Sudo was first conceived and implemented by Bob Coggeshall and Cliff Spencer around 1980 at the Department of Computer Science at SUNY/Buffalo. It ran on @@ -6,18 +8,24 @@ a VAX-11/750 running 4.1BSD. An updated version, credited to Phil Betchel, Cliff Spencer, Gretchen Phillips, John LoVerso and Don Gworek, was posted to the net.sources Usenet newsgroup in December of 1985. +Sudo at CU-Boulder + In the Summer of 1986, Garth Snyder released an enhanced version of sudo. For the next 5 years, sudo was fed and watered by a handful of folks at CU-Boulder, including Bob Coggeshall, Bob Manchek, and Trent Hein. +Root Group Sudo + In 1991, Dave Hieb and Jeff Nieusma wrote a new version of sudo with an enhanced sudoers format under contract to a consulting firm called "The Root Group". This version was later released under the GNU public license. +CU Sudo + In 1994, after maintaining sudo informally within CU-Boulder for some time, -Todd Miller made a public release of "CU sudo" (version 1.3) with bug fixes -and support for more operating systems. The "CU" was added to differentiate -it from the "official" version from "The Root Group". +Todd C. Miller made a public release of "CU sudo" (version 1.3) with bug +fixes and support for more operating systems. The "CU" was added to +differentiate it from the "official" version from "The Root Group". In 1995, a new parser for the sudoers file was contributed by Chris Jepeway. The new parser was a proper grammar (unlike the old one) and could work with @@ -27,6 +35,8 @@ In 1996, Todd, who had been maintaining sudo for several years in his spare time, moved distribution of sudo from a CU-Boulder ftp site to his domain, courtesan.com. +Just Plain Sudo + In 1999, the "CU" prefix was dropped from the name since there had been no formal release of sudo from "The Root Group" since 1991 (the original authors now work elsewhere). As of version 1.6, Sudo no longer contains any @@ -36,21 +46,29 @@ license. In 2001, the sudo web site, ftp site and mailing lists were moved from courtesan.com to the sudo.ws domain (sudo.org was already taken). +LDAP Integration + In 2003, Nationwide Mutual Insurance Company contributed code written by Aaron Spangler to store the sudoers data in LDAP. These changes were incorporated into Sudo 1.6.8. +New Parser + In 2005, Todd rewrote the sudoers parser to better support the features that had been added in the past ten years. This new parser removes some limitations of the previous one, removes ordering constraints and adds support for including multiple sudoers files. +Quest Sponsorship + In 2010, Quest Software began sponsoring Sudo development by hiring Todd to work on Sudo as part of his full-time job. -sudo, in its current form, is maintained by: +Present Day + +Sudo, in its current form, is maintained by: - Todd Miller + Todd C. Miller Todd continues to enhance sudo and fix bugs. diff --git a/LICENSE b/doc/LICENSE similarity index 70% rename from LICENSE rename to doc/LICENSE index 2af4e0f..f6c411f 100644 --- a/LICENSE +++ b/doc/LICENSE @@ -49,34 +49,6 @@ bear the following UCB license: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -The files nonunix.h and vasgroups.c bear the following license: - - Copyright (c) 2006 Quest Software, Inc. All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, - this list of conditions and the following disclaimer. - 2. Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in the - documentation and/or other materials provided with the distribution. - 3. Neither the name of Quest Software, Inc. nor the names of its - contributors may be used to endorse or promote products derived from - this software without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - The embedded copy of zlib bears the following license: Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler diff --git a/doc/Makefile.in b/doc/Makefile.in new file mode 100644 index 0000000..414d8c0 --- /dev/null +++ b/doc/Makefile.in @@ -0,0 +1,196 @@ +# +# Copyright (c) 2011 Todd C. Miller +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# @configure_input@ +# + +#### Start of system configuration section. #### + +srcdir = @srcdir@ +docdir = @docdir@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ + +# Tools to use +NROFF = @NROFFPROG@ -Tascii + +# Our install program supports extra flags... +INSTALL = $(SHELL) $(top_srcdir)/install-sh -c + +# Where to install things... +prefix = @prefix@ +datarootdir = @datarootdir@ +localstatedir = @localstatedir@ +mandir = @mandir@ + +# Directory in which to install the man page +mantype = @MANTYPE@ +mansectsu = @mansectsu@ +mansectform = @mansectform@ +mandirsu = $(mandir)/$(mantype)$(mansectsu) +mandirform = $(mandir)/$(mantype)$(mansectform) + +# User and group ids the installed files should be "owned" by +install_uid = 0 +install_gid = 0 + +#### End of system configuration section. #### + +SHELL = @SHELL@ + +DOCS = sudo.man visudo.man sudoers.man sudoers.ldap.man sudoers.man \ + sudoreplay.man sudo_plugin.man + +@DEV@DEVDOCS = $(srcdir)/sudo.man.in $(srcdir)/sudo.cat \ +@DEV@ $(srcdir)/visudo.man.in $(srcdir)/visudo.cat \ +@DEV@ $(srcdir)/sudoers.man.in $(srcdir)/sudoers.cat \ +@DEV@ $(srcdir)/sudoers.ldap.man.in $(srcdir)/sudoers.ldap.cat \ +@DEV@ $(srcdir)/sudoers.man.in $(srcdir)/sudoers.cat \ +@DEV@ $(srcdir)/sudoreplay.man.in $(srcdir)/sudoreplay.cat \ +@DEV@ $(srcdir)/sudo_plugin.man.in $(srcdir)/sudo_plugin.cat \ +@DEV@ $(srcdir)/HISTORY $(srcdir)/LICENSE + +OTHER_DOCS= $(top_srcdir)/ChangeLog $(top_srcdir)/README \ + $(top_srcdir)/NEWS $(srcdir)/HISTORY $(srcdir)/LICENSE \ + $(srcdir)/TROUBLESHOOTING $(srcdir)/UPGRADE $(srcdir)/sample.* + +OTHER_DOCS_LDAP= $(top_srcdir)/README.LDAP $(srcdir)/schema.* + +VERSION = @PACKAGE_VERSION@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ + +all: $(DEVDOCS) $(DOCS) + +Makefile: $(srcdir)/Makefile.in + (cd $(top_builddir) && ./config.status --file doc/Makefile) + +.SUFFIXES: .man + +@DEV@varsub: $(top_srcdir)/configure.in +@DEV@ printf 's#@%s@#1#\ns#@%s@#1#\ns#@%s@#1#\ns#@%s@#/etc#g\ns#@%s@#/usr/local#g\ns#@%s@#4#g\ns#@%s@#1m#g\n' SEMAN BAMAN LCMAN sysconfdir prefix mansectform mansectsu > $@; sed -n '/Begin initial values for man page substitution/,/End initial values for man page substitution/{;p;}' $(top_srcdir)/configure.in | sed -e '/^#/d' -e 's/^/s#@/' -e 's/=[\\"]*/@#/' -e 's/[\\"]*$$/#g/' >> $@ + +@DEV@$(srcdir)/sudo.man.in: $(srcdir)/sudo.pod +@DEV@ mansectsu=`echo @MANSECTSU@|tr A-Z a-z`; mansectform=`echo @MANSECTFORM@|tr A-Z a-z`; sed -n -e '/^=pod/q' -e 's/^/.\\" /p' $(srcdir)/sudo.pod > $@; pod2man --quotes=none --date="`date '+%B %e, %Y'`" --section=$$mansectsu --release=$(VERSION) --center="MAINTENANCE COMMANDS" $(srcdir)/sudo.pod | sed -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" | perl -p $(srcdir)/sudo.man.pl >> $@ + +sudo.man: $(srcdir)/sudo.man.in + (cd $(top_builddir) && $(SHELL) config.status --file=doc/$@) + +@DEV@$(srcdir)/sudo.cat: varsub $(srcdir)/sudo.man.in +@DEV@ sed -f varsub $(srcdir)/sudo.man.in | $(NROFF) -man > $@ + +@DEV@$(srcdir)/visudo.man.in: $(srcdir)/visudo.pod +@DEV@ mansectsu=`echo @MANSECTSU@|tr A-Z a-z`; mansectform=`echo @MANSECTFORM@|tr A-Z a-z`; sed -n -e '/^=pod/q' -e 's/^/.\\" /p' $(srcdir)/visudo.pod > $@; pod2man --quotes=none --date="`date '+%B %e, %Y'`" --section=$$mansectsu --release=$(VERSION) --center="MAINTENANCE COMMANDS" $(srcdir)/visudo.pod | sed -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" -e 's|\\fI\\f\((CW*\)*I@\([^@]*\)\\fI@|\\fI@\2@|g' >> $@ + +visudo.man: $(srcdir)/visudo.man.in + (cd $(top_builddir) && $(SHELL) config.status --file=doc/$@) + +@DEV@$(srcdir)/visudo.cat: varsub $(srcdir)/visudo.man.in +@DEV@ sed -f varsub $(srcdir)/visudo.man.in | $(NROFF) -man > $@ + +@DEV@$(srcdir)/sudoers.man.in: $(srcdir)/sudoers.pod +@DEV@ mansectsu=`echo @MANSECTSU@|tr A-Z a-z`; mansectform=`echo @MANSECTFORM@|tr A-Z a-z`; sed -n -e '/^=pod/q' -e 's/^/.\\" /p' $(srcdir)/sudoers.pod > $@; pod2man --quotes=none --date="`date '+%B %e, %Y'`" --section=$$mansectform --release=$(VERSION) --center="MAINTENANCE COMMANDS" $(srcdir)/sudoers.pod | sed -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" | perl -p $(srcdir)/sudoers.man.pl >> $@ + +sudoers.man: $(srcdir)/sudoers.man.in + (cd $(top_builddir) && $(SHELL) config.status --file=doc/$@) + +@DEV@$(srcdir)/sudoers.cat: varsub $(srcdir)/sudoers.man.in +@DEV@ sed -f varsub $(srcdir)/sudoers.man.in | $(NROFF) -man > $@ + +@DEV@$(srcdir)/sudoers.ldap.man.in: $(srcdir)/sudoers.ldap.pod +@DEV@ mansectsu=`echo @MANSECTSU@|tr A-Z a-z`; mansectform=`echo @MANSECTFORM@|tr A-Z a-z`; sed -n -e '/^=pod/q' -e 's/^/.\\" /p' $(srcdir)/sudoers.ldap.pod > $@; pod2man --quotes=none --date="`date '+%B %e, %Y'`" --section=$$mansectform --release=$(VERSION) --center="MAINTENANCE COMMANDS" $(srcdir)/sudoers.ldap.pod | sed -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" -e 's|\\fI\\f\((CW*\)*I@\([^@]*\)\\fI@|\\fI@\2@|g' >> $@ + +sudoers.ldap.man: $(srcdir)/sudoers.ldap.man.in + (cd $(top_builddir) && $(SHELL) config.status --file=doc/$@) + +@DEV@$(srcdir)/sudoers.ldap.cat: varsub $(srcdir)/sudoers.ldap.man.in +@DEV@ sed -f varsub $(srcdir)/sudoers.ldap.man.in | $(NROFF) -man > $@ + +@DEV@$(srcdir)/sudoreplay.man.in: $(srcdir)/sudoreplay.pod +@DEV@ mansectsu=`echo @MANSECTSU@|tr A-Z a-z`; mansectform=`echo @MANSECTFORM@|tr A-Z a-z`; sed -n -e '/^=pod/q' -e 's/^/.\\" /p' $(srcdir)/sudoreplay.pod > $@; pod2man --quotes=none --date="`date '+%B %e, %Y'`" --section=$$mansectsu --release=$(VERSION) --center="MAINTENANCE COMMANDS" $(srcdir)/sudoreplay.pod | sed -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" -e 's|\\fI\\f\((CW*\)*I@\([^@]*\)\\fI@|\\fI@\2@|g' >> $@ + +sudoreplay.man: $(srcdir)/sudoreplay.man.in + (cd $(top_builddir) && $(SHELL) config.status --file=doc/$@) + +@DEV@$(srcdir)/sudoreplay.cat: varsub $(srcdir)/sudoreplay.man.in +@DEV@ sed -f varsub $(srcdir)/sudoreplay.man.in | $(NROFF) -man > $@ + +@DEV@$(srcdir)/sudo_plugin.man.in: $(srcdir)/sudo_plugin.pod +@DEV@ mansectsu=`echo @MANSECTSU@|tr A-Z a-z`; mansectform=`echo @MANSECTFORM@|tr A-Z a-z`; sed -n -e '/^=pod/q' -e 's/^/.\\" /p' $(srcdir)/sudo_plugin.pod > $@; pod2man --quotes=none --date="`date '+%B %e, %Y'`" --section=$$mansectsu --release=$(VERSION) --center="MAINTENANCE COMMANDS" $(srcdir)/sudo_plugin.pod | sed -e "s/(5)/($$mansectform)/g" -e "s/(8)/($$mansectsu)/g" -e 's|\\fI\\f\((CW*\)*I@\([^@]*\)\\fI@|\\fI@\2@|g' >> $@ + +sudo_plugin.man: $(srcdir)/sudo_plugin.man.in + (cd $(top_builddir) && $(SHELL) config.status --file=doc/$@) + +@DEV@$(srcdir)/sudo_plugin.cat: varsub $(srcdir)/sudo_plugin.man.in +@DEV@ sed -f varsub $(srcdir)/sudo_plugin.man.in | $(NROFF) -man > $@ + +HISTORY: $(srcdir)/history.pod + pod2text -l -i0 $(srcdir)/history.pod > $@ + +LICENSE: $(srcdir)/license.pod + pod2text -l -i0 $(srcdir)/license.pod | sed '1,2d' > $@ + +pre-install: + +install: install-dirs install-doc + +install-dirs: + $(SHELL) $(top_srcdir)/mkinstalldirs $(DESTDIR)$(docdir) \ + $(DESTDIR)$(mandirsu) $(DESTDIR)$(mandirform) + +install-binaries: + +install-includes: + +install-doc: install-dirs + for f in $(OTHER_DOCS); do $(INSTALL) -O $(install_uid) -G $(install_gid) -M 0444 $$f $(DESTDIR)$(docdir); done + @LDAP@for f in $(OTHER_DOCS_LDAP); do $(INSTALL) -O $(install_uid) -G $(install_gid) -M 0444 $$f $(DESTDIR)$(docdir); done + $(INSTALL) -O $(install_uid) -G $(install_gid) -M 0444 @mansrcdir@/sudo.$(mantype) $(DESTDIR)$(mandirsu)/sudo.$(mansectsu) + @rm -f $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu) + ln $(DESTDIR)$(mandirsu)/sudo.$(mansectsu) $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu) + $(INSTALL) -O $(install_uid) -G $(install_gid) -M 0444 @mansrcdir@/sudo_plugin.$(mantype) $(DESTDIR)$(mandirsu)/sudo_plugin.$(mansectsu) + $(INSTALL) -O $(install_uid) -G $(install_gid) -M 0444 @mansrcdir@/sudoreplay.$(mantype) $(DESTDIR)$(mandirsu)/sudoreplay.$(mansectsu) + $(INSTALL) -O $(install_uid) -G $(install_gid) -M 0444 @mansrcdir@/visudo.$(mantype) $(DESTDIR)$(mandirsu)/visudo.$(mansectsu) + $(INSTALL) -O $(install_uid) -G $(install_gid) -M 0444 @mansrcdir@/sudoers.$(mantype) $(DESTDIR)$(mandirform)/sudoers.$(mansectform) + @LDAP@$(INSTALL) -O $(install_uid) -G $(install_gid) -M 0444 @mansrcdir@/sudoers.ldap.$(mantype) $(DESTDIR)$(mandirform)/sudoers.ldap.$(mansectform) +@MAN_POSTINSTALL@ + +install-plugin: + +uninstall: + -rm -rf $(DESTDIR)$(docdir) + -rm -f $(DESTDIR)$(mandirsu)/sudo.$(mansectsu) \ + $(DESTDIR)$(mandirsu)/sudoedit.$(mansectsu) \ + $(DESTDIR)$(mandirsu)/sudo_plugin.$(mansectsu) \ + $(DESTDIR)$(mandirsu)/sudoreplay.$(mansectsu) \ + $(DESTDIR)$(mandirsu)/visudo.$(mansectsu) \ + $(DESTDIR)$(mandirform)/sudoers.$(mansectform) \ + $(DESTDIR)$(mandirform)/sudoers.ldap.$(mansectform) + +check: + +clean: + -rm -f varsub + +mostlyclean: clean + +distclean: clean + -rm -rf Makefile config.log *.man + +clobber: distclean + +realclean: distclean + +cleandir: distclean diff --git a/TROUBLESHOOTING b/doc/TROUBLESHOOTING similarity index 100% rename from TROUBLESHOOTING rename to doc/TROUBLESHOOTING diff --git a/UPGRADE b/doc/UPGRADE similarity index 85% rename from UPGRADE rename to doc/UPGRADE index 8b7da22..35ca9a5 100644 --- a/UPGRADE +++ b/doc/UPGRADE @@ -1,7 +1,7 @@ Notes on upgrading from an older release ======================================== -o Upgrading from a version prior to 1.7.6: +o Upgrading from a version prior to 1.8.1: Changes in the sudoers parser could result in parse errors for existing sudoers file. These changes cause certain erroneous @@ -30,6 +30,45 @@ o Upgrading from a version prior to 1.7.6: To avoid problems, sudo 1.8.1's "make install" will not install a new sudo binary if the existing sudoers file has errors. + In Sudo 1.8.1 the "noexec" functionality has moved out of the + sudoers policy plugin and into the sudo front-end. As a result, + the path to the noexec file is now specified in the sudo.conf + file instead of the sudoers file. If you have a sudoers file + that uses the "noexec_file" option, you will need to move the + definition to the sudo.conf file instead. + + Old style in /etc/sudoers: + Defaults noexec_file=/usr/local/libexec/sudo_noexec.so + + New style in /etc/sudo.conf: + Path noexec /usr/local/libexec/sudo_noexec.so + +o Upgrading from a version prior to 1.8.0: + + Starting with version 1.8.0, sudo uses a modular framework to + support policy and I/O logging plugins. The default policy + plugin is "sudoers" which provides the traditional sudoers + evaluation and I/O logging. Plugins are typically located in + /usr/libexec or /usr/local/libexec, though this is system-dependent. + The sudoers plugin is named "sudoers.so" on most systems. + + The sudo.conf file, usually stored in /etc, is used to configure + plugins. This file is optional--if no plugins are specified + in sudo.conf, the "sudoers" plugin is used. See the sample.sudo.conf + file in the doc directory or refer to the updated sudo manual + to see how to configure sudo.conf. + + The "askpass" setting has moved from the sudoers file to the + sudo.conf file. If you have a sudoers file that uses the + "askpass" option, you will need to move the definition to the + sudo.conf file. + + Old style in /etc/sudoers: + Defaults askpass=/usr/X11R6/bin/ssh-askpass + + New style in /etc/sudo.conf: + Path askpass /usr/X11R6/bin/ssh-askpass + o Upgrading from a version prior to 1.7.5: Sudo 1.7.5 includes an updated LDAP schema with support for diff --git a/doc/history.pod b/doc/history.pod new file mode 100644 index 0000000..506afc0 --- /dev/null +++ b/doc/history.pod @@ -0,0 +1,79 @@ +=head1 A Brief History of Sudo: + +=head3 The Early Years + +Sudo was first conceived and implemented by Bob Coggeshall and Cliff +Spencer around 1980 at the Department of Computer Science at +SUNY/Buffalo. It ran on a VAX-11/750 running 4.1BSD. An updated +version, credited to Phil Betchel, Cliff Spencer, Gretchen Phillips, +John LoVerso and Don Gworek, was posted to the net.sources Usenet +newsgroup in December of 1985. + +=head3 Sudo at CU-Boulder + +In the Summer of 1986, Garth Snyder released an enhanced version +of sudo. For the next 5 years, sudo was fed and watered by a handful +of folks at CU-Boulder, including Bob Coggeshall, Bob Manchek, and +Trent Hein. + +=head3 Root Group Sudo + +In 1991, Dave Hieb and Jeff Nieusma wrote a new version of sudo +with an enhanced sudoers format under contract to a consulting firm +called "The Root Group". This version was later released under the +GNU public license. + +=head3 CU Sudo + +In 1994, after maintaining sudo informally within CU-Boulder for +some time, Todd C. Miller made a public release of "CU sudo" (version +1.3) with bug fixes and support for more operating systems. The +"CU" was added to differentiate it from the "official" version from +"The Root Group". + +In 1995, a new parser for the sudoers file was contributed by Chris +Jepeway. The new parser was a proper grammar (unlike the old one) +and could work with both sudo and visudo (previously they had +slightly different parsers). + +In 1996, Todd, who had been maintaining sudo for several years in +his spare time, moved distribution of sudo from a CU-Boulder ftp +site to his domain, courtesan.com. + +=head3 Just Plain Sudo + +In 1999, the "CU" prefix was dropped from the name since there had +been no formal release of sudo from "The Root Group" since 1991 +(the original authors now work elsewhere). As of version 1.6, Sudo +no longer contains any of the original "Root Group" code and is +available under an ISC-style license. + +In 2001, the sudo web site, ftp site and mailing lists were moved +from courtesan.com to the sudo.ws domain (sudo.org was already +taken). + +=head3 LDAP Integration + +In 2003, Nationwide Mutual Insurance Company contributed code written +by Aaron Spangler to store the sudoers data in LDAP. These changes +were incorporated into Sudo 1.6.8. + +=head3 New Parser + +In 2005, Todd rewrote the sudoers parser to better support the +features that had been added in the past ten years. This new parser +removes some limitations of the previous one, removes ordering +constraints and adds support for including multiple sudoers files. + +=head3 Quest Sponsorship + +In 2010, Quest Software began sponsoring Sudo development by hiring +Todd to work on Sudo as part of his full-time job. + +=head3 Present Day + +Sudo, in its current form, is maintained by: + + Todd C. Miller + +Todd continues to enhance sudo and fix bugs. diff --git a/doc/license.pod b/doc/license.pod new file mode 100644 index 0000000..5786e38 --- /dev/null +++ b/doc/license.pod @@ -0,0 +1,78 @@ +=head1 Sudo License + +=head3 +Sudo is distributed under the following ISC-style license: + + Copyright (c) 1994-1996, 1998-2010 + Todd C. Miller + + Permission to use, copy, modify, and distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + Sponsored in part by the Defense Advanced Research Projects + Agency (DARPA) and Air Force Research Laboratory, Air Force + Materiel Command, USAF, under agreement number F39502-99-1-0512. + +=head3 +The files fnmatch.c, fnmatch.h, getcwd.c, glob.c, glob.h and snprintf.c +bear the following UCB license: + + Copyright (c) 1987, 1989, 1990, 1991, 1992, 1993, 1994 + The Regents of the University of California. All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + 3. Neither the name of the University nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + SUCH DAMAGE. + +=head3 +The embedded copy of zlib bears the following license: + + Copyright (C) 1995-2010 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu diff --git a/sample.pam b/doc/sample.pam similarity index 100% rename from sample.pam rename to doc/sample.pam diff --git a/doc/sample.sudo.conf b/doc/sample.sudo.conf new file mode 100644 index 0000000..18baa59 --- /dev/null +++ b/doc/sample.sudo.conf @@ -0,0 +1,42 @@ +# +# Sample /etc/sudo.conf file +# +# Format: +# Plugin plugin_name plugin_path +# Path askpass /path/to/askpass +# Path noexec /path/to/noexec.so +# +# Sudo plugins: +# +# The plugin_path is relative to ${prefix}/libexec unless fully qualified. +# The plugin_name corresponds to a global symbol in the plugin +# that contains the plugin interface structure. +# +# The sudoers plugin is used by default if no Plugin lines are present. +Plugin sudoers_policy sudoers.so +Plugin sudoers_io sudoers.so + +# +# Sudo askpass: +# +# An askpass helper program may be specified to provide a graphical +# password prompt for "sudo -A" support. Sudo does not ship with its +# own passpass program but can use the OpenSSH askpass. +# +# Use the OpenSSH askpass +#Path askpass /usr/X11R6/bin/ssh-askpass +# +# Use the Gnome OpenSSH askpass +#Path askpass /usr/libexec/openssh/gnome-ssh-askpass + +# +# Sudo noexec: +# +# Path to a shared library containing dummy versions of the execv(), +# execve() and fexecve() library functions that just return an error. +# This is used to implement the "noexec" functionality on systems that +# support C or its equivalent. +# The compiled-in value is usually sufficient and should only be changed +# if you rename or move the sudo_noexec.so file. +# +#Path noexec /usr/libexec/sudo_noexec.so diff --git a/sample.sudoers b/doc/sample.sudoers similarity index 100% rename from sample.sudoers rename to doc/sample.sudoers diff --git a/sample.syslog.conf b/doc/sample.syslog.conf similarity index 100% rename from sample.syslog.conf rename to doc/sample.syslog.conf diff --git a/schema.ActiveDirectory b/doc/schema.ActiveDirectory similarity index 100% rename from schema.ActiveDirectory rename to doc/schema.ActiveDirectory diff --git a/schema.OpenLDAP b/doc/schema.OpenLDAP similarity index 100% rename from schema.OpenLDAP rename to doc/schema.OpenLDAP diff --git a/schema.iPlanet b/doc/schema.iPlanet similarity index 100% rename from schema.iPlanet rename to doc/schema.iPlanet diff --git a/doc/sudo.cat b/doc/sudo.cat new file mode 100644 index 0000000..08e1ac8 --- /dev/null +++ b/doc/sudo.cat @@ -0,0 +1,547 @@ +SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) + + + +NNAAMMEE + sudo, sudoedit - execute a command as another user + +SSYYNNOOPPSSIISS + ssuuddoo [--DD _l_e_v_e_l] --hh | --KK | --kk | --VV + + ssuuddoo --vv [--AAkknnSS] [--aa _a_u_t_h___t_y_p_e] [--DD _l_e_v_e_l] [--gg _g_r_o_u_p _n_a_m_e|_#_g_i_d] + [--pp _p_r_o_m_p_t] [--uu _u_s_e_r _n_a_m_e|_#_u_i_d] + + ssuuddoo --ll[[ll]] [--AAkknnSS] [--aa _a_u_t_h___t_y_p_e] [--DD _l_e_v_e_l] [--gg _g_r_o_u_p _n_a_m_e|_#_g_i_d] + [--pp _p_r_o_m_p_t] [--UU _u_s_e_r _n_a_m_e] [--uu _u_s_e_r _n_a_m_e|_#_u_i_d] [_c_o_m_m_a_n_d] + + ssuuddoo [--AAbbEEHHnnPPSS] [--aa _a_u_t_h___t_y_p_e] [--CC _f_d] [--DD _l_e_v_e_l] [--cc _c_l_a_s_s|_-] + [--gg _g_r_o_u_p _n_a_m_e|_#_g_i_d] [--pp _p_r_o_m_p_t] [--rr _r_o_l_e] [--tt _t_y_p_e] + [--uu _u_s_e_r _n_a_m_e|_#_u_i_d] [VVAARR=_v_a_l_u_e] [--ii | --ss] [_c_o_m_m_a_n_d] + + ssuuddooeeddiitt [--AAnnSS] [--aa _a_u_t_h___t_y_p_e] [--CC _f_d] [--cc _c_l_a_s_s|_-] [--DD _l_e_v_e_l] + [--gg _g_r_o_u_p _n_a_m_e|_#_g_i_d] [--pp _p_r_o_m_p_t] [--uu _u_s_e_r _n_a_m_e|_#_u_i_d] file ... + +DDEESSCCRRIIPPTTIIOONN + ssuuddoo allows a permitted user to execute a _c_o_m_m_a_n_d as the superuser or + another user, as specified by the security policy. The real and + effective uid and gid are set to match those of the target user, as + specified in the password database, and the group vector is initialized + based on the group database (unless the --PP option was specified). + + ssuuddoo supports a plugin architecture for security policies and + input/output logging. Third parties can develop and distribute their + own policy and I/O logging modules to work seemlessly with the ssuuddoo + front end. The default security policy is _s_u_d_o_e_r_s, which is configured + via the file _/_e_t_c_/_s_u_d_o_e_r_s, or via LDAP. See the PLUGINS section for + more information. + + The security policy determines what privileges, if any, a user has to + run ssuuddoo. The policy may require that users authenticate themselves + with a password or another authentication mechanism. If authentication + is required, ssuuddoo will exit if the user's password is not entered + within a configurable time limit. This limit is policy-specific; the + default password prompt timeout for the _s_u_d_o_e_r_s security policy is 5 + minutes. + + Security policies may support credential caching to allow the user to + run ssuuddoo again for a period of time without requiring authentication. + The _s_u_d_o_e_r_s policy caches credentials for 5 minutes, unless overridden + in _s_u_d_o_e_r_s(4). By running ssuuddoo with the --vv option, a user can update + the cached credentials without running a _c_o_m_m_a_n_d. + + When invoked as ssuuddooeeddiitt, the --ee option (described below), is implied. + + Security policies may log successful and failed attempts to use ssuuddoo. + If an I/O plugin is configured, the running command's input and output + may be logged as well. + +OOPPTTIIOONNSS + ssuuddoo accepts the following command line options: + + -A Normally, if ssuuddoo requires a password, it will read it from + the user's terminal. If the --AA (_a_s_k_p_a_s_s) option is + specified, a (possibly graphical) helper program is + executed to read the user's password and output the + password to the standard output. If the SUDO_ASKPASS + environment variable is set, it specifies the path to the + helper program. Otherwise, if _/_e_t_c_/_s_u_d_o_._c_o_n_f contains a + line specifying the askpass program, that value will be + used. For example: + + # Path to askpass helper program + Path askpass /usr/X11R6/bin/ssh-askpass + + If no askpass program is available, sudo will exit with an + error. + + -a _t_y_p_e The --aa (_a_u_t_h_e_n_t_i_c_a_t_i_o_n _t_y_p_e) option causes ssuuddoo to use the + specified authentication type when validating the user, as + allowed by _/_e_t_c_/_l_o_g_i_n_._c_o_n_f. The system administrator may + specify a list of sudo-specific authentication methods by + adding an "auth-sudo" entry in _/_e_t_c_/_l_o_g_i_n_._c_o_n_f. This + option is only available on systems that support BSD + authentication. + + -b The --bb (_b_a_c_k_g_r_o_u_n_d) option tells ssuuddoo to run the given + command in the background. Note that if you use the --bb + option you cannot use shell job control to manipulate the + process. Most interactive commands will fail to work + properly in background mode. + + -C _f_d Normally, ssuuddoo will close all open file descriptors other + than standard input, standard output and standard error. + The --CC (_c_l_o_s_e _f_r_o_m) option allows the user to specify a + starting point above the standard error (file descriptor + three). Values less than three are not permitted. The + security policy may restrict the user's ability to use the + --CC option. The _s_u_d_o_e_r_s policy only permits use of the --CC + option when the administrator has enabled the + _c_l_o_s_e_f_r_o_m___o_v_e_r_r_i_d_e option. + + -c _c_l_a_s_s The --cc (_c_l_a_s_s) option causes ssuuddoo to run the specified + command with resources limited by the specified login + class. The _c_l_a_s_s argument can be either a class name as + defined in _/_e_t_c_/_l_o_g_i_n_._c_o_n_f, or a single '-' character. + Specifying a _c_l_a_s_s of - indicates that the command should + be run restricted by the default login capabilities for the + user the command is run as. If the _c_l_a_s_s argument + specifies an existing user class, the command must be run + as root, or the ssuuddoo command must be run from a shell that + is already root. This option is only available on systems + with BSD login classes. + + -D _l_e_v_e_l Enable debugging of ssuuddoo plugins and ssuuddoo itself. The + _l_e_v_e_l may be a value from 1 through 9. + + -E The --EE (_p_r_e_s_e_r_v_e _e_n_v_i_r_o_n_m_e_n_t) option indicates to the + security policy that the uses wishes to preserve their + existing environment variables. The security policy may + return an error if the --EE option is specified and the user + does not have permission to preserve the environment. + + -e The --ee (_e_d_i_t) 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 security policy. If the user is authorized + by the policy, the following steps are taken: + + 1. Temporary copies are made of the files to be edited + with the owner set to the invoking user. + + 2. The editor specified by the policy is run to edit the + temporary files. The _s_u_d_o_e_r_s policy uses the + SUDO_EDITOR, VISUAL and EDITOR environment variables + (in that order). If none of SUDO_EDITOR, VISUAL or + EDITOR are set, the first program listed in the _e_d_i_t_o_r + _s_u_d_o_e_r_s(4) option is used. + + 3. If they have been modified, the temporary files are + copied back to their original location and the + temporary versions are removed. + + If the specified file does not exist, it will be created. + Note that unlike most commands run by ssuuddoo, the editor is + run with the invoking user's environment unmodified. If, + for some reason, ssuuddoo 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. + + -g _g_r_o_u_p Normally, ssuuddoo runs a command with the primary group set to + the one specified by the password database for the user the + command is being run as (by default, root). The --gg (_g_r_o_u_p) + option causes ssuuddoo to run the command with the primary + group set to _g_r_o_u_p instead. To specify a _g_i_d instead of a + _g_r_o_u_p _n_a_m_e, use _#_g_i_d. When running commands as a _g_i_d, many + shells require that the '#' be escaped with a backslash + ('\'). If no --uu option is specified, the command will be + run as the invoking user (not root). In either case, the + primary group will be set to _g_r_o_u_p. + + -H The --HH (_H_O_M_E) option requests that the security policy set + the HOME environment variable to the home directory of the + target user (root by default) as specified by the password + database. Depending on the policy, this may be the default + behavior. + + -h The --hh (_h_e_l_p) option causes ssuuddoo to print a short help + message to the standard output and exit. + + -i [command] + The --ii (_s_i_m_u_l_a_t_e _i_n_i_t_i_a_l _l_o_g_i_n) option runs the shell + specified by the password database entry of the target user + as a login shell. This means that login-specific resource + files such as .profile or .login will be read by the shell. + If a command is specified, it is passed to the shell for + execution via the shell's --cc option. If no command is + specified, an interactive shell is executed. ssuuddoo attempts + to change to that user's home directory before running the + shell. The security policy shall initialize the + environment to a minimal set of variables, similar to what + is present when a user logs in. + + -K The --KK (sure _k_i_l_l) option is like --kk except that it removes + the user's cached credentials entirely and may not be used + in conjunction with a command or other option. This option + does not require a password. Not all security policies + support credential caching. + + -k [command] + When used alone, the --kk (_k_i_l_l) option to ssuuddoo invalidates + the user's cached credentials. The next time ssuuddoo is run a + password will be required. This option does not require a + password and was added to allow a user to revoke ssuuddoo + permissions from a .logout file. Not all security policies + support credential caching. + + When used in conjunction with a command or an option that + may require a password, the --kk option will cause ssuuddoo to + ignore the user's cached credentials. As a result, ssuuddoo + will prompt for a password (if one is required by the + security policy) and will not update the user's cached + credentials. + + -l[l] [_c_o_m_m_a_n_d] + If no _c_o_m_m_a_n_d is specified, the --ll (_l_i_s_t) option will list + the allowed (and forbidden) commands for the invoking user + (or the user specified by the --UU option) on the current + host. If a _c_o_m_m_a_n_d is specified and is permitted by the + security policy, the fully-qualified path to the command is + displayed along with any command line arguments. If + _c_o_m_m_a_n_d is specified but not allowed, ssuuddoo will exit with a + status value of 1. If the --ll option is specified with an ll + argument (i.e. --llll), or if --ll is specified multiple times, + a longer list format is used. + + -n The --nn (_n_o_n_-_i_n_t_e_r_a_c_t_i_v_e) option prevents ssuuddoo from + prompting the user for a password. If a password is + required for the command to run, ssuuddoo will display an error + messages and exit. + + -P The --PP (_p_r_e_s_e_r_v_e _g_r_o_u_p _v_e_c_t_o_r) option causes ssuuddoo to + preserve the invoking user's group vector unaltered. By + default, the _s_u_d_o_e_r_s policy 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. + + -p _p_r_o_m_p_t The --pp (_p_r_o_m_p_t) option allows you to override the default + password prompt and use a custom one. The following + percent (`%') escapes are supported by the _s_u_d_o_e_r_s policy: + + %H expanded to the host name including the domain name (on + if the machine's host name is fully qualified or the + _f_q_d_n option is set in _s_u_d_o_e_r_s(4)) + + %h expanded to the local host name without the domain name + + %p expanded to the name of the user whose password is + being requested (respects the _r_o_o_t_p_w, _t_a_r_g_e_t_p_w and + _r_u_n_a_s_p_w flags in _s_u_d_o_e_r_s(4)) + + %U expanded to the login name of the user the command will + be run as (defaults to root unless the -u option is + also specified) + + %u expanded to the invoking user's login name + + %% two consecutive % characters are collapsed into a + single % character + + The prompt specified by the --pp option will override the + system password prompt on systems that support PAM unless + the _p_a_s_s_p_r_o_m_p_t___o_v_e_r_r_i_d_e flag is disabled in _s_u_d_o_e_r_s. + + -r _r_o_l_e The --rr (_r_o_l_e) option causes the new (SELinux) security + context to have the role specified by _r_o_l_e. + + -S The --SS (_s_t_d_i_n) option causes ssuuddoo to read the password from + the standard input instead of the terminal device. The + password must be followed by a newline character. + + -s [command] + The --ss (_s_h_e_l_l) option runs the shell specified by the _S_H_E_L_L + environment variable if it is set or the shell as specified + in the password database. If a command is specified, it is + passed to the shell for execution via the shell's --cc + option. If no command is specified, an interactive shell + is executed. + + -t _t_y_p_e The --tt (_t_y_p_e) option causes the new (SELinux) security + context to have the type specified by _t_y_p_e. If no type is + specified, the default type is derived from the specified + role. + + -U _u_s_e_r The --UU (_o_t_h_e_r _u_s_e_r) option is used in conjunction with the + --ll option to specify the user whose privileges should be + listed. The security policy may restrict listing other + users' privileges. The _s_u_d_o_e_r_s policy only allows root or + a user with the ALL privilege on the current host to use + this option. + + -u _u_s_e_r The --uu (_u_s_e_r) option causes ssuuddoo to run the specified + command as a user other than _r_o_o_t. To specify a _u_i_d + instead of a _u_s_e_r _n_a_m_e, use _#_u_i_d. When running commands as + a _u_i_d, many shells require that the '#' be escaped with a + backslash ('\'). Security policies may restrict _u_i_ds to + those listed in the password database. The _s_u_d_o_e_r_s policy + allows _u_i_ds that are not in the password database as long + as the _t_a_r_g_e_t_p_w option is not set. Other security policies + may not support this. + + -V The --VV (_v_e_r_s_i_o_n) option causes ssuuddoo to print its version + string and the version string of the security policy plugin + and any I/O plugins. If the invoking user is already root + the --VV option will display the arguments passed to + configure when _s_u_d_o was built and plugins may display more + verbose information such as default options. + + -v When given the --vv (_v_a_l_i_d_a_t_e) option, ssuuddoo will update the + user's cached credentials, authenticating the user's + password if necessary. For the _s_u_d_o_e_r_s plugin, this + extends the ssuuddoo timeout for another 5 minutes (or whatever + the timeout is set to in _s_u_d_o_e_r_s) but does not run a + command. Not all security policies support cached + credentials. + + -- The ---- option indicates that ssuuddoo should stop processing + command line arguments. + + Environment variables to be set for the command may also be passed on + the command line in the form of VVAARR=_v_a_l_u_e, e.g. + LLDD__LLIIBBRRAARRYY__PPAATTHH=_/_u_s_r_/_l_o_c_a_l_/_p_k_g_/_l_i_b. Variables passed on the command + line are subject to the same restrictions as normal environment + variables with one important exception. If the _s_e_t_e_n_v option is set in + _s_u_d_o_e_r_s, 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 _s_u_d_o_e_r_s(4) for more information. + +PPLLUUGGIINNSS + Plugins are dynamically loaded based on the contents of the + _/_e_t_c_/_s_u_d_o_._c_o_n_f file. If no _/_e_t_c_/_s_u_d_o_._c_o_n_f file is present, or it + contains no Plugin lines, ssuuddoo will use the traditional _s_u_d_o_e_r_s + security policy and I/O logging, which corresponds to the following + _/_e_t_c_/_s_u_d_o_._c_o_n_f file. + + # + # Default /etc/sudo.conf file + # + # Format: + # Plugin plugin_name plugin_path + # Path askpass /path/to/askpass + # Path noexec /path/to/noexec.so + # + # The plugin_path is relative to /usr/local/libexec unless + # fully qualified. + # The plugin_name corresponds to a global symbol in the plugin + # that contains the plugin interface structure. + # + Plugin policy_plugin sudoers.so + Plugin io_plugin sudoers.so + + A Plugin line consists of the Plugin keyword, followed by the + _s_y_m_b_o_l___n_a_m_e and the _p_a_t_h to the shared object containing the plugin. + The _s_y_m_b_o_l___n_a_m_e is the name of the struct policy_plugin or struct + io_plugin in the plugin shared object. The _p_a_t_h may be fully qualified + or relative. If not fully qualified it is relative to the + _/_u_s_r_/_l_o_c_a_l_/_l_i_b_e_x_e_c directory. Any additional parameters after the _p_a_t_h + are ignored. Lines that don't begin with Plugin or Path are silently + ignored + + For more information, see the _s_u_d_o___p_l_u_g_i_n(1m) manual. + +PPAATTHHSS + A Path line consists of the Path keyword, followed by the name of the + path to set and its value. E.g. + + Path noexec /usr/local/libexec/sudo_noexec.so + Path askpass /usr/X11R6/bin/ssh-askpass + + The following plugin-agnostic paths may be set in the _/_e_t_c_/_s_u_d_o_._c_o_n_f + file. + + askpass The fully qualified path to a helper program used to + read the user's password when no terminal is available. + This may be the case when ssuuddoo is executed from a + graphical (as opposed to text-based) application. The + program specified by _a_s_k_p_a_s_s should display the + argument passed to it as the prompt and write the + user's password to the standard output. The value of + _a_s_k_p_a_s_s may be overridden by the SUDO_ASKPASS + environment variable. + + noexec The fully-qualified path to a shared library containing + dummy versions of the _e_x_e_c_v_(_), _e_x_e_c_v_e_(_) and _f_e_x_e_c_v_e_(_) + library functions that just return an error. This is + used to implement the _n_o_e_x_e_c functionality on systems + that support LD_PRELOAD or its equivalent. Defaults to + _/_u_s_r_/_l_o_c_a_l_/_l_i_b_e_x_e_c_/_s_u_d_o___n_o_e_x_e_c_._s_o. + +RREETTUURRNN VVAALLUUEESS + Upon successful execution of a program, the exit status from ssuuddoo will + simply be the exit status of the program that was executed. + + Otherwise, ssuuddoo exits with a value of 1 if there is a + configuration/permission problem or if ssuuddoo cannot execute the given + command. In the latter case the error string is printed to the + standard error. If ssuuddoo cannot _s_t_a_t(2) one or more entries in the + user's PATH, an error is printed on stderr. (If the directory does not + exist or if it is not really a directory, the entry is ignored and no + error is printed.) This should not happen under normal circumstances. + The most common reason for _s_t_a_t(2) to return "permission denied" is if + you are running an automounter and one of the directories in your PATH + is on a machine that is currently unreachable. + +SSEECCUURRIITTYY NNOOTTEESS + ssuuddoo tries to be safe when executing external commands. + + To prevent command spoofing, ssuuddoo checks "." and "" (both denoting + current directory) last when searching for a command in the user's PATH + (if one or both are in the PATH). Note, however, that the actual PATH + environment variable is _n_o_t modified and is passed unchanged to the + program that ssuuddoo executes. + + Please note that ssuuddoo 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 are not subject to ssuuddoo's security policy. + The same is true for commands that offer shell escapes (including most + editors). If I/O logging is enabled, subsequent commands will have + their input and/or output logged, but there will not be traditional + logs for those commands. Because of this, care must be taken when + giving users access to commands via ssuuddoo to verify that the command + does not inadvertently give the user an effective root shell. For more + information, please see the PREVENTING SHELL ESCAPES section in + _s_u_d_o_e_r_s(4). + +EENNVVIIRROONNMMEENNTT + ssuuddoo utilizes the following environment variables. The security policy + has control over the content of the command's environment. + + EDITOR Default editor to use in --ee (sudoedit) mode if neither + SUDO_EDITOR nor VISUAL is set + + MAIL In --ii mode or when _e_n_v___r_e_s_e_t is enabled in _s_u_d_o_e_r_s, set + to the mail spool of the target user + + HOME Set to the home directory of the target user if --ii or + --HH are specified, _e_n_v___r_e_s_e_t or _a_l_w_a_y_s___s_e_t___h_o_m_e are set + in _s_u_d_o_e_r_s, or when the --ss option is specified and + _s_e_t___h_o_m_e is set in _s_u_d_o_e_r_s + + PATH May be overridden by the security policy. + + SHELL Used to determine shell to run with -s option + + SUDO_ASKPASS Specifies the path to a helper program used to read the + password if no terminal is available or if the -A + option is specified. + + SUDO_COMMAND Set to the command run by sudo + + SUDO_EDITOR Default editor to use in --ee (sudoedit) mode + + SUDO_GID Set to the group ID of the user who invoked sudo + + SUDO_PROMPT Used as the default password prompt + + SUDO_PS1 If set, PS1 will be set to its value for the program + being run + + SUDO_UID Set to the user ID of the user who invoked sudo + + SUDO_USER Set to the login of the user who invoked sudo + + USER Set to the target user (root unless the --uu option is + specified) + + VISUAL Default editor to use in --ee (sudoedit) mode if + SUDO_EDITOR is not set + +FFIILLEESS + _/_e_t_c_/_s_u_d_o_._c_o_n_f ssuuddoo plugin and path configuration + +EEXXAAMMPPLLEESS + Note: the following examples assume a properly configured security + policy. + + To get a file listing of an unreadable directory: + + $ sudo ls /usr/local/protected + + To list the home directory of user yaz on a machine where the file + system holding ~yaz is not exported as root: + + $ sudo -u yaz ls ~yaz + + To edit the _i_n_d_e_x_._h_t_m_l file as user www: + + $ sudo -u www vi ~www/htdocs/index.html + + To view system logs only accessible to root and users in the adm group: + + $ sudo -g adm view /var/log/syslog + + To run an editor as jim with a different primary group: + + $ sudo -u jim -g audio vi ~jim/sound.txt + + To shutdown a machine: + + $ sudo shutdown -r +15 "quick reboot" + + To make a usage listing of the directories in the /home partition. + Note that this runs the commands in a sub-shell to make the cd and file + redirection work. + + $ sudo sh -c "cd /home ; du -s * | sort -rn > USAGE" + +SSEEEE AALLSSOO + _g_r_e_p(1), _s_u(1), _s_t_a_t(2), _l_o_g_i_n___c_a_p(3), _p_a_s_s_w_d(4), _s_u_d_o_e_r_s(4), + _s_u_d_o___p_l_u_g_i_n(1m), _s_u_d_o_r_e_p_l_a_y(1m), _v_i_s_u_d_o(1m) + +AAUUTTHHOORRSS + Many people have worked on ssuuddoo over the years; this version consists + of code written primarily by: + + Todd C. Miller + + See the HISTORY file in the ssuuddoo distribution or visit + http://www.sudo.ws/sudo/history.html for a short history of ssuuddoo. + +CCAAVVEEAATTSS + There is no easy way to prevent a user from gaining a root shell if + that user is allowed to run arbitrary commands via ssuuddoo. Also, many + programs (such as editors) allow the user to run commands via shell + escapes, thus avoiding ssuuddoo's checks. However, on most systems it is + possible to prevent shell escapes with the _s_u_d_o_e_r_s(4) module's _n_o_e_x_e_c + functionality. + + It is not meaningful to run the cd command directly via sudo, e.g., + + $ sudo cd /usr/local/protected + + since when the command exits the parent process (your shell) will still + be the same. Please see the EXAMPLES section for more information. + + Running shell scripts via ssuuddoo can expose the same kernel bugs that + make setuid shell scripts unsafe on some operating systems (if your OS + has a /dev/fd/ directory, setuid shell scripts are generally safe). + +BBUUGGSS + If you feel you have found a bug in ssuuddoo, please submit a bug report at + http://www.sudo.ws/sudo/bugs/ + +SSUUPPPPOORRTT + Limited free support is available via the sudo-users mailing list, see + http://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or search + the archives. + +DDIISSCCLLAAIIMMEERR + ssuuddoo is provided ``AS IS'' and any express or implied warranties, + including, but not limited to, the implied warranties of + merchantability and fitness for a particular purpose are disclaimed. + See the LICENSE file distributed with ssuuddoo or + http://www.sudo.ws/sudo/license.html for complete details. + + + +1.8.1p2 May 16, 2011 SUDO(1m) diff --git a/sudo.man.in b/doc/sudo.man.in similarity index 57% rename from sudo.man.in rename to doc/sudo.man.in index 09f1508..1d5ca05 100644 --- a/sudo.man.in +++ b/doc/sudo.man.in @@ -1,4 +1,4 @@ -.\" Copyright (c) 1994-1996, 1998-2005, 2007-2010 +.\" Copyright (c) 1994-1996, 1998-2005, 2007-2011 .\" Todd C. Miller .\" .\" Permission to use, copy, modify, and distribute this software for any @@ -149,7 +149,7 @@ .\" ======================================================================== .\" .IX Title "SUDO @mansectsu@" -.TH SUDO @mansectsu@ "April 9, 2011" "1.7.6" "MAINTENANCE COMMANDS" +.TH SUDO @mansectsu@ "May 16, 2011" "1.8.1p2" "MAINTENANCE COMMANDS" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -158,21 +158,24 @@ 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 +\&\fBsudo\fR [\fB\-D\fR\ \fIlevel\fR] \fB\-h\fR | \fB\-K\fR | \fB\-k\fR | \fB\-V\fR .PP \&\fBsudo\fR \fB\-v\fR [\fB\-AknS\fR] .if \n(BA [\fB\-a\fR\ \fIauth_type\fR] +[\fB\-D\fR\ \fIlevel\fR] [\fB\-g\fR\ \fIgroup\ name\fR|\fI#gid\fR] [\fB\-p\fR\ \fIprompt\fR] -[\fB\-u\fR\ \fIusername\fR|\fI#uid\fR] +[\fB\-u\fR\ \fIuser\ name\fR|\fI#uid\fR] .PP \&\fBsudo\fR \fB\-l[l]\fR [\fB\-AknS\fR] .if \n(BA [\fB\-a\fR\ \fIauth_type\fR] +[\fB\-D\fR\ \fIlevel\fR] [\fB\-g\fR\ \fIgroup\ name\fR|\fI#gid\fR] [\fB\-p\fR\ \fIprompt\fR] [\fB\-U\fR\ \fIuser\ name\fR] [\fB\-u\fR\ \fIuser\ name\fR|\fI#uid\fR] [\fIcommand\fR] .PP \&\fBsudo\fR [\fB\-AbEHnPS\fR] .if \n(BA [\fB\-a\fR\ \fIauth_type\fR] [\fB\-C\fR\ \fIfd\fR] +[\fB\-D\fR\ \fIlevel\fR] .if \n(LC [\fB\-c\fR\ \fIclass\fR|\fI\-\fR] [\fB\-g\fR\ \fIgroup\ name\fR|\fI#gid\fR] [\fB\-p\fR\ \fIprompt\fR] .if \n(SL [\fB\-r\fR\ \fIrole\fR] [\fB\-t\fR\ \fItype\fR] @@ -183,68 +186,68 @@ sudo, sudoedit \- execute a command as another user .if \n(BA [\fB\-a\fR\ \fIauth_type\fR] [\fB\-C\fR\ \fIfd\fR] .if \n(LC [\fB\-c\fR\ \fIclass\fR|\fI\-\fR] +[\fB\-D\fR\ \fIlevel\fR] [\fB\-g\fR\ \fIgroup\ name\fR|\fI#gid\fR] [\fB\-p\fR\ \fIprompt\fR] [\fB\-u\fR\ \fIuser\ name\fR|\fI#uid\fR] file ... .SH "DESCRIPTION" .IX Header "DESCRIPTION" \&\fBsudo\fR allows a permitted user to execute a \fIcommand\fR as the -superuser or another user, as specified in the \fIsudoers\fR file. +superuser or another user, as specified by the security policy. The real and effective uid and gid are set to match those of the -target user as specified in the passwd file and the group vector -is initialized based on the group file (unless the \fB\-P\fR option was -specified). If the invoking user is root or if the target user is -the same as the invoking user, no password is required. Otherwise, -\&\fBsudo\fR requires that users authenticate themselves with a password -by default (\s-1NOTE:\s0 in the default configuration this is the user's -password, not the root password). Once a user has been authenticated, -a time stamp is updated and the user may then use sudo without a -password for a short period of time (\f(CW\*(C`@timeout@\*(C'\fR minutes unless -overridden in \fIsudoers\fR). +target user, as specified in the password database, and the group +vector is initialized based on the group database (unless the \fB\-P\fR +option was specified). +.PP +\&\fBsudo\fR supports a plugin architecture for security policies and +input/output logging. Third parties can develop and distribute +their own policy and I/O logging modules to work seemlessly with +the \fBsudo\fR front end. The default security policy is \fIsudoers\fR, +which is configured via the file \fI@sysconfdir@/sudoers\fR, or via +\&\s-1LDAP\s0. See the \s-1PLUGINS\s0 section for more information. +.PP +The security policy determines what privileges, if any, a user has +to run \fBsudo\fR. The policy may require that users authenticate +themselves with a password or another authentication mechanism. If +authentication is required, \fBsudo\fR will exit if the user's password +is not entered within a configurable time limit. This limit is +policy-specific; the default password prompt timeout for the +\&\fIsudoers\fR security policy is +.ie \n(PT \f(CW\*(C`@password_timeout@\*(C'\fR minutes. +.el unlimited. +.PP +Security policies may support credential caching to allow the user +to run \fBsudo\fR again for a period of time without requiring +authentication. The \fIsudoers\fR policy caches credentials for +\&\f(CW\*(C`@timeout@\*(C'\fR minutes, unless overridden in \fIsudoers\fR\|(@mansectform@). By +running \fBsudo\fR with the \fB\-v\fR option, a user can update the cached +credentials without running a \fIcommand\fR. .PP When invoked as \fBsudoedit\fR, the \fB\-e\fR option (described below), is implied. .PP -\&\fBsudo\fR determines who is an authorized user by consulting the file -\&\fI@sysconfdir@/sudoers\fR. By running \fBsudo\fR with the \fB\-v\fR option, -a user can update the time stamp without running a \fIcommand\fR. If -a password is required, \fBsudo\fR will exit if the user's password -is not entered within a configurable time limit. The default -password prompt timeout is -.ie \n(PT \f(CW\*(C`@password_timeout@\*(C'\fR minutes. -.el unlimited. -.PP -If a user who is not listed in the \fIsudoers\fR file tries to run a -command via \fBsudo\fR, mail is sent to the proper authorities, as -defined at configure time or in the \fIsudoers\fR file (defaults to -\&\f(CW\*(C`@mailto@\*(C'\fR). Note that the mail will not be sent if an unauthorized -user tries to run sudo with the \fB\-l\fR or \fB\-v\fR option. This allows -users to determine for themselves whether or not they are allowed -to use \fBsudo\fR. -.PP -If \fBsudo\fR is run by root and the \f(CW\*(C`SUDO_USER\*(C'\fR environment variable -is set, \fBsudo\fR will use this value to determine who the actual -user is. This can be used by a user to log commands through sudo -even when a root shell has been invoked. It also allows the \fB\-e\fR -option 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 \f(CW\*(C`SUDO_USER\*(C'\fR. -.PP -\&\fBsudo\fR can log both successful and unsuccessful attempts (as well -as errors) to \fIsyslog\fR\|(3), a log file, or both. By default \fBsudo\fR -will log via \fIsyslog\fR\|(3) but this is changeable at configure time -or via the \fIsudoers\fR file. +Security policies may log successful and failed attempts to use +\&\fBsudo\fR. If an I/O plugin is configured, the running command's +input and output may be logged as well. .SH "OPTIONS" .IX Header "OPTIONS" \&\fBsudo\fR accepts the following command line options: .IP "\-A" 12 .IX Item "-A" Normally, if \fBsudo\fR requires a password, it will read it from the -current terminal. If the \fB\-A\fR (\fIaskpass\fR) option is specified, -a (possibly graphical) helper program is executed to read the -user's password and output the password to the standard output. If -the \f(CW\*(C`SUDO_ASKPASS\*(C'\fR environment variable is set, it specifies the -path to the helper program. Otherwise, the value specified by the -\&\fIaskpass\fR option in \fIsudoers\fR\|(@mansectform@) is used. +user's terminal. If the \fB\-A\fR (\fIaskpass\fR) option is specified, +a (possibly graphical) helper program is executed to read the user's +password and output the password to the standard output. If the +\&\f(CW\*(C`SUDO_ASKPASS\*(C'\fR environment variable is set, it specifies the path +to the helper program. Otherwise, if \fI@sysconfdir@/sudo.conf\fR +contains a line specifying the askpass program, that value will be +used. For example: +.Sp +.Vb 2 +\& # Path to askpass helper program +\& Path askpass /usr/X11R6/bin/ssh\-askpass +.Ve +.Sp +If no askpass program is available, sudo will exit with an error. .if \n(BA \{\ .IP "\-a \fItype\fR" 12 .IX Item "-a type" @@ -260,15 +263,18 @@ that support \s-1BSD\s0 authentication. 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. +Most interactive commands will fail to work properly in background +mode. .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 (\fIclose from\fR) 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 \fIclosefrom_override\fR option in -\&\fIsudoers\fR\|(@mansectform@). +three are not permitted. The security policy may restrict the +user's ability to use the \fB\-C\fR option. The \fIsudoers\fR policy only +permits use of the \fB\-C\fR option when the administrator has enabled +the \fIclosefrom_override\fR option. .if \n(LC \{\ .IP "\-c \fIclass\fR" 12 .IX Item "-c class" @@ -282,28 +288,34 @@ 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 "\-D \fIlevel\fR" 12 +.IX Item "-D level" +Enable debugging of \fBsudo\fR plugins and \fBsudo\fR itself. The \fIlevel\fR +may be a value from 1 through 9. .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@). +The \fB\-E\fR (\fIpreserve\fR \fIenvironment\fR) option indicates to the +security policy that the uses wishes to preserve their existing +environment variables. The security policy may return an error if +the \fB\-E\fR option is specified and the user does not have permission +to preserve the environment. .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: +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 security +policy. If the user is authorized by the policy, the following +steps are taken: .RS 12 .IP "1." 4 Temporary copies are made of the files to be edited with the owner set to the invoking user. .IP "2." 4 -The editor specified by the \f(CW\*(C`SUDO_EDITOR\*(C'\fR, \f(CW\*(C`VISUAL\*(C'\fR or \f(CW\*(C`EDITOR\*(C'\fR -environment variables is run to edit the temporary files. If none -of \f(CW\*(C`SUDO_EDITOR\*(C'\fR, \f(CW\*(C`VISUAL\*(C'\fR or \f(CW\*(C`EDITOR\*(C'\fR are set, the first program -listed in the \fIeditor\fR \fIsudoers\fR variable is used. +The editor specified by the policy is run to edit the temporary files. +The \fIsudoers\fR policy uses the \f(CW\*(C`SUDO_EDITOR\*(C'\fR, \f(CW\*(C`VISUAL\*(C'\fR and \f(CW\*(C`EDITOR\*(C'\fR +environment variables (in that order). If none of \f(CW\*(C`SUDO_EDITOR\*(C'\fR, +\&\f(CW\*(C`VISUAL\*(C'\fR or \f(CW\*(C`EDITOR\*(C'\fR are set, the first program listed in the +\&\fIeditor\fR \fIsudoers\fR\|(@mansectform@) option is used. .IP "3." 4 If they have been modified, the temporary files are copied back to their original location and the temporary versions are removed. @@ -319,24 +331,21 @@ temporary file. .RE .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. +Normally, \fBsudo\fR runs a command with the primary group set to the +one specified by the password 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 command with the primary group set to \fIgroup\fR +instead. 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@). The default handling of the \f(CW\*(C`HOME\*(C'\fR environment -variable depends on \fIsudoers\fR\|(@mansectform@) settings. By default, \fBsudo\fR -will set \f(CW\*(C`HOME\*(C'\fR if \fIenv_reset\fR or \fIalways_set_home\fR are set, or -if \fIset_home\fR is set and the \fB\-s\fR option is specified on the -command line. +The \fB\-H\fR (\fI\s-1HOME\s0\fR) option requests that the security policy set +the \f(CW\*(C`HOME\*(C'\fR environment variable to the home directory of the target +user (root by default) as specified by the password database. +Depending on the policy, this may be the default behavior. .IP "\-h" 12 .IX Item "-h" The \fB\-h\fR (\fIhelp\fR) option causes \fBsudo\fR to print a short help message @@ -344,51 +353,47 @@ to the standard output and exit. .IP "\-i [command]" 12 .IX Item "-i [command]" The \fB\-i\fR (\fIsimulate initial login\fR) option runs the shell specified -in the \fIpasswd\fR\|(@mansectform@) entry of the target user as a login shell. This -means that login-specific resource files such as \f(CW\*(C`.profile\*(C'\fR or -\&\f(CW\*(C`.login\*(C'\fR will be read by the shell. If a command is specified, -it is passed to the shell for execution. Otherwise, an interactive -shell is executed. \fBsudo\fR attempts to change to that user's home -directory before running the 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-1MAIL\s0\fR, \fI\s-1SHELL\s0\fR, \fI\s-1USER\s0\fR, \fI\s-1LOGNAME\s0\fR, and \fI\s-1PATH\s0\fR, as well as -the contents of \fI/etc/environment\fR on Linux and \s-1AIX\s0 systems. -All other environment variables are removed. +by the password database entry of the target user as a login shell. +This means that login-specific resource files such as \f(CW\*(C`.profile\*(C'\fR +or \f(CW\*(C`.login\*(C'\fR will be read by the shell. If a command is specified, +it is passed to the shell for execution via the shell's \fB\-c\fR option. +If no command is specified, an interactive shell is executed. +\&\fBsudo\fR attempts to change to that user's home directory before +running the shell. The security policy shall initialize the +environment to a minimal set of variables, similar to what is present +when a user logs in. .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 time stamp entirely and may not be used in conjunction -with a command or other option. This option does not require a -password. -.IP "\-k" 12 -.IX Item "-k" -When used by itself, the \fB\-k\fR (\fIkill\fR) option to \fBsudo\fR invalidates -the user's time stamp 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. +the user's cached credentials entirely and may not be used in +conjunction with a command or other option. This option does not +require a password. Not all security policies support credential +caching. +.IP "\-k [command]" 12 +.IX Item "-k [command]" +When used alone, the \fB\-k\fR (\fIkill\fR) option to \fBsudo\fR invalidates +the user's cached credentials. 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. Not all security policies support credential +caching. .Sp When used in conjunction with a command or an option that may require a password, the \fB\-k\fR option will cause \fBsudo\fR to ignore the user's -time stamp file. As a result, \fBsudo\fR will prompt for a password -(if one is required by \fIsudoers\fR) and will not update the user's -time stamp file. -.IP "\-L" 12 -.IX Item "-L" -The \fB\-L\fR (\fIlist\fR defaults) option will list the parameters that -may be set in a \fIDefaults\fR line along with a short description for -each. This option will be removed from a future version of \fBsudo\fR. +cached credentials. As a result, \fBsudo\fR will prompt for a password +(if one is required by the security policy) and will not update the +user's cached credentials. .IP "\-l[l] [\fIcommand\fR]" 12 .IX Item "-l[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 user specified by the \fB\-U\fR option) on the current host. If a -\&\fIcommand\fR is specified and is permitted by \fIsudoers\fR, the -fully-qualified path to the command is displayed along with any +\&\fIcommand\fR is specified and is permitted by the security policy, +the fully-qualified path to the command is displayed along with any command line arguments. If \fIcommand\fR is specified but not allowed, -\&\fBsudo\fR will exit with a status value of 1. If the \fB\-l\fR option is -specified with an \fBl\fR argument (i.e. \fB\-ll\fR), or if \fB\-l\fR -is specified multiple times, a longer list format is used. +\&\fBsudo\fR will exit with a status value of 1. If the \fB\-l\fR option +is specified with an \fBl\fR argument (i.e. \fB\-ll\fR), or if \fB\-l\fR is +specified multiple times, a longer list format is used. .IP "\-n" 12 .IX Item "-n" The \fB\-n\fR (\fInon-interactive\fR) option prevents \fBsudo\fR from prompting @@ -398,21 +403,21 @@ to run, \fBsudo\fR will display an error messages and exit. .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. +the \fIsudoers\fR policy 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 \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: +escapes are supported by the \fIsudoers\fR policy: .RS 12 .ie n .IP "%H" 4 .el .IP "\f(CW%H\fR" 4 .IX Item "%H" -expanded to the local host name including the domain name -(on if the machine's host name is fully qualified or the \fIfqdn\fR -\&\fIsudoers\fR option is set) +expanded to the host name including the domain name (on if +the machine's host name is fully qualified or the \fIfqdn\fR option +is set in \fIsudoers\fR\|(@mansectform@)) .ie n .IP "%h" 4 .el .IP "\f(CW%h\fR" 4 .IX Item "%h" @@ -420,13 +425,14 @@ expanded to the local host name without the domain name .ie n .IP "%p" 4 .el .IP "\f(CW%p\fR" 4 .IX Item "%p" -expanded to the user whose password is being asked for (respects the -\&\fIrootpw\fR, \fItargetpw\fR and \fIrunaspw\fR flags in \fIsudoers\fR) +expanded to the name of the user whose password is being requested +(respects the \fIrootpw\fR, \fItargetpw\fR and \fIrunaspw\fR flags in +\&\fIsudoers\fR\|(@mansectform@)) .ie n .IP "%U" 4 .el .IP "\f(CW%U\fR" 4 .IX Item "%U" -expanded to the login name of the user the command will -be run as (defaults to root) +expanded to the login name of the user the command will be run as +(defaults to root unless the \f(CW\*(C`\-u\*(C'\fR option is also specified) .ie n .IP "%u" 4 .el .IP "\f(CW%u\fR" 4 .IX Item "%u" @@ -445,7 +451,7 @@ password prompt on systems that support \s-1PAM\s0 unless the .if \n(SL \{\ .IP "\-r \fIrole\fR" 12 .IX Item "-r role" -The \fB\-r\fR (\fIrole\fR) option causes the new (SELinux) security context to +The \fB\-r\fR (\fIrole\fR) option causes the new (SELinux) security context to have the role specified by \fIrole\fR. \} .IP "\-S" 12 @@ -456,44 +462,50 @@ be followed by a newline character. .IP "\-s [command]" 12 .IX Item "-s [command]" 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@). If a command is specified, it is passed to the shell -for execution. Otherwise, an interactive shell is executed. +environment variable if it is set or the shell as specified in the +password database. If a command is specified, it is passed to the +shell for execution via the shell's \fB\-c\fR option. If no command +is specified, an interactive shell is executed. .if \n(SL \{\ .IP "\-t \fItype\fR" 12 .IX Item "-t type" -The \fB\-t\fR (\fItype\fR) option causes the new (SELinux) security context to +The \fB\-t\fR (\fItype\fR) option causes the new (SELinux) security context to have the type specified by \fItype\fR. If no type is specified, the default type is derived from the specified role. \} .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. +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. +The security policy may restrict listing other users' privileges. +The \fIsudoers\fR policy only allows root or a user with the \f(CW\*(C`ALL\*(C'\fR +privilege on the current host to use this option. .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 \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. +Security policies may restrict \fIuid\fRs to those listed in the +password database. The \fIsudoers\fR policy allows \fIuid\fRs that are +not in the password database as long as the \fItargetpw\fR option is +not set. Other security policies may not support this. .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. +The \fB\-V\fR (\fIversion\fR) option causes \fBsudo\fR to print its version +string and the version string of the security policy plugin and any +I/O plugins. If the invoking user is already root the \fB\-V\fR option +will display the arguments passed to configure when \fIsudo\fR was +built and plugins may display more verbose information such as +default options. .IP "\-v" 12 .IX Item "-v" -If given the \fB\-v\fR (\fIvalidate\fR) option, \fBsudo\fR will update the -user's time stamp, 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. +When given the \fB\-v\fR (\fIvalidate\fR) option, \fBsudo\fR will update the +user's cached credentials, authenticating the user's password if +necessary. For the \fIsudoers\fR plugin, 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. Not all +security policies support cached credentials. .IP "\-\-" 12 The \fB\-\-\fR option indicates that \fBsudo\fR should stop processing command line arguments. @@ -506,114 +518,111 @@ variables with one important exception. If the \fIsetenv\fR option 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 "PLUGINS" +.IX Header "PLUGINS" +Plugins are dynamically loaded based on the contents of the +\&\fI@sysconfdir@/sudo.conf\fR file. If no \fI@sysconfdir@/sudo.conf\fR +file is present, or it contains no \f(CW\*(C`Plugin\*(C'\fR lines, \fBsudo\fR +will use the traditional \fIsudoers\fR security policy and I/O logging, +which corresponds to the following \fI@sysconfdir@/sudo.conf\fR file. +.PP +.Vb 10 +\& # +\& # Default @sysconfdir@/sudo.conf file +\& # +\& # Format: +\& # Plugin plugin_name plugin_path +\& # Path askpass /path/to/askpass +\& # Path noexec /path/to/noexec.so +\& # +\& # The plugin_path is relative to @prefix@/libexec unless +\& # fully qualified. +\& # The plugin_name corresponds to a global symbol in the plugin +\& # that contains the plugin interface structure. +\& # +\& Plugin policy_plugin sudoers.so +\& Plugin io_plugin sudoers.so +.Ve +.PP +A \f(CW\*(C`Plugin\*(C'\fR line consists of the \f(CW\*(C`Plugin\*(C'\fR keyword, followed by the +\&\fIsymbol_name\fR and the \fIpath\fR to the shared object containing the +plugin. The \fIsymbol_name\fR is the name of the \f(CW\*(C`struct policy_plugin\*(C'\fR +or \f(CW\*(C`struct io_plugin\*(C'\fR in the plugin shared object. The \fIpath\fR +may be fully qualified or relative. If not fully qualified it is +relative to the \fI@prefix@/libexec\fR directory. Any additional +parameters after the \fIpath\fR are ignored. Lines that don't begin +with \f(CW\*(C`Plugin\*(C'\fR or \f(CW\*(C`Path\*(C'\fR are silently ignored +.PP +For more information, see the \fIsudo_plugin\fR\|(@mansectsu@) manual. +.SH "PATHS" +.IX Header "PATHS" +A \f(CW\*(C`Path\*(C'\fR line consists of the \f(CW\*(C`Path\*(C'\fR keyword, followed by the +name of the path to set and its value. E.g. +.PP +.Vb 2 +\& Path noexec @noexec_file@ +\& Path askpass /usr/X11R6/bin/ssh\-askpass +.Ve +.PP +The following plugin-agnostic paths may be set in the +\&\fI@sysconfdir@/sudo.conf\fR file. +.IP "askpass" 16 +.IX Item "askpass" +The fully qualified path to a helper program used to read the user's +password when no terminal is available. This may be the case when +\&\fBsudo\fR is executed from a graphical (as opposed to text-based) +application. The program specified by \fIaskpass\fR should display +the argument passed to it as the prompt and write the user's password +to the standard output. The value of \fIaskpass\fR may be overridden +by the \f(CW\*(C`SUDO_ASKPASS\*(C'\fR environment variable. +.IP "noexec" 16 +.IX Item "noexec" +The fully-qualified path to a shared library containing dummy +versions of the \fIexecv()\fR, \fIexecve()\fR and \fIfexecve()\fR library functions +that just return an error. This is used to implement the \fInoexec\fR +functionality on systems that support \f(CW\*(C`LD_PRELOAD\*(C'\fR or its equivalent. +Defaults to \fI@noexec_file@\fR. .SH "RETURN VALUES" .IX Header "RETURN VALUES" Upon successful execution of a program, the exit status from \fBsudo\fR will simply be the exit status of the program that was executed. .PP -Otherwise, \fBsudo\fR quits with an exit value of 1 if there is a +Otherwise, \fBsudo\fR exits with a value of 1 if there is a configuration/permission problem or if \fBsudo\fR cannot execute the given command. In the latter case the error string is printed to -stderr. If \fBsudo\fR cannot \fIstat\fR\|(2) one or more entries in the user's -\&\f(CW\*(C`PATH\*(C'\fR an error is printed on stderr. (If the directory does not -exist or if it is not really a directory, the entry is ignored and -no error is printed.) This should not happen under normal -circumstances. The most common reason for \fIstat\fR\|(2) to return -\&\*(L"permission denied\*(R" is if you are running an automounter and one -of the directories in your \f(CW\*(C`PATH\*(C'\fR is on a machine that is currently -unreachable. +the standard error. If \fBsudo\fR cannot \fIstat\fR\|(2) one or more entries +in the user's \f(CW\*(C`PATH\*(C'\fR, an error is printed on stderr. (If the +directory does not exist or if it is not really a directory, the +entry is ignored and no error is printed.) This should not happen +under normal circumstances. The most common reason for \fIstat\fR\|(2) +to return \*(L"permission denied\*(R" is if you are running an automounter +and one of the directories in your \f(CW\*(C`PATH\*(C'\fR is on a machine that is +currently unreachable. .SH "SECURITY NOTES" .IX Header "SECURITY NOTES" \&\fBsudo\fR tries to be safe when executing external commands. .PP -There are two distinct ways to deal with environment variables. -By default, the \fIenv_reset\fR \fIsudoers\fR option is enabled. -This causes commands to be executed with a minimal environment -containing \f(CW\*(C`TERM\*(C'\fR, \f(CW\*(C`PATH\*(C'\fR, \f(CW\*(C`HOME\*(C'\fR, \f(CW\*(C`SHELL\*(C'\fR, \f(CW\*(C`LOGNAME\*(C'\fR, \f(CW\*(C`USER\*(C'\fR -and \f(CW\*(C`USERNAME\*(C'\fR in addition to variables from the invoking process -permitted by the \fIenv_check\fR and \fIenv_keep\fR \fIsudoers\fR options. -There is effectively a whitelist for environment variables. -.PP -If, however, the \fIenv_reset\fR option is disabled in \fIsudoers\fR, any -variables not explicitly denied by the \fIenv_check\fR and \fIenv_delete\fR -options are inherited from the invoking process. In this case, -\&\fIenv_check\fR and \fIenv_delete\fR behave like a blacklist. Since it -is not possible to blacklist all potentially dangerous environment -variables, use of the default \fIenv_reset\fR behavior is encouraged. -.PP -In all cases, environment variables with a value beginning with -\&\f(CW\*(C`()\*(C'\fR are removed as they could be interpreted as \fBbash\fR functions. -The list of environment variables that \fBsudo\fR allows or denies is -contained in the output of \f(CW\*(C`sudo \-V\*(C'\fR when run as root. -.PP -Note that the dynamic linker on most operating systems will remove -variables that can control dynamic linking from the environment of -setuid executables, including \fBsudo\fR. Depending on the operating -system this may include \f(CW\*(C`_RLD*\*(C'\fR, \f(CW\*(C`DYLD_*\*(C'\fR, \f(CW\*(C`LD_*\*(C'\fR, \f(CW\*(C`LDR_*\*(C'\fR, -\&\f(CW\*(C`LIBPATH\*(C'\fR, \f(CW\*(C`SHLIB_PATH\*(C'\fR, and others. These type of variables are -removed from the environment before \fBsudo\fR even begins execution -and, as such, it is not possible for \fBsudo\fR to preserve them. -.PP To prevent command spoofing, \fBsudo\fR checks \*(L".\*(R" and "" (both denoting current directory) last when searching for a command in the user's \&\s-1PATH\s0 (if one or both are in the \s-1PATH\s0). Note, however, that the actual \f(CW\*(C`PATH\*(C'\fR environment variable is \fInot\fR modified and is passed unchanged to the program that \fBsudo\fR executes. .PP -\&\fBsudo\fR will check the ownership of its time stamp directory -(\fI@timedir@\fR by default) and ignore the directory's contents if -it is not owned by root or if it is writable by a user other than -root. On systems that allow non-root users to give away files via -\&\fIchown\fR\|(2), if the time stamp directory is located in a directory -writable by anyone (e.g., \fI/tmp\fR), it is possible for a user to -create the time stamp directory before \fBsudo\fR is run. However, -because \fBsudo\fR checks the ownership and mode of the directory and -its contents, the only damage that can be done is to \*(L"hide\*(R" files -by putting them in the time stamp dir. This is unlikely to happen -since once the time stamp dir is owned by root and inaccessible by -any other user, the user placing files there would be unable to get -them back out. To get around this issue you can use a directory -that is not world-writable for the time stamps (\fI/var/adm/sudo\fR for -instance) or create \fI@timedir@\fR with the appropriate owner (root) -and permissions (0700) in the system startup files. -.PP -\&\fBsudo\fR will not honor time stamps set far in the future. -Timestamps with a date greater than current_time + 2 * \f(CW\*(C`TIMEOUT\*(C'\fR -will be ignored and sudo will log and complain. This is done to -keep a user from creating his/her own time stamp with a bogus -date on systems that allow users to give away files. -.PP -On systems where the boot time is available, \fBsudo\fR will also not -honor time stamps from before the machine booted. -.PP -Since time stamp files live in the file system, they can outlive a -user's login session. As a result, a user may be able to login, -run a command with \fBsudo\fR after authenticating, logout, login -again, and run \fBsudo\fR without authenticating so long as the time -stamp file's modification time is within \f(CW\*(C`@timeout@\*(C'\fR minutes (or -whatever the timeout is set to in \fIsudoers\fR). When the \fItty_tickets\fR -option is enabled in \fIsudoers\fR, the time stamp has per-tty granularity -but still may outlive the user's session. On Linux systems where -the devpts filesystem is used, Solaris systems with the devices -filesystem, as well as other systems that utilize a devfs filesystem -that monotonically increase the inode number of devices as they are -created (such as Mac \s-1OS\s0 X), \fBsudo\fR is able to determine when a -tty-based time stamp file is stale and will ignore it. Administrators -should not rely on this feature as it is not universally available. -.PP Please note that \fBsudo\fR will normally only log the command it explicitly runs. If a user runs a command such as \f(CW\*(C`sudo su\*(C'\fR or -\&\f(CW\*(C`sudo sh\*(C'\fR, subsequent commands run from that shell will \fInot\fR be -logged, nor will \fBsudo\fR's access control affect them. The same -is true for commands that offer shell escapes (including most -editors). Because of this, care must be taken when giving users -access to commands via \fBsudo\fR to verify that the command does not -inadvertently give the user an effective root shell. For more -information, please see the \f(CW\*(C`PREVENTING SHELL ESCAPES\*(C'\fR section in -\&\fIsudoers\fR\|(@mansectform@). +\&\f(CW\*(C`sudo sh\*(C'\fR, subsequent commands run from that shell are not subject +to \fBsudo\fR's security policy. The same is true for commands that +offer shell escapes (including most editors). If I/O logging is +enabled, subsequent commands will have their input and/or output +logged, but there will not be traditional logs for those commands. +Because of this, care must be taken when giving users access to +commands via \fBsudo\fR to verify that the command does not inadvertently +give the user an effective root shell. For more information, please +see the \f(CW\*(C`PREVENTING SHELL ESCAPES\*(C'\fR section in \fIsudoers\fR\|(@mansectform@). .SH "ENVIRONMENT" .IX Header "ENVIRONMENT" -\&\fBsudo\fR utilizes the following environment variables: +\&\fBsudo\fR utilizes the following environment variables. The security +policy has control over the content of the command's environment. .ie n .IP "\*(C`EDITOR\*(C'" 16 .el .IP "\f(CW\*(C`EDITOR\*(C'\fR" 16 .IX Item "EDITOR" @@ -634,7 +643,7 @@ or when the \fB\-s\fR option is specified and \fIset_home\fR is set in .ie n .IP "\*(C`PATH\*(C'" 16 .el .IP "\f(CW\*(C`PATH\*(C'\fR" 16 .IX Item "PATH" -Set to a sane value if the \fIsecure_path\fR sudoers option is set. +May be overridden by the security policy. .ie n .IP "\*(C`SHELL\*(C'" 16 .el .IP "\f(CW\*(C`SHELL\*(C'\fR" 16 .IX Item "SHELL" @@ -683,20 +692,13 @@ Default editor to use in \fB\-e\fR (sudoedit) mode if \f(CW\*(C`SUDO_EDITOR\*(C' is not set .SH "FILES" .IX Header "FILES" -.ie n .IP "\fI@sysconfdir@/sudoers\fR" 24 -.el .IP "\fI@sysconfdir@/sudoers\fR" 24 -.IX Item "@sysconfdir@/sudoers" -List of who can run what -.ie n .IP "\fI@timedir@\fR" 24 -.el .IP "\fI@timedir@\fR" 24 -.IX Item "@timedir@" -Directory containing time stamps -.IP "\fI/etc/environment\fR" 24 -.IX Item "/etc/environment" -Initial environment for \fB\-i\fR mode on Linux and \s-1AIX\s0 +.ie n .IP "\fI@sysconfdir@/sudo.conf\fR" 24 +.el .IP "\fI@sysconfdir@/sudo.conf\fR" 24 +.IX Item "@sysconfdir@/sudo.conf" +\&\fBsudo\fR plugin and path configuration .SH "EXAMPLES" .IX Header "EXAMPLES" -Note: the following examples assume suitable \fIsudoers\fR\|(@mansectform@) entries. +Note: the following examples assume a properly configured security policy. .PP To get a file listing of an unreadable directory: .PP @@ -746,7 +748,7 @@ to make the \f(CW\*(C`cd\*(C'\fR and file redirection work. .IX Header "SEE ALSO" \&\fIgrep\fR\|(1), \fIsu\fR\|(1), \fIstat\fR\|(2), .if \n(LC \&\fIlogin_cap\fR\|(3), -\&\fIpasswd\fR\|(@mansectform@), \fIsudoers\fR\|(5), \fIvisudo\fR\|(@mansectsu@) +\&\fIpasswd\fR\|(@mansectform@), \fIsudoers\fR\|(@mansectform@), \fIsudo_plugin\fR\|(@mansectsu@), \fIsudoreplay\fR\|(@mansectsu@), \fIvisudo\fR\|(@mansectsu@) .SH "AUTHORS" .IX Header "AUTHORS" Many people have worked on \fBsudo\fR over the years; this @@ -765,9 +767,8 @@ There is no easy way to prevent a user from gaining a root shell if that user is allowed to run arbitrary commands via \fBsudo\fR. Also, many programs (such as editors) allow the user to run commands via shell escapes, thus avoiding \fBsudo\fR's checks. However, on -most systems it is possible to prevent shell escapes with \fBsudo\fR's -\&\fInoexec\fR functionality. See the \fIsudoers\fR\|(@mansectform@) manual -for details. +most systems it is possible to prevent shell escapes with the +\&\fIsudoers\fR\|(@mansectform@) module's \fInoexec\fR functionality. .PP It is not meaningful to run the \f(CW\*(C`cd\*(C'\fR command directly via sudo, e.g., .PP @@ -778,10 +779,6 @@ It is not meaningful to run the \f(CW\*(C`cd\*(C'\fR command directly via sudo, since when the command exits the parent process (your shell) will still be the same. Please see the \s-1EXAMPLES\s0 section for more information. .PP -If users have sudo \f(CW\*(C`ALL\*(C'\fR there is nothing to prevent them from -creating their own program that gives them a root shell regardless -of any '!' elements in the user specification. -.PP Running shell scripts via \fBsudo\fR can expose the same kernel bugs that make setuid shell scripts unsafe on some operating systems (if your \s-1OS\s0 has a /dev/fd/ directory, setuid shell scripts are generally safe). diff --git a/sudo.man.pl b/doc/sudo.man.pl similarity index 100% rename from sudo.man.pl rename to doc/sudo.man.pl diff --git a/doc/sudo.pod b/doc/sudo.pod new file mode 100644 index 0000000..cdc5832 --- /dev/null +++ b/doc/sudo.pod @@ -0,0 +1,700 @@ +Copyright (c) 1994-1996, 1998-2005, 2007-2011 + Todd C. Miller + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +Sponsored in part by the Defense Advanced Research Projects +Agency (DARPA) and Air Force Research Laboratory, Air Force +Materiel Command, USAF, under agreement number F39502-99-1-0512. + +=pod + +=head1 NAME + +sudo, sudoedit - execute a command as another user + +=head1 SYNOPSIS + +B S<[B<-D> I]> B<-h> | B<-K> | B<-k> | B<-V> + +B B<-v> [B<-AknS>] +S<[B<-a> I]> +S<[B<-D> I]> +S<[B<-g> I|I<#gid>]> S<[B<-p> I]> +S<[B<-u> I|I<#uid>]> + +B B<-l[l]> [B<-AknS>] +S<[B<-a> I]> +S<[B<-D> I]> +S<[B<-g> I|I<#gid>]> S<[B<-p> I]> +S<[B<-U> I]> S<[B<-u> I|I<#uid>]> [I] + +B [B<-AbEHnPS>] +S<[B<-a> I]> +S<[B<-C> I]> +S<[B<-D> I]> +S<[B<-c> I|I<->]> +S<[B<-g> I|I<#gid>]> S<[B<-p> I]> +S<[B<-r> I]> S<[B<-t> I]> +S<[B<-u> I|I<#uid>]> +S<[B=I]> S<[B<-i> | B<-s>]> [I] + +B [B<-AnS>] +S<[B<-a> I]> +S<[B<-C> I]> +S<[B<-c> I|I<->]> +S<[B<-D> I]> +S<[B<-g> I|I<#gid>]> S<[B<-p> I]> +S<[B<-u> I|I<#uid>]> file ... + +=head1 DESCRIPTION + +B allows a permitted user to execute a I as the +superuser or another user, as specified by the security policy. +The real and effective uid and gid are set to match those of the +target user, as specified in the password database, and the group +vector is initialized based on the group database (unless the B<-P> +option was specified). + +B supports a plugin architecture for security policies and +input/output logging. Third parties can develop and distribute +their own policy and I/O logging modules to work seemlessly with +the B front end. The default security policy is I, +which is configured via the file F<@sysconfdir@/sudoers>, or via +LDAP. See the L section for more information. + +The security policy determines what privileges, if any, a user has +to run B. The policy may require that users authenticate +themselves with a password or another authentication mechanism. If +authentication is required, B will exit if the user's password +is not entered within a configurable time limit. This limit is +policy-specific; the default password prompt timeout for the +I security policy is C<@password_timeout@> minutes. + +Security policies may support credential caching to allow the user +to run B again for a period of time without requiring +authentication. The I policy caches credentials for +C<@timeout@> minutes, unless overridden in L. By +running B with the B<-v> option, a user can update the cached +credentials without running a I. + +When invoked as B, the B<-e> option (described below), +is implied. + +Security policies may log successful and failed attempts to use +B. If an I/O plugin is configured, the running command's +input and output may be logged as well. + +=head1 OPTIONS + +B accepts the following command line options: + +=over 12 + +=item -A + +Normally, if B requires a password, it will read it from the +user's terminal. If the B<-A> (I) option is specified, +a (possibly graphical) helper program is executed to read the user's +password and output the password to the standard output. If the +C environment variable is set, it specifies the path +to the helper program. Otherwise, if F<@sysconfdir@/sudo.conf> +contains a line specifying the askpass program, that value will be +used. For example: + + # Path to askpass helper program + Path askpass /usr/X11R6/bin/ssh-askpass + +If no askpass program is available, sudo will exit with an error. + +=item -a I + +The B<-a> (I) option causes B to use the +specified authentication type when validating the user, as allowed +by F. The system administrator may specify a list +of sudo-specific authentication methods by adding an "auth-sudo" +entry in F. This option is only available on systems +that support BSD authentication. + +=item -b + +The B<-b> (I) option tells B to run the given +command in the background. Note that if you use the B<-b> +option you cannot use shell job control to manipulate the process. +Most interactive commands will fail to work properly in background +mode. + +=item -C I + +Normally, B will close all open file descriptors other than +standard input, standard output and standard error. The B<-C> +(I) option allows the user to specify a starting point +above the standard error (file descriptor three). Values less than +three are not permitted. The security policy may restrict the +user's ability to use the B<-C> option. The I policy only +permits use of the B<-C> option when the administrator has enabled +the I option. + +=item -c I + +The B<-c> (I) option causes B to run the specified command +with resources limited by the specified login class. The I +argument can be either a class name as defined in F, +or a single '-' character. Specifying a I of C<-> indicates +that the command should be run restricted by the default login +capabilities for the user the command is run as. If the I +argument specifies an existing user class, the command must be run +as root, or the B command must be run from a shell that is already +root. This option is only available on systems with BSD login classes. + +=item -D I + +Enable debugging of B plugins and B itself. The I +may be a value from 1 through 9. + +=item -E + +The B<-E> (I I) option indicates to the +security policy that the uses wishes to preserve their existing +environment variables. The security policy may return an error if +the B<-E> option is specified and the user does not have permission +to preserve the environment. + +=item -e + +The B<-e> (I) 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 security +policy. If the user is authorized by the policy, the following +steps are taken: + +=over 4 + +=item 1. + +Temporary copies are made of the files to be edited with the owner +set to the invoking user. + +=item 2. + +The editor specified by the policy is run to edit the temporary files. +The I policy uses the C, C and C +environment variables (in that order). If none of C, +C or C are set, the first program listed in the +I L option is used. + +=item 3. + +If they have been modified, the temporary files are copied back to +their original location and the temporary versions are removed. + +=back + +If the specified file does not exist, it will be created. Note +that unlike most commands run by B, the editor is run with +the invoking user's environment unmodified. If, for some reason, +B 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. + +=item -g I + +Normally, B runs a command with the primary group set to the +one specified by the password database for the user the command is +being run as (by default, root). The B<-g> (I) option causes +B to run the command with the primary group set to I +instead. To specify a I instead of a I, use +I<#gid>. When running commands as a I, 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. + +=item -H + +The B<-H> (I) option requests that the security policy set +the C environment variable to the home directory of the target +user (root by default) as specified by the password database. +Depending on the policy, this may be the default behavior. + +=item -h + +The B<-h> (I) option causes B to print a short help message +to the standard output and exit. + +=item -i [command] + +The B<-i> (I) option runs the shell specified +by the password database entry of the target user as a login shell. +This means that login-specific resource files such as C<.profile> +or C<.login> will be read by the shell. If a command is specified, +it is passed to the shell for execution via the shell's B<-c> option. +If no command is specified, an interactive shell is executed. +B attempts to change to that user's home directory before +running the shell. The security policy shall initialize the +environment to a minimal set of variables, similar to what is present +when a user logs in. + +=item -K + +The B<-K> (sure I) option is like B<-k> except that it removes +the user's cached credentials entirely and may not be used in +conjunction with a command or other option. This option does not +require a password. Not all security policies support credential +caching. + +=item -k [command] + +When used alone, the B<-k> (I) option to B invalidates +the user's cached credentials. The next time B is run a +password will be required. This option does not require a password +and was added to allow a user to revoke B permissions from a +.logout file. Not all security policies support credential +caching. + +When used in conjunction with a command or an option that may require +a password, the B<-k> option will cause B to ignore the user's +cached credentials. As a result, B will prompt for a password +(if one is required by the security policy) and will not update the +user's cached credentials. + +=item -l[l] [I] + +If no I is specified, the B<-l> (I) option will list +the allowed (and forbidden) commands for the invoking user (or the +user specified by the B<-U> option) on the current host. If a +I is specified and is permitted by the security policy, +the fully-qualified path to the command is displayed along with any +command line arguments. If I is specified but not allowed, +B will exit with a status value of 1. If the B<-l> option +is specified with an B argument (i.e. B<-ll>), or if B<-l> is +specified multiple times, a longer list format is used. + +=item -n + +The B<-n> (I) option prevents B from prompting +the user for a password. If a password is required for the command +to run, B will display an error messages and exit. + +=item -P + +The B<-P> (I I) option causes B to +preserve the invoking user's group vector unaltered. By default, +the I policy 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. + +=item -p I + +The B<-p> (I) option allows you to override the default +password prompt and use a custom one. The following percent (`C<%>') +escapes are supported by the I policy: + +=over 4 + +=item C<%H> + +expanded to the host name including the domain name (on if +the machine's host name is fully qualified or the I option +is set in L) + +=item C<%h> + +expanded to the local host name without the domain name + +=item C<%p> + +expanded to the name of the user whose password is being requested +(respects the I, I and I flags in +L) + +=item C<%U> + +expanded to the login name of the user the command will be run as +(defaults to root unless the C<-u> option is also specified) + +=item C<%u> + +expanded to the invoking user's login name + +=item C<%%> + +two consecutive C<%> characters are collapsed into a single C<%> character + +=back + +The prompt specified by the B<-p> option will override the system +password prompt on systems that support PAM unless the +I flag is disabled in I. + +=item -r I + +The B<-r> (I) option causes the new (SELinux) security context to +have the role specified by I. + +=item -S + +The B<-S> (I) option causes B to read the password from +the standard input instead of the terminal device. The password must +be followed by a newline character. + +=item -s [command] + +The B<-s> (I) option runs the shell specified by the I +environment variable if it is set or the shell as specified in the +password database. If a command is specified, it is passed to the +shell for execution via the shell's B<-c> option. If no command +is specified, an interactive shell is executed. + +=item -t I + +The B<-t> (I) option causes the new (SELinux) security context to +have the type specified by I. If no type is specified, the default +type is derived from the specified role. + +=item -U I + +The B<-U> (I) option is used in conjunction with the +B<-l> option to specify the user whose privileges should be listed. +The security policy may restrict listing other users' privileges. +The I policy only allows root or a user with the C +privilege on the current host to use this option. + +=item -u I + +The B<-u> (I) option causes B to run the specified +command as a user other than I. To specify a I instead +of a I, use I<#uid>. When running commands as a I, +many shells require that the '#' be escaped with a backslash ('\'). +Security policies may restrict Is to those listed in the +password database. The I policy allows Is that are +not in the password database as long as the I option is +not set. Other security policies may not support this. + +=item -V + +The B<-V> (I) option causes B to print its version +string and the version string of the security policy plugin and any +I/O plugins. If the invoking user is already root the B<-V> option +will display the arguments passed to configure when I was +built and plugins may display more verbose information such as +default options. + +=item -v + +When given the B<-v> (I) option, B will update the +user's cached credentials, authenticating the user's password if +necessary. For the I plugin, this extends the B +timeout for another C<@timeout@> minutes (or whatever the timeout +is set to in I) but does not run a command. Not all +security policies support cached credentials. + +=item -- + +The B<--> option indicates that B should stop processing command +line arguments. + +=back + +Environment variables to be set for the command may also be passed +on the command line in the form of B=I, e.g. +B=I. Variables passed on the +command line are subject to the same restrictions as normal environment +variables with one important exception. If the I option +is set in I, the command to be run has the C tag +set or the command matched is C, the user may set variables +that would overwise be forbidden. See L for more information. + +=head1 PLUGINS + +Plugins are dynamically loaded based on the contents of the +F<@sysconfdir@/sudo.conf> file. If no F<@sysconfdir@/sudo.conf> +file is present, or it contains no C lines, B +will use the traditional I security policy and I/O logging, +which corresponds to the following F<@sysconfdir@/sudo.conf> file. + + # + # Default @sysconfdir@/sudo.conf file + # + # Format: + # Plugin plugin_name plugin_path + # Path askpass /path/to/askpass + # Path noexec /path/to/noexec.so + # + # The plugin_path is relative to @prefix@/libexec unless + # fully qualified. + # The plugin_name corresponds to a global symbol in the plugin + # that contains the plugin interface structure. + # + Plugin policy_plugin sudoers.so + Plugin io_plugin sudoers.so + +A C line consists of the C keyword, followed by the +I and the I to the shared object containing the +plugin. The I is the name of the C +or C in the plugin shared object. The I +may be fully qualified or relative. If not fully qualified it is +relative to the F<@prefix@/libexec> directory. Any additional +parameters after the I are ignored. Lines that don't begin +with C or C are silently ignored + +For more information, see the L manual. + +=head1 PATHS + +A C line consists of the C keyword, followed by the +name of the path to set and its value. E.g. + + Path noexec @noexec_file@ + Path askpass /usr/X11R6/bin/ssh-askpass + +The following plugin-agnostic paths may be set in the +F<@sysconfdir@/sudo.conf> file. + +=over 16 + +=item askpass + +The fully qualified path to a helper program used to read the user's +password when no terminal is available. This may be the case when +B is executed from a graphical (as opposed to text-based) +application. The program specified by I should display +the argument passed to it as the prompt and write the user's password +to the standard output. The value of I may be overridden +by the C environment variable. + +=item noexec + +The fully-qualified path to a shared library containing dummy +versions of the execv(), execve() and fexecve() library functions +that just return an error. This is used to implement the I +functionality on systems that support C or its equivalent. +Defaults to F<@noexec_file@>. + +=back + +=head1 RETURN VALUES + +Upon successful execution of a program, the exit status from B +will simply be the exit status of the program that was executed. + +Otherwise, B exits with a value of 1 if there is a +configuration/permission problem or if B cannot execute the +given command. In the latter case the error string is printed to +the standard error. If B cannot L one or more entries +in the user's C, an error is printed on stderr. (If the +directory does not exist or if it is not really a directory, the +entry is ignored and no error is printed.) This should not happen +under normal circumstances. The most common reason for L +to return "permission denied" is if you are running an automounter +and one of the directories in your C is on a machine that is +currently unreachable. + +=head1 SECURITY NOTES + +B tries to be safe when executing external commands. + +To prevent command spoofing, B checks "." and "" (both denoting +current directory) last when searching for a command in the user's +PATH (if one or both are in the PATH). Note, however, that the +actual C environment variable is I modified and is passed +unchanged to the program that B executes. + +Please note that B will normally only log the command it +explicitly runs. If a user runs a command such as C or +C, subsequent commands run from that shell are not subject +to B's security policy. The same is true for commands that +offer shell escapes (including most editors). If I/O logging is +enabled, subsequent commands will have their input and/or output +logged, but there will not be traditional logs for those commands. +Because of this, care must be taken when giving users access to +commands via B to verify that the command does not inadvertently +give the user an effective root shell. For more information, please +see the C section in L. + +=head1 ENVIRONMENT + +B utilizes the following environment variables. The security +policy has control over the content of the command's environment. + +=over 16 + +=item C + +Default editor to use in B<-e> (sudoedit) mode if neither C +nor C is set + +=item C + +In B<-i> mode or when I is enabled in I, set +to the mail spool of the target user + +=item C + +Set to the home directory of the target user if B<-i> or B<-H> are +specified, I or I are set in I, +or when the B<-s> option is specified and I is set in +I + +=item C + +May be overridden by the security policy. + +=item C + +Used to determine shell to run with C<-s> option + +=item C + +Specifies the path to a helper program used to read the password +if no terminal is available or if the C<-A> option is specified. + +=item C + +Set to the command run by sudo + +=item C + +Default editor to use in B<-e> (sudoedit) mode + +=item C + +Set to the group ID of the user who invoked sudo + +=item C + +Used as the default password prompt + +=item C + +If set, C will be set to its value for the program being run + +=item C + +Set to the user ID of the user who invoked sudo + +=item C + +Set to the login of the user who invoked sudo + +=item C + +Set to the target user (root unless the B<-u> option is specified) + +=item C + +Default editor to use in B<-e> (sudoedit) mode if C +is not set + +=back + +=head1 FILES + +=over 24 + +=item F<@sysconfdir@/sudo.conf> + +B plugin and path configuration + +=back + +=head1 EXAMPLES + +Note: the following examples assume a properly configured security policy. + +To get a file listing of an unreadable directory: + + $ sudo ls /usr/local/protected + +To list the home directory of user yaz on a machine where the +file system holding ~yaz is not exported as root: + + $ sudo -u yaz ls ~yaz + +To edit the F file as user www: + + $ sudo -u www vi ~www/htdocs/index.html + +To view system logs only accessible to root and users in the adm group: + + $ sudo -g adm view /var/log/syslog + +To run an editor as jim with a different primary group: + + $ sudo -u jim -g audio vi ~jim/sound.txt + +To shutdown a machine: + + $ sudo shutdown -r +15 "quick reboot" + +To make a usage listing of the directories in the /home +partition. Note that this runs the commands in a sub-shell +to make the C and file redirection work. + + $ sudo sh -c "cd /home ; du -s * | sort -rn > USAGE" + +=head1 SEE ALSO + +L, L, L, +L, +L, L, L, L, L + +=head1 AUTHORS + +Many people have worked on B over the years; this +version consists of code written primarily by: + + Todd C. Miller + +See the HISTORY file in the B distribution or visit +http://www.sudo.ws/sudo/history.html for a short history +of B. + +=head1 CAVEATS + +There is no easy way to prevent a user from gaining a root shell +if that user is allowed to run arbitrary commands via B. +Also, many programs (such as editors) allow the user to run commands +via shell escapes, thus avoiding B's checks. However, on +most systems it is possible to prevent shell escapes with the +L module's I functionality. + +It is not meaningful to run the C command directly via sudo, e.g., + + $ sudo cd /usr/local/protected + +since when the command exits the parent process (your shell) will +still be the same. Please see the EXAMPLES section for more information. + +Running shell scripts via B can expose the same kernel bugs that +make setuid shell scripts unsafe on some operating systems (if your OS +has a /dev/fd/ directory, setuid shell scripts are generally safe). + +=head1 BUGS + +If you feel you have found a bug in B, please submit a bug report +at http://www.sudo.ws/sudo/bugs/ + +=head1 SUPPORT + +Limited free support is available via the sudo-users mailing list, +see http://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or +search the archives. + +=head1 DISCLAIMER + +B is provided ``AS IS'' and any express or implied warranties, +including, but not limited to, the implied warranties of merchantability +and fitness for a particular purpose are disclaimed. See the LICENSE +file distributed with B or http://www.sudo.ws/sudo/license.html +for complete details. diff --git a/doc/sudo_plugin.cat b/doc/sudo_plugin.cat new file mode 100644 index 0000000..a486f02 --- /dev/null +++ b/doc/sudo_plugin.cat @@ -0,0 +1,1033 @@ +SUDO_PLUGIN(1m) MAINTENANCE COMMANDS SUDO_PLUGIN(1m) + + + +NNAAMMEE + sudo_plugin - Sudo Plugin API + +DDEESSCCRRIIPPTTIIOONN + Starting with version 1.8, ssuuddoo supports a plugin API for policy and + session logging. By default, the _s_u_d_o_e_r_s policy plugin and an + associated I/O logging plugin are used. Via the plugin API, ssuuddoo can + be configured to use alternate policy and/or I/O logging plugins + provided by third parties. The plugins to be used are specified via + the _/_e_t_c_/_s_u_d_o_._c_o_n_f file. + + The API is versioned with a major and minor number. The minor version + number is incremented when additions are made. The major number is + incremented when incompatible changes are made. A plugin should be + check the version passed to it and make sure that the major version + matches. + + The plugin API is defined by the sudo_plugin.h header file. + + TThhee ssuuddoo..ccoonnff FFiillee + The _/_e_t_c_/_s_u_d_o_._c_o_n_f file contains plugin configuration directives. + Currently, the only supported keyword is the Plugin directive, which + causes a plugin plugin to be loaded. + + A Plugin line consists of the Plugin keyword, followed by the + _s_y_m_b_o_l___n_a_m_e and the _p_a_t_h to the shared object containing the plugin. + The _s_y_m_b_o_l___n_a_m_e is the name of the struct policy_plugin or struct + io_plugin in the plugin shared object. The _p_a_t_h may be fully qualified + or relative. If not fully qualified it is relative to the + _/_u_s_r_/_l_o_c_a_l_/_l_i_b_e_x_e_c directory. Any additional parameters after the _p_a_t_h + are ignored. Lines that don't begin with Plugin or Path are silently + ignored. + + The same shared object may contain multiple plugins, each with a + different symbol name. The shared object file must be owned by uid 0 + and only writable by its owner. Because of ambiguities that arise from + composite policies, only a single policy plugin may be specified. This + limitation does not apply to I/O plugins. + + # + # Default /etc/sudo.conf file + # + # Format: + # Plugin plugin_name plugin_path + # Path askpass /path/to/askpass + # + # The plugin_path is relative to /usr/local/libexec unless + # fully qualified. + # The plugin_name corresponds to a global symbol in the plugin + # that contains the plugin interface structure. + # + Plugin sudoers_policy sudoers.so + Plugin sudoers_io sudoers.so + + PPoolliiccyy PPlluuggiinn AAPPII + A policy plugin must declare and populate a policy_plugin struct in the + global scope. This structure contains pointers to the functions that + implement the ssuuddoo policy checks. The name of the symbol should be + specified in _/_e_t_c_/_s_u_d_o_._c_o_n_f along with a path to the plugin so that + ssuuddoo can load it. + + struct policy_plugin { + #define SUDO_POLICY_PLUGIN 1 + unsigned int type; /* always SUDO_POLICY_PLUGIN */ + unsigned int version; /* always SUDO_API_VERSION */ + int (*open)(unsigned int version, sudo_conv_t conversation, + sudo_printf_t plugin_printf, char * const settings[], + char * const user_info[], char * const user_env[]); + void (*close)(int exit_status, int error); + int (*show_version)(int verbose); + int (*check_policy)(int argc, char * const argv[], + char *env_add[], char **command_info[], + char **argv_out[], char **user_env_out[]); + int (*list)(int argc, char * const argv[], int verbose, + const char *list_user); + int (*validate)(void); + void (*invalidate)(int remove); + int (*init_session)(struct passwd *pwd); + }; + + The policy_plugin struct has the following fields: + + type + The type field should always be set to SUDO_POLICY_PLUGIN. + + version + The version field should be set to SUDO_API_VERSION. + + This allows ssuuddoo to determine the API version the plugin was built + against. + + open + int (*open)(unsigned int version, sudo_conv_t conversation, + sudo_printf_t plugin_printf, char * const settings[], + char * const user_info[], char * const user_env[]); + + Returns 1 on success, 0 on failure, -1 if a general error occurred, + or -2 if there was a usage error. In the latter case, ssuuddoo will + print a usage message before it exits. If an error occurs, the + plugin may optionally call the conversation or plugin_printf + function with SUDO_CONF_ERROR_MSG to present additional error + information to the user. + + The function arguments are as follows: + + version + The version passed in by ssuuddoo allows the plugin to determine + the major and minor version number of the plugin API supported + by ssuuddoo. + + conversation + A pointer to the conversation function that can be used by the + plugin to interact with the user (see below). Returns 0 on + success and -1 on failure. + + plugin_printf + A pointer to a printf-style function that may be used to + display informational or error messages (see below). Returns + the number of characters printed on success and -1 on failure. + + settings + A vector of user-supplied ssuuddoo settings in the form of + "name=value" strings. The vector is terminated by a NULL + pointer. These settings correspond to flags the user specified + when running ssuuddoo. As such, they will only be present when the + corresponding flag has been specified on the command line. + + When parsing _s_e_t_t_i_n_g_s, the plugin should split on the ffiirrsstt + equal sign ('=') since the _n_a_m_e field will never include one + itself but the _v_a_l_u_e might. + + debug_level=number + A numeric debug level, from 1-9, if specified via the -D + flag. + + runas_user=string + The user name or uid to to run the command as, if specified + via the -u flag. + + runas_group=string + The group name or gid to to run the command as, if + specified via the -g flag. + + prompt=string + The prompt to use when requesting a password, if specified + via the -p flag. + + set_home=bool + Set to true if the user specified the -H flag. If true, + set the HOME environment variable to the target user's home + directory. + + preserve_environment=bool + Set to true if the user specified the -E flag, indicating + that the user wishes to preserve the environment. + + run_shell=bool + Set to true if the user specified the -s flag, indicating + that the user wishes to run a shell. + + login_shell=bool + Set to true if the user specified the -i flag, indicating + that the user wishes to run a login shell. + + implied_shell=bool + If the user does not specify a program on the command line, + ssuuddoo will pass the plugin the path to the user's shell and + set _i_m_p_l_i_e_d___s_h_e_l_l to true. This allows ssuuddoo with no + arguments to be used similarly to _s_u(1). If the plugin + does not to support this usage, it may return a value of -2 + from the check_policy function, which will cause ssuuddoo to + print a usage message and exit. + + preserve_groups=bool + Set to true if the user specified the -P flag, indicating + that the user wishes to preserve the group vector instead + of setting it based on the runas user. + + ignore_ticket=bool + Set to true if the user specified the -k flag along with a + command, indicating that the user wishes to ignore any + cached authentication credentials. + + noninteractive=bool + Set to true if the user specified the -n flag, indicating + that ssuuddoo should operate in non-interactive mode. The + plugin may reject a command run in non-interactive mode if + user interaction is required. + + login_class=string + BSD login class to use when setting resource limits and + nice value, if specified by the -c flag. + + selinux_role=string + SELinux role to use when executing the command, if + specified by the -r flag. + + selinux_type=string + SELinux type to use when executing the command, if + specified by the -t flag. + + bsdauth_type=string + Authentication type, if specified by the -a flag, to use on + systems where BSD authentication is supported. + + network_addrs=list + A space-separated list of IP network addresses and netmasks + in the form "addr/netmask", e.g. + "192.168.1.2/255.255.255.0". The address and netmask pairs + may be either IPv4 or IPv6, depending on what the operating + system supports. If the address contains a colon (':'), it + is an IPv6 address, else it is IPv4. + + progname=string + The command name that sudo was run as, typically "sudo" or + "sudoedit". + + sudoedit=bool + Set to true when the -e flag is is specified or if invoked + as ssuuddooeeddiitt. The plugin shall substitute an editor into + _a_r_g_v in the _c_h_e_c_k___p_o_l_i_c_y function or return -2 with a usage + error if the plugin does not support _s_u_d_o_e_d_i_t. For more + information, see the _c_h_e_c_k___p_o_l_i_c_y section. + + closefrom=number + If specified, the user has requested via the -C flag that + ssuuddoo close all files descriptors with a value of _n_u_m_b_e_r or + higher. The plugin may optionally pass this, or another + value, back in the _c_o_m_m_a_n_d___i_n_f_o list. + + Additional settings may be added in the future so the plugin + should silently ignore settings that it does not recognize. + + user_info + A vector of information about the user running the command in + the form of "name=value" strings. The vector is terminated by + a NULL pointer. + + When parsing _u_s_e_r___i_n_f_o, the plugin should split on the ffiirrsstt + equal sign ('=') since the _n_a_m_e field will never include one + itself but the _v_a_l_u_e might. + + user=string + The name of the user invoking ssuuddoo. + + uid=uid_t + The real user ID of the user invoking ssuuddoo. + + gid=gid_t + The real group ID of the user invoking ssuuddoo. + + groups=list + The user's supplementary group list formatted as a string + of comma-separated group IDs. + + cwd=string + The user's current working directory. + + tty=string + The path to the user's terminal device. If the user has no + terminal device associated with the session, the value will + be empty, as in tty=. + + host=string + The local machine's hostname as returned by the + gethostname() system call. + + lines=int + The number of lines the user's terminal supports. If there + is no terminal device available, a default value of 24 is + used. + + cols=int + The number of columns the user's terminal supports. If + there is no terminal device available, a default value of + 80 is used. + + user_env + The user's environment in the form of a NULL-terminated vector + of "name=value" strings. + + When parsing _u_s_e_r___e_n_v, the plugin should split on the ffiirrsstt + equal sign ('=') since the _n_a_m_e field will never include one + itself but the _v_a_l_u_e might. + + close + void (*close)(int exit_status, int error); + + The close function is called when the command being run by ssuuddoo + finishes. + + The function arguments are as follows: + + exit_status + The command's exit status, as returned by the _w_a_i_t(2) system + call. The value of exit_status is undefined if error is non- + zero. + + error + If the command could not be executed, this is set to the value + of errno set by the _e_x_e_c_v_e(2) system call. The plugin is + responsible for displaying error information via the + conversation or plugin_printf function. If the command was + successfully executed, the value of error is 0. + + show_version + int (*show_version)(int verbose); + + The show_version function is called by ssuuddoo when the user specifies + the -V option. The plugin may display its version information to + the user via the conversation or plugin_printf function using + SUDO_CONV_INFO_MSG. If the user requests detailed version + information, the verbose flag will be set. + + check_policy + int (*check_policy)(int argc, char * const argv[] + char *env_add[], char **command_info[], + char **argv_out[], char **user_env_out[]); + + The _c_h_e_c_k___p_o_l_i_c_y function is called by ssuuddoo to determine whether + the user is allowed to run the specified commands. + + If the _s_u_d_o_e_d_i_t option was enabled in the _s_e_t_t_i_n_g_s array passed to + the _o_p_e_n function, the user has requested _s_u_d_o_e_d_i_t mode. _s_u_d_o_e_d_i_t + is a mechanism for editing one or more files where an editor is run + with the user's credentials instead of with elevated privileges. + ssuuddoo achieves this by creating user-writable temporary copies of + the files to be edited and then overwriting the originals with the + temporary copies after editing is complete. If the plugin supports + ssuuddooeeddiitt, it should choose the editor to be used, potentially from + a variable in the user's environment, such as EDITOR, and include + it in _a_r_g_v___o_u_t (note that environment variables may include command + line flags). The files to be edited should be copied from _a_r_g_v + into _a_r_g_v___o_u_t, separated from the editor and its arguments by a + "--" element. The "--" will be removed by ssuuddoo before the editor + is executed. The plugin should also set _s_u_d_o_e_d_i_t_=_t_r_u_e in the + _c_o_m_m_a_n_d___i_n_f_o list. + + The _c_h_e_c_k___p_o_l_i_c_y function returns 1 if the command is allowed, 0 if + not allowed, -1 for a general error, or -2 for a usage error or if + ssuuddooeeddiitt was specified but is unsupported by the plugin. In the + latter case, ssuuddoo will print a usage message before it exits. If + an error occurs, the plugin may optionally call the conversation or + plugin_printf function with SUDO_CONF_ERROR_MSG to present + additional error information to the user. + + The function arguments are as follows: + + argc + The number of elements in _a_r_g_v, not counting the final NULL + pointer. + + argv + The argument vector describing the command the user wishes to + run, in the same form as what would be passed to the _e_x_e_c_v_e_(_) + system call. The vector is terminated by a NULL pointer. + + env_add + Additional environment variables specified by the user on the + command line in the form of a NULL-terminated vector of + "name=value" strings. The plugin may reject the command if one + or more variables are not allowed to be set, or it may silently + ignore such variables. + + When parsing _e_n_v___a_d_d, the plugin should split on the ffiirrsstt + equal sign ('=') since the _n_a_m_e field will never include one + itself but the _v_a_l_u_e might. + + command_info + Information about the command being run in the form of + "name=value" strings. These values are used by ssuuddoo to set the + execution environment when running a command. The plugin is + responsible for creating and populating the vector, which must + be terminated with a NULL pointer. The following values are + recognized by ssuuddoo: + + command=string + Fully qualified path to the command to be executed. + + runas_uid=uid + User ID to run the command as. + + runas_euid=uid + Effective user ID to run the command as. If not specified, + the value of _r_u_n_a_s___u_i_d is used. + + runas_gid=gid + Group ID to run the command as. + + runas_egid=gid + Effective group ID to run the command as. If not + specified, the value of _r_u_n_a_s___g_i_d is used. + + runas_groups=list + The supplementary group vector to use for the command in + the form of a comma-separated list of group IDs. If + _p_r_e_s_e_r_v_e___g_r_o_u_p_s is set, this option is ignored. + + login_class=string + BSD login class to use when setting resource limits and + nice value (optional). This option is only set on systems + that support login classes. + + preserve_groups=bool + If set, ssuuddoo will preserve the user's group vector instead + of initializing the group vector based on runas_user. + + cwd=string + The current working directory to change to when executing + the command. + + noexec=bool + If set, prevent the command from executing other programs. + + chroot=string + The root directory to use when running the command. + + nice=int + Nice value (priority) to use when executing the command. + The nice value, if specified, overrides the priority + associated with the _l_o_g_i_n___c_l_a_s_s on BSD systems. + + umask=octal + The file creation mask to use when executing the command. + + selinux_role=string + SELinux role to use when executing the command. + + selinux_type=string + SELinux type to use when executing the command. + + timeout=int + Command timeout. If non-zero then when the timeout expires + the command will be killed. + + sudoedit=bool + Set to true when in _s_u_d_o_e_d_i_t mode. The plugin may enable + _s_u_d_o_e_d_i_t mode even if ssuuddoo was not invoked as ssuuddooeeddiitt. + This allows the plugin to perform command substitution and + transparently enable _s_u_d_o_e_d_i_t when the user attempts to run + an editor. + + closefrom=number + If specified, ssuuddoo will close all files descriptors with a + value of _n_u_m_b_e_r or higher. + + iolog_compress=bool + Set to true if the I/O logging plugins, if any, should + compress the log data. This is a hint to the I/O logging + plugin which may choose to ignore it. + + iolog_path=string + Fully qualified path to the file or directory in which I/O + log is to be stored. This is a hint to the I/O logging + plugin which may choose to ignore it. If no I/O logging + plugin is loaded, this setting has no effect. + + iolog_stdin=bool + Set to true if the I/O logging plugins, if any, should log + the standard input if it is not connected to a terminal + device. This is a hint to the I/O logging plugin which may + choose to ignore it. + + iolog_stdout=bool + Set to true if the I/O logging plugins, if any, should log + the standard output if it is not connected to a terminal + device. This is a hint to the I/O logging plugin which may + choose to ignore it. + + iolog_stderr=bool + Set to true if the I/O logging plugins, if any, should log + the standard error if it is not connected to a terminal + device. This is a hint to the I/O logging plugin which may + choose to ignore it. + + iolog_ttyin=bool + Set to true if the I/O logging plugins, if any, should log + all terminal input. This only includes input typed by the + user and not from a pipe or redirected from a file. This + is a hint to the I/O logging plugin which may choose to + ignore it. + + iolog_ttyout=bool + Set to true if the I/O logging plugins, if any, should log + all terminal output. This only includes output to the + screen, not output to a pipe or file. This is a hint to + the I/O logging plugin which may choose to ignore it. + + use_pty=bool + Allocate a pseudo-tty to run the command in, regardless of + whether or not I/O logging is in use. By default, ssuuddoo + will only run the command in a pty when an I/O log plugin + is loaded. + + set_utmp=bool + Create a utmp (or utmpx) entry when a pseudo-tty is + allocated. By default, the new entry will be a copy of the + user's existing utmp entry (if any), with the tty, time, + type and pid fields updated. + + utmp_user=string + User name to use when constructing a new utmp (or utmpx) + entry when _s_e_t___u_t_m_p is enabled. This option can be used to + set the user field in the utmp entry to the user the + command runs as rather than the invoking user. If not set, + ssuuddoo will base the new entry on the invoking user's + existing entry. + + Unsupported values will be ignored. + + argv_out + The NULL-terminated argument vector to pass to the _e_x_e_c_v_e_(_) + system call when executing the command. The plugin is + responsible for allocating and populating the vector. + + user_env_out + The NULL-terminated environment vector to use when executing + the command. The plugin is responsible for allocating and + populating the vector. + + list + int (*list)(int verbose, const char *list_user, + int argc, char * const argv[]); + + List available privileges for the invoking user. Returns 1 on + success, 0 on failure and -1 on error. On error, the plugin may + optionally call the conversation or plugin_printf function with + SUDO_CONF_ERROR_MSG to present additional error information to the + user. + + Privileges should be output via the conversation or plugin_printf + function using SUDO_CONV_INFO_MSG. + + verbose + Flag indicating whether to list in verbose mode or not. + + list_user + The name of a different user to list privileges for if the + policy allows it. If NULL, the plugin should list the + privileges of the invoking user. + + argc + The number of elements in _a_r_g_v, not counting the final NULL + pointer. + + argv + If non-NULL, an argument vector describing a command the user + wishes to check against the policy in the same form as what + would be passed to the _e_x_e_c_v_e_(_) system call. If the command is + permitted by the policy, the fully-qualified path to the + command should be displayed along with any command line + arguments. + + validate + int (*validate)(void); + + The validate function is called when ssuuddoo is run with the -v flag. + For policy plugins such as _s_u_d_o_e_r_s that cache authentication + credentials, this function will validate and cache the credentials. + + The validate function should be NULL if the plugin does not support + credential caching. + + Returns 1 on success, 0 on failure and -1 on error. On error, the + plugin may optionally call the conversation or plugin_printf + function with SUDO_CONF_ERROR_MSG to present additional error + information to the user. + + invalidate + void (*invalidate)(int remove); + + The invalidate function is called when ssuuddoo is called with the -k + or -K flag. For policy plugins such as _s_u_d_o_e_r_s that cache + authentication credentials, this function will invalidate the + credentials. If the _r_e_m_o_v_e flag is set, the plugin may remove the + credentials instead of simply invalidating them. + + The invalidate function should be NULL if the plugin does not + support credential caching. + + init_session + int (*init_session)(struct passwd *pwd); + + The init_session function is called when ssuuddoo sets up the execution + environment for the command, immediately before the contents of the + _c_o_m_m_a_n_d___i_n_f_o list are applied (before the uid changes). This can + be used to do session setup that is not supported by _c_o_m_m_a_n_d___i_n_f_o, + such as opening the PAM session. + + The _p_w_d argument points to a passwd struct for the user the command + will be run as if the uid the command will run as was found in the + password database, otherwise it will be NULL. + + Returns 1 on success, 0 on failure and -1 on error. On error, the + plugin may optionally call the conversation or plugin_printf + function with SUDO_CONF_ERROR_MSG to present additional error + information to the user. + + _V_e_r_s_i_o_n _m_a_c_r_o_s + + #define SUDO_API_VERSION_GET_MAJOR(v) ((v) >> 16) + #define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffff) + #define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \ + *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \ + } while(0) + #define SUDO_VERSION_SET_MINOR(vp, n) do { \ + *(vp) = (*(vp) & 0xffff0000) | (n); \ + } while(0) + + #define SUDO_API_VERSION_MAJOR 1 + #define SUDO_API_VERSION_MINOR 0 + #define SUDO_API_VERSION ((SUDO_API_VERSION_MAJOR << 16) | \ + SUDO_API_VERSION_MINOR) + + II//OO PPlluuggiinn AAPPII + struct io_plugin { + #define SUDO_IO_PLUGIN 2 + unsigned int type; /* always SUDO_IO_PLUGIN */ + unsigned int version; /* always SUDO_API_VERSION */ + int (*open)(unsigned int version, sudo_conv_t conversation + sudo_printf_t plugin_printf, char * const settings[], + char * const user_info[], int argc, char * const argv[], + char * const user_env[]); + void (*close)(int exit_status, int error); /* wait status or error */ + int (*show_version)(int verbose); + int (*log_ttyin)(const char *buf, unsigned int len); + int (*log_ttyout)(const char *buf, unsigned int len); + int (*log_stdin)(const char *buf, unsigned int len); + int (*log_stdout)(const char *buf, unsigned int len); + int (*log_stderr)(const char *buf, unsigned int len); + }; + + When an I/O plugin is loaded, ssuuddoo runs the command in a pseudo-tty. + This makes it possible to log the input and output from the user's + session. If any of the standard input, standard output or standard + error do not correspond to a tty, ssuuddoo will open a pipe to capture the + I/O for logging before passing it on. + + The log_ttyin function receives the raw user input from the terminal + device (note that this will include input even when echo is disabled, + such as when a password is read). The log_ttyout function receives + output from the pseudo-tty that is suitable for replaying the user's + session at a later time. The log_stdin, log_stdout and log_stderr + functions are only called if the standard input, standard output or + standard error respectively correspond to something other than a tty. + + Any of the logging functions may be set to the NULL pointer if no + logging is to be performed. If the open function returns 0, no I/O + will be sent to the plugin. + + The io_plugin struct has the following fields: + + type + The type field should always be set to SUDO_IO_PLUGIN + + version + The version field should be set to SUDO_API_VERSION. + + This allows ssuuddoo to determine the API version the plugin was built + against. + + open + int (*open)(unsigned int version, sudo_conv_t conversation + sudo_printf_t plugin_printf, char * const settings[], + char * const user_info[], int argc, char * const argv[], + char * const user_env[]); + + The _o_p_e_n function is run before the _l_o_g___i_n_p_u_t, _l_o_g___o_u_t_p_u_t or + _s_h_o_w___v_e_r_s_i_o_n functions are called. It is only called if the + version is being requested or the _c_h_e_c_k___p_o_l_i_c_y function has + returned successfully. It returns 1 on success, 0 on failure, -1 + if a general error occurred, or -2 if there was a usage error. In + the latter case, ssuuddoo will print a usage message before it exits. + If an error occurs, the plugin may optionally call the conversation + or plugin_printf function with SUDO_CONF_ERROR_MSG to present + additional error information to the user. + + The function arguments are as follows: + + version + The version passed in by ssuuddoo allows the plugin to determine + the major and minor version number of the plugin API supported + by ssuuddoo. + + conversation + A pointer to the conversation function that may be used by the + _s_h_o_w___v_e_r_s_i_o_n function to display version information (see + show_version below). The conversation function may also be + used to display additional error message to the user. The + conversation function returns 0 on success and -1 on failure. + + plugin_printf + A pointer to a printf-style function that may be used by the + _s_h_o_w___v_e_r_s_i_o_n function to display version information (see + show_version below). The plugin_printf function may also be + used to display additional error message to the user. The + plugin_printf function returns number of characters printed on + success and -1 on failure. + + settings + A vector of user-supplied ssuuddoo settings in the form of + "name=value" strings. The vector is terminated by a NULL + pointer. These settings correspond to flags the user specified + when running ssuuddoo. As such, they will only be present when the + corresponding flag has been specified on the command line. + + When parsing _s_e_t_t_i_n_g_s, the plugin should split on the ffiirrsstt + equal sign ('=') since the _n_a_m_e field will never include one + itself but the _v_a_l_u_e might. + + See the "Policy Plugin API" section for a list of all possible + settings. + + user_info + A vector of information about the user running the command in + the form of "name=value" strings. The vector is terminated by + a NULL pointer. + + When parsing _u_s_e_r___i_n_f_o, the plugin should split on the ffiirrsstt + equal sign ('=') since the _n_a_m_e field will never include one + itself but the _v_a_l_u_e might. + + See the "Policy Plugin API" section for a list of all possible + strings. + + argc + The number of elements in _a_r_g_v, not counting the final NULL + pointer. + + argv + If non-NULL, an argument vector describing a command the user + wishes to run in the same form as what would be passed to the + _e_x_e_c_v_e_(_) system call. + + user_env + The user's environment in the form of a NULL-terminated vector + of "name=value" strings. + + When parsing _u_s_e_r___e_n_v, the plugin should split on the ffiirrsstt + equal sign ('=') since the _n_a_m_e field will never include one + itself but the _v_a_l_u_e might. + + close + void (*close)(int exit_status, int error); + + The close function is called when the command being run by ssuuddoo + finishes. + + The function arguments are as follows: + + exit_status + The command's exit status, as returned by the _w_a_i_t(2) system + call. The value of exit_status is undefined if error is non- + zero. + + error + If the command could not be executed, this is set to the value + of errno set by the _e_x_e_c_v_e(2) system call. If the command was + successfully executed, the value of error is 0. + + show_version + int (*show_version)(int verbose); + + The show_version function is called by ssuuddoo when the user specifies + the -V option. The plugin may display its version information to + the user via the conversation or plugin_printf function using + SUDO_CONV_INFO_MSG. If the user requests detailed version + information, the verbose flag will be set. + + log_ttyin + int (*log_ttyin)(const char *buf, unsigned int len); + + The _l_o_g___t_t_y_i_n function is called whenever data can be read from the + user but before it is passed to the running command. This allows + the plugin to reject data if it chooses to (for instance if the + input contains banned content). Returns 1 if the data should be + passed to the command, 0 if the data is rejected (which will + terminate the command) or -1 if an error occurred. + + The function arguments are as follows: + + buf The buffer containing user input. + + len The length of _b_u_f in bytes. + + log_ttyout + int (*log_ttyout)(const char *buf, unsigned int len); + + The _l_o_g___t_t_y_o_u_t function is called whenever data can be read from + the command but before it is written to the user's terminal. This + allows the plugin to reject data if it chooses to (for instance if + the output contains banned content). Returns 1 if the data should + be passed to the user, 0 if the data is rejected (which will + terminate the command) or -1 if an error occurred. + + The function arguments are as follows: + + buf The buffer containing command output. + + len The length of _b_u_f in bytes. + + log_stdin + int (*log_stdin)(const char *buf, unsigned int len); + + The _l_o_g___s_t_d_i_n function is only used if the standard input does not + correspond to a tty device. It is called whenever data can be read + from the standard input but before it is passed to the running + command. This allows the plugin to reject data if it chooses to + (for instance if the input contains banned content). Returns 1 if + the data should be passed to the command, 0 if the data is rejected + (which will terminate the command) or -1 if an error occurred. + + The function arguments are as follows: + + buf The buffer containing user input. + + len The length of _b_u_f in bytes. + + log_stdout + int (*log_stdout)(const char *buf, unsigned int len); + + The _l_o_g___s_t_d_o_u_t function is only used if the standard output does + not correspond to a tty device. It is called whenever data can be + read from the command but before it is written to the standard + output. This allows the plugin to reject data if it chooses to + (for instance if the output contains banned content). Returns 1 if + the data should be passed to the user, 0 if the data is rejected + (which will terminate the command) or -1 if an error occurred. + + The function arguments are as follows: + + buf The buffer containing command output. + + len The length of _b_u_f in bytes. + + log_stderr + int (*log_stderr)(const char *buf, unsigned int len); + + The _l_o_g___s_t_d_e_r_r function is only used if the standard error does not + correspond to a tty device. It is called whenever data can be read + from the command but before it is written to the standard error. + This allows the plugin to reject data if it chooses to (for + instance if the output contains banned content). Returns 1 if the + data should be passed to the user, 0 if the data is rejected (which + will terminate the command) or -1 if an error occurred. + + The function arguments are as follows: + + buf The buffer containing command output. + + len The length of _b_u_f in bytes. + + _V_e_r_s_i_o_n _m_a_c_r_o_s + + Same as for the "Policy Plugin API". + + CCoonnvveerrssaattiioonn AAPPII + If the plugin needs to interact with the user, it may do so via the + conversation function. A plugin should not attempt to read directly + from the standard input or the user's tty (neither of which are + guaranteed to exist). The caller must include a trailing newline in + msg if one is to be printed. + + A printf-style function is also available that can be used to display + informational or error messages to the user, which is usually more + convenient for simple messages where no use input is required. + + struct sudo_conv_message { + #define SUDO_CONV_PROMPT_ECHO_OFF 0x0001 /* do not echo user input */ + #define SUDO_CONV_PROMPT_ECHO_ON 0x0002 /* echo user input */ + #define SUDO_CONV_ERROR_MSG 0x0003 /* error message */ + #define SUDO_CONV_INFO_MSG 0x0004 /* informational message */ + #define SUDO_CONV_PROMPT_MASK 0x0005 /* mask user input */ + #define SUDO_CONV_PROMPT_ECHO_OK 0x1000 /* flag: allow echo if no tty */ + int msg_type; + int timeout; + const char *msg; + }; + + struct sudo_conv_reply { + char *reply; + }; + + typedef int (*sudo_conv_t)(int num_msgs, + const struct sudo_conv_message msgs[], + struct sudo_conv_reply replies[]); + + typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...); + + Pointers to the conversation and printf-style functions are passed in + to the plugin's open function when the plugin is initialized. + + To use the conversation function, the plugin must pass an array of + sudo_conv_message and sudo_conv_reply structures. There must be a + struct sudo_conv_message and struct sudo_conv_reply for each message in + the conversation. The plugin is responsible for freeing the reply + buffer filled in to the struct sudo_conv_reply, if any. + + The printf-style function uses the same underlying mechanism as the + conversation function but only supports SUDO_CONV_INFO_MSG and + SUDO_CONV_ERROR_MSG for the _m_s_g___t_y_p_e parameter. It can be more + convenient than using the conversation function if no user reply is + needed and supports standard _p_r_i_n_t_f_(_) escape sequences. + + See the sample plugin for an example of the conversation function + usage. + + SSuuddooeerrss GGrroouupp PPlluuggiinn AAPPII + The _s_u_d_o_e_r_s module supports a plugin interface to allow non-Unix group + lookups. This can be used to query a group source other than the + standard Unix group database. A sample group plugin is bundled with + ssuuddoo that implements file-based lookups. Third party group plugins + include a QAS AD plugin available from Quest Software. + + A group plugin must declare and populate a sudoers_group_plugin struct + in the global scope. This structure contains pointers to the functions + that implement plugin initialization, cleanup and group lookup. + + struct sudoers_group_plugin { + unsigned int version; + int (*init)(int version, sudo_printf_t sudo_printf, + char *const argv[]); + void (*cleanup)(void); + int (*query)(const char *user, const char *group, + const struct passwd *pwd); + }; + + The sudoers_group_plugin struct has the following fields: + + version + The version field should be set to GROUP_API_VERSION. + + This allows _s_u_d_o_e_r_s to determine the API version the group plugin + was built against. + + init + int (*init)(int version, sudo_printf_t plugin_printf, + char *const argv[]); + + The _i_n_i_t function is called after _s_u_d_o_e_r_s has been parsed but + before any policy checks. It returns 1 on success, 0 on failure + (or if the plugin is not configured), and -1 if a error occurred. + If an error occurs, the plugin may call the plugin_printf function + with SUDO_CONF_ERROR_MSG to present additional error information to + the user. + + The function arguments are as follows: + + version + The version passed in by _s_u_d_o_e_r_s allows the plugin to determine + the major and minor version number of the group plugin API + supported by _s_u_d_o_e_r_s. + + plugin_printf + A pointer to a printf-style function that may be used to + display informational or error message to the user. Returns + the number of characters printed on success and -1 on failure. + + argv + A NULL-terminated array of arguments generated from the + _g_r_o_u_p___p_l_u_g_i_n option in _s_u_d_o_e_r_s. If no arguments were given, + _a_r_g_v will be NULL. + + cleanup + void (*cleanup)(); + + The _c_l_e_a_n_u_p function is called when _s_u_d_o_e_r_s has finished its group + checks. The plugin should free any memory it has allocated and + close open file handles. + + query + int (*query)(const char *user, const char *group, + const struct passwd *pwd); + + The _q_u_e_r_y function is used to ask the group plugin whether _u_s_e_r is + a member of _g_r_o_u_p. + + The function arguments are as follows: + + user + The name of the user being looked up in the external group + database. + + group + The name of the group being queried. + + pwd The password database entry for _u_s_e_r, if any. If _u_s_e_r is not + present in the password database, _p_w_d will be NULL. + + _V_e_r_s_i_o_n _M_a_c_r_o_s + + /* Sudoers group plugin version major/minor */ + #define GROUP_API_VERSION_MAJOR 1 + #define GROUP_API_VERSION_MINOR 0 + #define GROUP_API_VERSION ((GROUP_API_VERSION_MAJOR << 16) | \ + GROUP_API_VERSION_MINOR) + + /* Getters and setters for group version */ + #define GROUP_API_VERSION_GET_MAJOR(v) ((v) >> 16) + #define GROUP_API_VERSION_GET_MINOR(v) ((v) & 0xffff) + #define GROUP_API_VERSION_SET_MAJOR(vp, n) do { \ + *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \ + } while(0) + #define GROUP_API_VERSION_SET_MINOR(vp, n) do { \ + *(vp) = (*(vp) & 0xffff0000) | (n); \ + } while(0) + +SSEEEE AALLSSOO + _s_u_d_o_e_r_s(4), _s_u_d_o(1m) + +BBUUGGSS + If you feel you have found a bug in ssuuddoo, please submit a bug report at + http://www.sudo.ws/sudo/bugs/ + +SSUUPPPPOORRTT + Limited free support is available via the sudo-workers mailing list, + see http://www.sudo.ws/mailman/listinfo/sudo-workers to subscribe or + search the archives. + +DDIISSCCLLAAIIMMEERR + ssuuddoo is provided ``AS IS'' and any express or implied warranties, + including, but not limited to, the implied warranties of + merchantability and fitness for a particular purpose are disclaimed. + See the LICENSE file distributed with ssuuddoo or + http://www.sudo.ws/sudo/license.html for complete details. + + + +1.8.1p2 May 16, 2011 SUDO_PLUGIN(1m) diff --git a/doc/sudo_plugin.man.in b/doc/sudo_plugin.man.in new file mode 100644 index 0000000..9f26bfc --- /dev/null +++ b/doc/sudo_plugin.man.in @@ -0,0 +1,1282 @@ +.\" Copyright (c) 2009-2011 Todd C. Miller +.\" +.\" Permission to use, copy, modify, and distribute this software for any +.\" purpose with or without fee is hereby granted, provided that the above +.\" copyright notice and this permission notice appear in all copies. +.\" +.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +.\" +.\" Automatically generated by Pod::Man 2.23 (Pod::Simple 3.14) +.\" +.\" Standard preamble: +.\" ======================================================================== +.de Sp \" Vertical space (when we can't use .PP) +.if t .sp .5v +.if n .sp +.. +.de Vb \" Begin verbatim text +.ft CW +.nf +.ne \\$1 +.. +.de Ve \" End verbatim text +.ft R +.fi +.. +.\" Set up some character translations and predefined strings. \*(-- will +.\" give an unbreakable dash, \*(PI will give pi, \*(L" will give a left +.\" double quote, and \*(R" will give a right double quote. \*(C+ will +.\" give a nicer C++. Capital omega is used to do unbreakable dashes and +.\" therefore won't be available. \*(C` and \*(C' expand to `' in nroff, +.\" nothing in troff, for use with C<>. +.tr \(*W- +.ds C+ C\v'-.1v'\h'-1p'\s-2+\h'-1p'+\s0\v'.1v'\h'-1p' +.ie n \{\ +. ds -- \(*W- +. ds PI pi +. if (\n(.H=4u)&(1m=24u) .ds -- \(*W\h'-12u'\(*W\h'-12u'-\" diablo 10 pitch +. if (\n(.H=4u)&(1m=20u) .ds -- \(*W\h'-12u'\(*W\h'-8u'-\" diablo 12 pitch +. ds L" "" +. ds R" "" +. ds C` +. ds C' +'br\} +.el\{\ +. ds -- \|\(em\| +. ds PI \(*p +. ds L" `` +. ds R" '' +'br\} +.\" +.\" Escape single quotes in literal strings from groff's Unicode transform. +.ie \n(.g .ds Aq \(aq +.el .ds Aq ' +.\" +.\" If the F register is turned on, we'll generate index entries on stderr for +.\" titles (.TH), headers (.SH), subsections (.SS), items (.Ip), and index +.\" entries marked with X<> in POD. Of course, you'll have to process the +.\" output yourself in some meaningful fashion. +.ie \nF \{\ +. de IX +. tm Index:\\$1\t\\n%\t"\\$2" +.. +. nr % 0 +. rr F +.\} +.el \{\ +. de IX +.. +.\} +.\" +.\" Accent mark definitions (@(#)ms.acc 1.5 88/02/08 SMI; from UCB 4.2). +.\" Fear. Run. Save yourself. No user-serviceable parts. +. \" fudge factors for nroff and troff +.if n \{\ +. ds #H 0 +. ds #V .8m +. ds #F .3m +. ds #[ \f1 +. ds #] \fP +.\} +.if t \{\ +. ds #H ((1u-(\\\\n(.fu%2u))*.13m) +. ds #V .6m +. ds #F 0 +. ds #[ \& +. ds #] \& +.\} +. \" simple accents for nroff and troff +.if n \{\ +. ds ' \& +. ds ` \& +. ds ^ \& +. ds , \& +. ds ~ ~ +. ds / +.\} +.if t \{\ +. ds ' \\k:\h'-(\\n(.wu*8/10-\*(#H)'\'\h"|\\n:u" +. ds ` \\k:\h'-(\\n(.wu*8/10-\*(#H)'\`\h'|\\n:u' +. ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'^\h'|\\n:u' +. ds , \\k:\h'-(\\n(.wu*8/10)',\h'|\\n:u' +. ds ~ \\k:\h'-(\\n(.wu-\*(#H-.1m)'~\h'|\\n:u' +. ds / \\k:\h'-(\\n(.wu*8/10-\*(#H)'\z\(sl\h'|\\n:u' +.\} +. \" troff and (daisy-wheel) nroff accents +.ds : \\k:\h'-(\\n(.wu*8/10-\*(#H+.1m+\*(#F)'\v'-\*(#V'\z.\h'.2m+\*(#F'.\h'|\\n:u'\v'\*(#V' +.ds 8 \h'\*(#H'\(*b\h'-\*(#H' +.ds o \\k:\h'-(\\n(.wu+\w'\(de'u-\*(#H)/2u'\v'-.3n'\*(#[\z\(de\v'.3n'\h'|\\n:u'\*(#] +.ds d- \h'\*(#H'\(pd\h'-\w'~'u'\v'-.25m'\f2\(hy\fP\v'.25m'\h'-\*(#H' +.ds D- D\\k:\h'-\w'D'u'\v'-.11m'\z\(hy\v'.11m'\h'|\\n:u' +.ds th \*(#[\v'.3m'\s+1I\s-1\v'-.3m'\h'-(\w'I'u*2/3)'\s-1o\s+1\*(#] +.ds Th \*(#[\s+2I\s-2\h'-\w'I'u*3/5'\v'-.3m'o\v'.3m'\*(#] +.ds ae a\h'-(\w'a'u*4/10)'e +.ds Ae A\h'-(\w'A'u*4/10)'E +. \" corrections for vroff +.if v .ds ~ \\k:\h'-(\\n(.wu*9/10-\*(#H)'\s-2\u~\d\s+2\h'|\\n:u' +.if v .ds ^ \\k:\h'-(\\n(.wu*10/11-\*(#H)'\v'-.4m'^\v'.4m'\h'|\\n:u' +. \" for low resolution devices (crt and lpr) +.if \n(.H>23 .if \n(.V>19 \ +\{\ +. ds : e +. ds 8 ss +. ds o a +. ds d- d\h'-1'\(ga +. ds D- D\h'-1'\(hy +. ds th \o'bp' +. ds Th \o'LP' +. ds ae ae +. ds Ae AE +.\} +.rm #[ #] #H #V #F C +.\" ======================================================================== +.\" +.IX Title "SUDO_PLUGIN @mansectsu@" +.TH SUDO_PLUGIN @mansectsu@ "May 16, 2011" "1.8.1p2" "MAINTENANCE COMMANDS" +.\" For nroff, turn off justification. Always turn off hyphenation; it makes +.\" way too many mistakes in technical documents. +.if n .ad l +.nh +.SH "NAME" +sudo_plugin \- Sudo Plugin API +.SH "DESCRIPTION" +.IX Header "DESCRIPTION" +Starting with version 1.8, \fBsudo\fR supports a plugin \s-1API\s0 +for policy and session logging. By default, the \fIsudoers\fR policy +plugin and an associated I/O logging plugin are used. Via the plugin +\&\s-1API\s0, \fBsudo\fR can be configured to use alternate policy and/or I/O +logging plugins provided by third parties. The plugins to be used +are specified via the \fI@sysconfdir@/sudo.conf\fR file. +.PP +The \s-1API\s0 is versioned with a major and minor number. The minor +version number is incremented when additions are made. The major +number is incremented when incompatible changes are made. A plugin +should be check the version passed to it and make sure that the +major version matches. +.PP +The plugin \s-1API\s0 is defined by the \f(CW\*(C`sudo_plugin.h\*(C'\fR header file. +.SS "The sudo.conf File" +.IX Subsection "The sudo.conf File" +The \fI@sysconfdir@/sudo.conf\fR file contains plugin configuration directives. +Currently, the only supported keyword is the \f(CW\*(C`Plugin\*(C'\fR directive, +which causes a plugin plugin to be loaded. +.PP +A \f(CW\*(C`Plugin\*(C'\fR line consists of the \f(CW\*(C`Plugin\*(C'\fR keyword, followed by the +\&\fIsymbol_name\fR and the \fIpath\fR to the shared object containing the +plugin. The \fIsymbol_name\fR is the name of the \f(CW\*(C`struct policy_plugin\*(C'\fR +or \f(CW\*(C`struct io_plugin\*(C'\fR in the plugin shared object. The \fIpath\fR +may be fully qualified or relative. If not fully qualified it is +relative to the \fI@prefix@/libexec\fR directory. Any additional +parameters after the \fIpath\fR are ignored. Lines that don't begin +with \f(CW\*(C`Plugin\*(C'\fR or \f(CW\*(C`Path\*(C'\fR are silently ignored. +.PP +The same shared object may contain multiple plugins, each with a +different symbol name. The shared object file must be owned by uid +0 and only writable by its owner. Because of ambiguities that arise +from composite policies, only a single policy plugin may be specified. +This limitation does not apply to I/O plugins. +.PP +.Vb 10 +\& # +\& # Default @sysconfdir@/sudo.conf file +\& # +\& # Format: +\& # Plugin plugin_name plugin_path +\& # Path askpass /path/to/askpass +\& # +\& # The plugin_path is relative to @prefix@/libexec unless +\& # fully qualified. +\& # The plugin_name corresponds to a global symbol in the plugin +\& # that contains the plugin interface structure. +\& # +\& Plugin sudoers_policy sudoers.so +\& Plugin sudoers_io sudoers.so +.Ve +.SS "Policy Plugin \s-1API\s0" +.IX Subsection "Policy Plugin API" +A policy plugin must declare and populate a \f(CW\*(C`policy_plugin\*(C'\fR struct +in the global scope. This structure contains pointers to the functions +that implement the \fBsudo\fR policy checks. The name of the symbol should +be specified in \fI@sysconfdir@/sudo.conf\fR along with a path to the plugin +so that \fBsudo\fR can load it. +.PP +.Vb 10 +\& struct policy_plugin { +\& #define SUDO_POLICY_PLUGIN 1 +\& unsigned int type; /* always SUDO_POLICY_PLUGIN */ +\& unsigned int version; /* always SUDO_API_VERSION */ +\& int (*open)(unsigned int version, sudo_conv_t conversation, +\& sudo_printf_t plugin_printf, char * const settings[], +\& char * const user_info[], char * const user_env[]); +\& void (*close)(int exit_status, int error); +\& int (*show_version)(int verbose); +\& int (*check_policy)(int argc, char * const argv[], +\& char *env_add[], char **command_info[], +\& char **argv_out[], char **user_env_out[]); +\& int (*list)(int argc, char * const argv[], int verbose, +\& const char *list_user); +\& int (*validate)(void); +\& void (*invalidate)(int remove); +\& int (*init_session)(struct passwd *pwd); +\& }; +.Ve +.PP +The policy_plugin struct has the following fields: +.IP "type" 4 +.IX Item "type" +The \f(CW\*(C`type\*(C'\fR field should always be set to \s-1SUDO_POLICY_PLUGIN\s0. +.IP "version" 4 +.IX Item "version" +The \f(CW\*(C`version\*(C'\fR field should be set to \s-1SUDO_API_VERSION\s0. +.Sp +This allows \fBsudo\fR to determine the \s-1API\s0 version the plugin was +built against. +.IP "open" 4 +.IX Item "open" +.Vb 3 +\& int (*open)(unsigned int version, sudo_conv_t conversation, +\& sudo_printf_t plugin_printf, char * const settings[], +\& char * const user_info[], char * const user_env[]); +.Ve +.Sp +Returns 1 on success, 0 on failure, \-1 if a general error occurred, +or \-2 if there was a usage error. In the latter case, \fBsudo\fR will +print a usage message before it exits. If an error occurs, the +plugin may optionally call the conversation or plugin_printf function +with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional error information +to the user. +.Sp +The function arguments are as follows: +.RS 4 +.IP "version" 4 +.IX Item "version" +The version passed in by \fBsudo\fR allows the plugin to determine the +major and minor version number of the plugin \s-1API\s0 supported by +\&\fBsudo\fR. +.IP "conversation" 4 +.IX Item "conversation" +A pointer to the conversation function that can be used by the +plugin to interact with the user (see below). +Returns 0 on success and \-1 on failure. +.IP "plugin_printf" 4 +.IX Item "plugin_printf" +A pointer to a printf-style function that may be used to display +informational or error messages (see below). +Returns the number of characters printed on success and \-1 on failure. +.IP "settings" 4 +.IX Item "settings" +A vector of user-supplied \fBsudo\fR settings in the form of \*(L"name=value\*(R" +strings. The vector is terminated by a \f(CW\*(C`NULL\*(C'\fR pointer. These +settings correspond to flags the user specified when running \fBsudo\fR. +As such, they will only be present when the corresponding flag has +been specified on the command line. +.Sp +When parsing \fIsettings\fR, the plugin should split on the \fBfirst\fR +equal sign ('=') since the \fIname\fR field will never include one +itself but the \fIvalue\fR might. +.RS 4 +.IP "debug_level=number" 4 +.IX Item "debug_level=number" +A numeric debug level, from 1\-9, if specified via the \f(CW\*(C`\-D\*(C'\fR flag. +.IP "runas_user=string" 4 +.IX Item "runas_user=string" +The user name or uid to to run the command as, if specified via the +\&\f(CW\*(C`\-u\*(C'\fR flag. +.IP "runas_group=string" 4 +.IX Item "runas_group=string" +The group name or gid to to run the command as, if specified via +the \f(CW\*(C`\-g\*(C'\fR flag. +.IP "prompt=string" 4 +.IX Item "prompt=string" +The prompt to use when requesting a password, if specified via +the \f(CW\*(C`\-p\*(C'\fR flag. +.IP "set_home=bool" 4 +.IX Item "set_home=bool" +Set to true if the user specified the \f(CW\*(C`\-H\*(C'\fR flag. If true, set the +\&\f(CW\*(C`HOME\*(C'\fR environment variable to the target user's home directory. +.IP "preserve_environment=bool" 4 +.IX Item "preserve_environment=bool" +Set to true if the user specified the \f(CW\*(C`\-E\*(C'\fR flag, indicating that +the user wishes to preserve the environment. +.IP "run_shell=bool" 4 +.IX Item "run_shell=bool" +Set to true if the user specified the \f(CW\*(C`\-s\*(C'\fR flag, indicating that +the user wishes to run a shell. +.IP "login_shell=bool" 4 +.IX Item "login_shell=bool" +Set to true if the user specified the \f(CW\*(C`\-i\*(C'\fR flag, indicating that +the user wishes to run a login shell. +.IP "implied_shell=bool" 4 +.IX Item "implied_shell=bool" +If the user does not specify a program on the command line, \fBsudo\fR +will pass the plugin the path to the user's shell and set +\&\fIimplied_shell\fR to true. This allows \fBsudo\fR with no arguments +to be used similarly to \fIsu\fR\|(1). If the plugin does not to support +this usage, it may return a value of \-2 from the \f(CW\*(C`check_policy\*(C'\fR +function, which will cause \fBsudo\fR to print a usage message and +exit. +.IP "preserve_groups=bool" 4 +.IX Item "preserve_groups=bool" +Set to true if the user specified the \f(CW\*(C`\-P\*(C'\fR flag, indicating that +the user wishes to preserve the group vector instead of setting it +based on the runas user. +.IP "ignore_ticket=bool" 4 +.IX Item "ignore_ticket=bool" +Set to true if the user specified the \f(CW\*(C`\-k\*(C'\fR flag along with a +command, indicating that the user wishes to ignore any cached +authentication credentials. +.IP "noninteractive=bool" 4 +.IX Item "noninteractive=bool" +Set to true if the user specified the \f(CW\*(C`\-n\*(C'\fR flag, indicating that +\&\fBsudo\fR should operate in non-interactive mode. The plugin may +reject a command run in non-interactive mode if user interaction +is required. +.IP "login_class=string" 4 +.IX Item "login_class=string" +\&\s-1BSD\s0 login class to use when setting resource limits and nice value, +if specified by the \f(CW\*(C`\-c\*(C'\fR flag. +.IP "selinux_role=string" 4 +.IX Item "selinux_role=string" +SELinux role to use when executing the command, if specified by +the \f(CW\*(C`\-r\*(C'\fR flag. +.IP "selinux_type=string" 4 +.IX Item "selinux_type=string" +SELinux type to use when executing the command, if specified by +the \f(CW\*(C`\-t\*(C'\fR flag. +.IP "bsdauth_type=string" 4 +.IX Item "bsdauth_type=string" +Authentication type, if specified by the \f(CW\*(C`\-a\*(C'\fR flag, to use on +systems where \s-1BSD\s0 authentication is supported. +.IP "network_addrs=list" 4 +.IX Item "network_addrs=list" +A space-separated list of \s-1IP\s0 network addresses and netmasks in the +form \*(L"addr/netmask\*(R", e.g. \*(L"192.168.1.2/255.255.255.0\*(R". The address +and netmask pairs may be either IPv4 or IPv6, depending on what the +operating system supports. If the address contains a colon (':'), +it is an IPv6 address, else it is IPv4. +.IP "progname=string" 4 +.IX Item "progname=string" +The command name that sudo was run as, typically \*(L"sudo\*(R" or \*(L"sudoedit\*(R". +.IP "sudoedit=bool" 4 +.IX Item "sudoedit=bool" +Set to true when the \f(CW\*(C`\-e\*(C'\fR flag is is specified or if invoked as +\&\fBsudoedit\fR. The plugin shall substitute an editor into \fIargv\fR +in the \fIcheck_policy\fR function or return \f(CW\*(C`\-2\*(C'\fR with a usage error +if the plugin does not support \fIsudoedit\fR. For more information, +see the \fIcheck_policy\fR section. +.IP "closefrom=number" 4 +.IX Item "closefrom=number" +If specified, the user has requested via the \f(CW\*(C`\-C\*(C'\fR flag that \fBsudo\fR +close all files descriptors with a value of \fInumber\fR or higher. +The plugin may optionally pass this, or another value, back in the +\&\fIcommand_info\fR list. +.RE +.RS 4 +.Sp +Additional settings may be added in the future so the plugin should +silently ignore settings that it does not recognize. +.RE +.IP "user_info" 4 +.IX Item "user_info" +A vector of information about the user running the command in the form of +\&\*(L"name=value\*(R" strings. The vector is terminated by a \f(CW\*(C`NULL\*(C'\fR pointer. +.Sp +When parsing \fIuser_info\fR, the plugin should split on the \fBfirst\fR +equal sign ('=') since the \fIname\fR field will never include one +itself but the \fIvalue\fR might. +.RS 4 +.IP "user=string" 4 +.IX Item "user=string" +The name of the user invoking \fBsudo\fR. +.IP "uid=uid_t" 4 +.IX Item "uid=uid_t" +The real user \s-1ID\s0 of the user invoking \fBsudo\fR. +.IP "gid=gid_t" 4 +.IX Item "gid=gid_t" +The real group \s-1ID\s0 of the user invoking \fBsudo\fR. +.IP "groups=list" 4 +.IX Item "groups=list" +The user's supplementary group list formatted as a string of +comma-separated group IDs. +.IP "cwd=string" 4 +.IX Item "cwd=string" +The user's current working directory. +.IP "tty=string" 4 +.IX Item "tty=string" +The path to the user's terminal device. If the user has no terminal +device associated with the session, the value will be empty, as in +\&\f(CW\*(C`tty=\*(C'\fR. +.IP "host=string" 4 +.IX Item "host=string" +The local machine's hostname as returned by the \f(CW\*(C`gethostname()\*(C'\fR +system call. +.IP "lines=int" 4 +.IX Item "lines=int" +The number of lines the user's terminal supports. If there is +no terminal device available, a default value of 24 is used. +.IP "cols=int" 4 +.IX Item "cols=int" +The number of columns the user's terminal supports. If there is +no terminal device available, a default value of 80 is used. +.RE +.RS 4 +.RE +.IP "user_env" 4 +.IX Item "user_env" +The user's environment in the form of a \f(CW\*(C`NULL\*(C'\fR\-terminated vector of +\&\*(L"name=value\*(R" strings. +.Sp +When parsing \fIuser_env\fR, the plugin should split on the \fBfirst\fR +equal sign ('=') since the \fIname\fR field will never include one +itself but the \fIvalue\fR might. +.RE +.RS 4 +.RE +.IP "close" 4 +.IX Item "close" +.Vb 1 +\& void (*close)(int exit_status, int error); +.Ve +.Sp +The \f(CW\*(C`close\*(C'\fR function is called when the command being run by \fBsudo\fR +finishes. +.Sp +The function arguments are as follows: +.RS 4 +.IP "exit_status" 4 +.IX Item "exit_status" +The command's exit status, as returned by the \fIwait\fR\|(2) system call. +The value of \f(CW\*(C`exit_status\*(C'\fR is undefined if \f(CW\*(C`error\*(C'\fR is non-zero. +.IP "error" 4 +.IX Item "error" +If the command could not be executed, this is set to the value of +\&\f(CW\*(C`errno\*(C'\fR set by the \fIexecve\fR\|(2) system call. The plugin is responsible +for displaying error information via the conversation or plugin_printf +function. If the command was successfully executed, the value of +\&\f(CW\*(C`error\*(C'\fR is 0. +.RE +.RS 4 +.RE +.IP "show_version" 4 +.IX Item "show_version" +.Vb 1 +\& int (*show_version)(int verbose); +.Ve +.Sp +The \f(CW\*(C`show_version\*(C'\fR function is called by \fBsudo\fR when the user specifies +the \f(CW\*(C`\-V\*(C'\fR option. The plugin may display its version information +to the user via the conversation or plugin_printf function using +\&\f(CW\*(C`SUDO_CONV_INFO_MSG\*(C'\fR. If the user requests detailed version +information, the verbose flag will be set. +.IP "check_policy" 4 +.IX Item "check_policy" +.Vb 3 +\& int (*check_policy)(int argc, char * const argv[] +\& char *env_add[], char **command_info[], +\& char **argv_out[], char **user_env_out[]); +.Ve +.Sp +The \fIcheck_policy\fR function is called by \fBsudo\fR to determine +whether the user is allowed to run the specified commands. +.Sp +If the \fIsudoedit\fR option was enabled in the \fIsettings\fR array +passed to the \fIopen\fR function, the user has requested \fIsudoedit\fR +mode. \fIsudoedit\fR is a mechanism for editing one or more files +where an editor is run with the user's credentials instead of with +elevated privileges. \fBsudo\fR achieves this by creating user-writable +temporary copies of the files to be edited and then overwriting the +originals with the temporary copies after editing is complete. If +the plugin supports \fBsudoedit\fR, it should choose the editor to be +used, potentially from a variable in the user's environment, such +as \f(CW\*(C`EDITOR\*(C'\fR, and include it in \fIargv_out\fR (note that environment +variables may include command line flags). The files to be edited +should be copied from \fIargv\fR into \fIargv_out\fR, separated from the +editor and its arguments by a \f(CW"\-\-"\fR element. The \f(CW"\-\-"\fR will +be removed by \fBsudo\fR before the editor is executed. The plugin +should also set \fIsudoedit=true\fR in the \fIcommand_info\fR list. +.Sp +The \fIcheck_policy\fR function returns 1 if the command is allowed, +0 if not allowed, \-1 for a general error, or \-2 for a usage error +or if \fBsudoedit\fR was specified but is unsupported by the plugin. +In the latter case, \fBsudo\fR will print a usage message before it +exits. If an error occurs, the plugin may optionally call the +conversation or plugin_printf function with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR +to present additional error information to the user. +.Sp +The function arguments are as follows: +.RS 4 +.IP "argc" 4 +.IX Item "argc" +The number of elements in \fIargv\fR, not counting the final \f(CW\*(C`NULL\*(C'\fR +pointer. +.IP "argv" 4 +.IX Item "argv" +The argument vector describing the command the user wishes to run, +in the same form as what would be passed to the \fIexecve()\fR system +call. The vector is terminated by a \f(CW\*(C`NULL\*(C'\fR pointer. +.IP "env_add" 4 +.IX Item "env_add" +Additional environment variables specified by the user on the command +line in the form of a \f(CW\*(C`NULL\*(C'\fR\-terminated vector of \*(L"name=value\*(R" +strings. The plugin may reject the command if one or more variables +are not allowed to be set, or it may silently ignore such variables. +.Sp +When parsing \fIenv_add\fR, the plugin should split on the \fBfirst\fR +equal sign ('=') since the \fIname\fR field will never include one +itself but the \fIvalue\fR might. +.IP "command_info" 4 +.IX Item "command_info" +Information about the command being run in the form of \*(L"name=value\*(R" +strings. These values are used by \fBsudo\fR to set the execution +environment when running a command. The plugin is responsible for +creating and populating the vector, which must be terminated with +a \f(CW\*(C`NULL\*(C'\fR pointer. The following values are recognized by \fBsudo\fR: +.RS 4 +.IP "command=string" 4 +.IX Item "command=string" +Fully qualified path to the command to be executed. +.IP "runas_uid=uid" 4 +.IX Item "runas_uid=uid" +User \s-1ID\s0 to run the command as. +.IP "runas_euid=uid" 4 +.IX Item "runas_euid=uid" +Effective user \s-1ID\s0 to run the command as. +If not specified, the value of \fIrunas_uid\fR is used. +.IP "runas_gid=gid" 4 +.IX Item "runas_gid=gid" +Group \s-1ID\s0 to run the command as. +.IP "runas_egid=gid" 4 +.IX Item "runas_egid=gid" +Effective group \s-1ID\s0 to run the command as. +If not specified, the value of \fIrunas_gid\fR is used. +.IP "runas_groups=list" 4 +.IX Item "runas_groups=list" +The supplementary group vector to use for the command in the form +of a comma-separated list of group IDs. If \fIpreserve_groups\fR +is set, this option is ignored. +.IP "login_class=string" 4 +.IX Item "login_class=string" +\&\s-1BSD\s0 login class to use when setting resource limits and nice value +(optional). This option is only set on systems that support login +classes. +.IP "preserve_groups=bool" 4 +.IX Item "preserve_groups=bool" +If set, \fBsudo\fR will preserve the user's group vector instead of +initializing the group vector based on \f(CW\*(C`runas_user\*(C'\fR. +.IP "cwd=string" 4 +.IX Item "cwd=string" +The current working directory to change to when executing the command. +.IP "noexec=bool" 4 +.IX Item "noexec=bool" +If set, prevent the command from executing other programs. +.IP "chroot=string" 4 +.IX Item "chroot=string" +The root directory to use when running the command. +.IP "nice=int" 4 +.IX Item "nice=int" +Nice value (priority) to use when executing the command. The nice +value, if specified, overrides the priority associated with the +\&\fIlogin_class\fR on \s-1BSD\s0 systems. +.IP "umask=octal" 4 +.IX Item "umask=octal" +The file creation mask to use when executing the command. +.IP "selinux_role=string" 4 +.IX Item "selinux_role=string" +SELinux role to use when executing the command. +.IP "selinux_type=string" 4 +.IX Item "selinux_type=string" +SELinux type to use when executing the command. +.IP "timeout=int" 4 +.IX Item "timeout=int" +Command timeout. If non-zero then when the timeout expires the +command will be killed. +.IP "sudoedit=bool" 4 +.IX Item "sudoedit=bool" +Set to true when in \fIsudoedit\fR mode. The plugin may enable +\&\fIsudoedit\fR mode even if \fBsudo\fR was not invoked as \fBsudoedit\fR. +This allows the plugin to perform command substitution and transparently +enable \fIsudoedit\fR when the user attempts to run an editor. +.IP "closefrom=number" 4 +.IX Item "closefrom=number" +If specified, \fBsudo\fR will close all files descriptors with a value +of \fInumber\fR or higher. +.IP "iolog_compress=bool" 4 +.IX Item "iolog_compress=bool" +Set to true if the I/O logging plugins, if any, should compress the +log data. This is a hint to the I/O logging plugin which may choose +to ignore it. +.IP "iolog_path=string" 4 +.IX Item "iolog_path=string" +Fully qualified path to the file or directory in which I/O log is +to be stored. This is a hint to the I/O logging plugin which may +choose to ignore it. If no I/O logging plugin is loaded, this +setting has no effect. +.IP "iolog_stdin=bool" 4 +.IX Item "iolog_stdin=bool" +Set to true if the I/O logging plugins, if any, should log the +standard input if it is not connected to a terminal device. This +is a hint to the I/O logging plugin which may choose to ignore it. +.IP "iolog_stdout=bool" 4 +.IX Item "iolog_stdout=bool" +Set to true if the I/O logging plugins, if any, should log the +standard output if it is not connected to a terminal device. This +is a hint to the I/O logging plugin which may choose to ignore it. +.IP "iolog_stderr=bool" 4 +.IX Item "iolog_stderr=bool" +Set to true if the I/O logging plugins, if any, should log the +standard error if it is not connected to a terminal device. This +is a hint to the I/O logging plugin which may choose to ignore it. +.IP "iolog_ttyin=bool" 4 +.IX Item "iolog_ttyin=bool" +Set to true if the I/O logging plugins, if any, should log all +terminal input. This only includes input typed by the user and not +from a pipe or redirected from a file. This is a hint to the I/O +logging plugin which may choose to ignore it. +.IP "iolog_ttyout=bool" 4 +.IX Item "iolog_ttyout=bool" +Set to true if the I/O logging plugins, if any, should log all +terminal output. This only includes output to the screen, not +output to a pipe or file. This is a hint to the I/O logging plugin +which may choose to ignore it. +.IP "use_pty=bool" 4 +.IX Item "use_pty=bool" +Allocate a pseudo-tty to run the command in, regardless of whether +or not I/O logging is in use. By default, \fBsudo\fR will only run +the command in a pty when an I/O log plugin is loaded. +.IP "set_utmp=bool" 4 +.IX Item "set_utmp=bool" +Create a utmp (or utmpx) entry when a pseudo-tty is allocated. By +default, the new entry will be a copy of the user's existing utmp +entry (if any), with the tty, time, type and pid fields updated. +.IP "utmp_user=string" 4 +.IX Item "utmp_user=string" +User name to use when constructing a new utmp (or utmpx) entry when +\&\fIset_utmp\fR is enabled. This option can be used to set the user +field in the utmp entry to the user the command runs as rather than +the invoking user. If not set, \fBsudo\fR will base the new entry on +the invoking user's existing entry. +.RE +.RS 4 +.Sp +Unsupported values will be ignored. +.RE +.IP "argv_out" 4 +.IX Item "argv_out" +The \f(CW\*(C`NULL\*(C'\fR\-terminated argument vector to pass to the \fIexecve()\fR +system call when executing the command. The plugin is responsible +for allocating and populating the vector. +.IP "user_env_out" 4 +.IX Item "user_env_out" +The \f(CW\*(C`NULL\*(C'\fR\-terminated environment vector to use when executing the +command. The plugin is responsible for allocating and populating +the vector. +.RE +.RS 4 +.RE +.IP "list" 4 +.IX Item "list" +.Vb 2 +\& int (*list)(int verbose, const char *list_user, +\& int argc, char * const argv[]); +.Ve +.Sp +List available privileges for the invoking user. Returns 1 on +success, 0 on failure and \-1 on error. On error, the plugin may +optionally call the conversation or plugin_printf function with +\&\f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional error information to +the user. +.Sp +Privileges should be output via the conversation or plugin_printf +function using \f(CW\*(C`SUDO_CONV_INFO_MSG\*(C'\fR. +.RS 4 +.IP "verbose" 4 +.IX Item "verbose" +Flag indicating whether to list in verbose mode or not. +.IP "list_user" 4 +.IX Item "list_user" +The name of a different user to list privileges for if the policy +allows it. If \f(CW\*(C`NULL\*(C'\fR, the plugin should list the privileges of +the invoking user. +.IP "argc" 4 +.IX Item "argc" +The number of elements in \fIargv\fR, not counting the final \f(CW\*(C`NULL\*(C'\fR +pointer. +.IP "argv" 4 +.IX Item "argv" +If non\-\f(CW\*(C`NULL\*(C'\fR, an argument vector describing a command the user +wishes to check against the policy in the same form as what would +be passed to the \fIexecve()\fR system call. If the command is permitted +by the policy, the fully-qualified path to the command should be +displayed along with any command line arguments. +.RE +.RS 4 +.RE +.IP "validate" 4 +.IX Item "validate" +.Vb 1 +\& int (*validate)(void); +.Ve +.Sp +The \f(CW\*(C`validate\*(C'\fR function is called when \fBsudo\fR is run with the +\&\f(CW\*(C`\-v\*(C'\fR flag. For policy plugins such as \fIsudoers\fR that cache +authentication credentials, this function will validate and cache +the credentials. +.Sp +The \f(CW\*(C`validate\*(C'\fR function should be \f(CW\*(C`NULL\*(C'\fR if the plugin does not +support credential caching. +.Sp +Returns 1 on success, 0 on failure and \-1 on error. +On error, the plugin may optionally call the conversation or plugin_printf +function with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional +error information to the user. +.IP "invalidate" 4 +.IX Item "invalidate" +.Vb 1 +\& void (*invalidate)(int remove); +.Ve +.Sp +The \f(CW\*(C`invalidate\*(C'\fR function is called when \fBsudo\fR is called with +the \f(CW\*(C`\-k\*(C'\fR or \f(CW\*(C`\-K\*(C'\fR flag. For policy plugins such as \fIsudoers\fR that +cache authentication credentials, this function will invalidate the +credentials. If the \fIremove\fR flag is set, the plugin may remove +the credentials instead of simply invalidating them. +.Sp +The \f(CW\*(C`invalidate\*(C'\fR function should be \f(CW\*(C`NULL\*(C'\fR if the plugin does not +support credential caching. +.IP "init_session" 4 +.IX Item "init_session" +.Vb 1 +\& int (*init_session)(struct passwd *pwd); +.Ve +.Sp +The \f(CW\*(C`init_session\*(C'\fR function is called when \fBsudo\fR sets up the +execution environment for the command, immediately before the +contents of the \fIcommand_info\fR list are applied (before the uid +changes). This can be used to do session setup that is not supported +by \fIcommand_info\fR, such as opening the \s-1PAM\s0 session. +.Sp +The \fIpwd\fR argument points to a passwd struct for the user the +command will be run as if the uid the command will run as was found +in the password database, otherwise it will be \s-1NULL\s0. +.Sp +Returns 1 on success, 0 on failure and \-1 on error. +On error, the plugin may optionally call the conversation or plugin_printf +function with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional +error information to the user. +.PP +\fIVersion macros\fR +.IX Subsection "Version macros" +.PP +.Vb 8 +\& #define SUDO_API_VERSION_GET_MAJOR(v) ((v) >> 16) +\& #define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffff) +\& #define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \e +\& *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \e +\& } while(0) +\& #define SUDO_VERSION_SET_MINOR(vp, n) do { \e +\& *(vp) = (*(vp) & 0xffff0000) | (n); \e +\& } while(0) +\& +\& #define SUDO_API_VERSION_MAJOR 1 +\& #define SUDO_API_VERSION_MINOR 0 +\& #define SUDO_API_VERSION ((SUDO_API_VERSION_MAJOR << 16) | \e +\& SUDO_API_VERSION_MINOR) +.Ve +.SS "I/O Plugin \s-1API\s0" +.IX Subsection "I/O Plugin API" +.Vb 10 +\& struct io_plugin { +\& #define SUDO_IO_PLUGIN 2 +\& unsigned int type; /* always SUDO_IO_PLUGIN */ +\& unsigned int version; /* always SUDO_API_VERSION */ +\& int (*open)(unsigned int version, sudo_conv_t conversation +\& sudo_printf_t plugin_printf, char * const settings[], +\& char * const user_info[], int argc, char * const argv[], +\& char * const user_env[]); +\& void (*close)(int exit_status, int error); /* wait status or error */ +\& int (*show_version)(int verbose); +\& int (*log_ttyin)(const char *buf, unsigned int len); +\& int (*log_ttyout)(const char *buf, unsigned int len); +\& int (*log_stdin)(const char *buf, unsigned int len); +\& int (*log_stdout)(const char *buf, unsigned int len); +\& int (*log_stderr)(const char *buf, unsigned int len); +\& }; +.Ve +.PP +When an I/O plugin is loaded, \fBsudo\fR runs the command in a pseudo-tty. +This makes it possible to log the input and output from the user's +session. If any of the standard input, standard output or standard +error do not correspond to a tty, \fBsudo\fR will open a pipe to capture +the I/O for logging before passing it on. +.PP +The log_ttyin function receives the raw user input from the terminal +device (note that this will include input even when echo is disabled, +such as when a password is read). The log_ttyout function receives +output from the pseudo-tty that is suitable for replaying the user's +session at a later time. The log_stdin, log_stdout and log_stderr +functions are only called if the standard input, standard output +or standard error respectively correspond to something other than +a tty. +.PP +Any of the logging functions may be set to the \s-1NULL\s0 +pointer if no logging is to be performed. If the open function +returns \f(CW0\fR, no I/O will be sent to the plugin. +.PP +The io_plugin struct has the following fields: +.IP "type" 4 +.IX Item "type" +The \f(CW\*(C`type\*(C'\fR field should always be set to \s-1SUDO_IO_PLUGIN\s0 +.IP "version" 4 +.IX Item "version" +The \f(CW\*(C`version\*(C'\fR field should be set to \s-1SUDO_API_VERSION\s0. +.Sp +This allows \fBsudo\fR to determine the \s-1API\s0 version the plugin was +built against. +.IP "open" 4 +.IX Item "open" +.Vb 4 +\& int (*open)(unsigned int version, sudo_conv_t conversation +\& sudo_printf_t plugin_printf, char * const settings[], +\& char * const user_info[], int argc, char * const argv[], +\& char * const user_env[]); +.Ve +.Sp +The \fIopen\fR function is run before the \fIlog_input\fR, \fIlog_output\fR +or \fIshow_version\fR functions are called. It is only called if the +version is being requested or the \fIcheck_policy\fR function has +returned successfully. It returns 1 on success, 0 on failure, \-1 +if a general error occurred, or \-2 if there was a usage error. In +the latter case, \fBsudo\fR will print a usage message before it exits. +If an error occurs, the plugin may optionally call the conversation +or plugin_printf function with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present +additional error information to the user. +.Sp +The function arguments are as follows: +.RS 4 +.IP "version" 4 +.IX Item "version" +The version passed in by \fBsudo\fR allows the plugin to determine the +major and minor version number of the plugin \s-1API\s0 supported by +\&\fBsudo\fR. +.IP "conversation" 4 +.IX Item "conversation" +A pointer to the conversation function that may be used by the +\&\fIshow_version\fR function to display version information (see +show_version below). The conversation function may also be used +to display additional error message to the user. +The conversation function returns 0 on success and \-1 on failure. +.IP "plugin_printf" 4 +.IX Item "plugin_printf" +A pointer to a printf-style function that may be used by the +\&\fIshow_version\fR function to display version information (see +show_version below). The plugin_printf function may also be used +to display additional error message to the user. +The plugin_printf function returns number of characters printed on +success and \-1 on failure. +.IP "settings" 4 +.IX Item "settings" +A vector of user-supplied \fBsudo\fR settings in the form of \*(L"name=value\*(R" +strings. The vector is terminated by a \f(CW\*(C`NULL\*(C'\fR pointer. These +settings correspond to flags the user specified when running \fBsudo\fR. +As such, they will only be present when the corresponding flag has +been specified on the command line. +.Sp +When parsing \fIsettings\fR, the plugin should split on the \fBfirst\fR +equal sign ('=') since the \fIname\fR field will never include one +itself but the \fIvalue\fR might. +.Sp +See the \*(L"Policy Plugin \s-1API\s0\*(R" section for a list of all possible settings. +.IP "user_info" 4 +.IX Item "user_info" +A vector of information about the user running the command in the form of +\&\*(L"name=value\*(R" strings. The vector is terminated by a \f(CW\*(C`NULL\*(C'\fR pointer. +.Sp +When parsing \fIuser_info\fR, the plugin should split on the \fBfirst\fR +equal sign ('=') since the \fIname\fR field will never include one +itself but the \fIvalue\fR might. +.Sp +See the \*(L"Policy Plugin \s-1API\s0\*(R" section for a list of all possible strings. +.IP "argc" 4 +.IX Item "argc" +The number of elements in \fIargv\fR, not counting the final \f(CW\*(C`NULL\*(C'\fR +pointer. +.IP "argv" 4 +.IX Item "argv" +If non\-\f(CW\*(C`NULL\*(C'\fR, an argument vector describing a command the user +wishes to run in the same form as what would be passed to the +\&\fIexecve()\fR system call. +.IP "user_env" 4 +.IX Item "user_env" +The user's environment in the form of a \f(CW\*(C`NULL\*(C'\fR\-terminated vector of +\&\*(L"name=value\*(R" strings. +.Sp +When parsing \fIuser_env\fR, the plugin should split on the \fBfirst\fR +equal sign ('=') since the \fIname\fR field will never include one +itself but the \fIvalue\fR might. +.RE +.RS 4 +.RE +.IP "close" 4 +.IX Item "close" +.Vb 1 +\& void (*close)(int exit_status, int error); +.Ve +.Sp +The \f(CW\*(C`close\*(C'\fR function is called when the command being run by \fBsudo\fR +finishes. +.Sp +The function arguments are as follows: +.RS 4 +.IP "exit_status" 4 +.IX Item "exit_status" +The command's exit status, as returned by the \fIwait\fR\|(2) system call. +The value of \f(CW\*(C`exit_status\*(C'\fR is undefined if \f(CW\*(C`error\*(C'\fR is non-zero. +.IP "error" 4 +.IX Item "error" +If the command could not be executed, this is set to the value of +\&\f(CW\*(C`errno\*(C'\fR set by the \fIexecve\fR\|(2) system call. If the command was +successfully executed, the value of \f(CW\*(C`error\*(C'\fR is 0. +.RE +.RS 4 +.RE +.IP "show_version" 4 +.IX Item "show_version" +.Vb 1 +\& int (*show_version)(int verbose); +.Ve +.Sp +The \f(CW\*(C`show_version\*(C'\fR function is called by \fBsudo\fR when the user specifies +the \f(CW\*(C`\-V\*(C'\fR option. The plugin may display its version information +to the user via the conversation or plugin_printf function using +\&\f(CW\*(C`SUDO_CONV_INFO_MSG\*(C'\fR. If the user requests detailed version +information, the verbose flag will be set. +.IP "log_ttyin" 4 +.IX Item "log_ttyin" +.Vb 1 +\& int (*log_ttyin)(const char *buf, unsigned int len); +.Ve +.Sp +The \fIlog_ttyin\fR function is called whenever data can be read from +the user but before it is passed to the running command. This +allows the plugin to reject data if it chooses to (for instance +if the input contains banned content). Returns \f(CW1\fR if the data +should be passed to the command, \f(CW0\fR if the data is rejected +(which will terminate the command) or \f(CW\*(C`\-1\*(C'\fR if an error occurred. +.Sp +The function arguments are as follows: +.RS 4 +.IP "buf" 4 +.IX Item "buf" +The buffer containing user input. +.IP "len" 4 +.IX Item "len" +The length of \fIbuf\fR in bytes. +.RE +.RS 4 +.RE +.IP "log_ttyout" 4 +.IX Item "log_ttyout" +.Vb 1 +\& int (*log_ttyout)(const char *buf, unsigned int len); +.Ve +.Sp +The \fIlog_ttyout\fR function is called whenever data can be read from +the command but before it is written to the user's terminal. This +allows the plugin to reject data if it chooses to (for instance +if the output contains banned content). Returns \f(CW1\fR if the data +should be passed to the user, \f(CW0\fR if the data is rejected +(which will terminate the command) or \f(CW\*(C`\-1\*(C'\fR if an error occurred. +.Sp +The function arguments are as follows: +.RS 4 +.IP "buf" 4 +.IX Item "buf" +The buffer containing command output. +.IP "len" 4 +.IX Item "len" +The length of \fIbuf\fR in bytes. +.RE +.RS 4 +.RE +.IP "log_stdin" 4 +.IX Item "log_stdin" +.Vb 1 +\& int (*log_stdin)(const char *buf, unsigned int len); +.Ve +.Sp +The \fIlog_stdin\fR function is only used if the standard input does +not correspond to a tty device. It is called whenever data can be +read from the standard input but before it is passed to the running +command. This allows the plugin to reject data if it chooses to +(for instance if the input contains banned content). Returns \f(CW1\fR +if the data should be passed to the command, \f(CW0\fR if the data is +rejected (which will terminate the command) or \f(CW\*(C`\-1\*(C'\fR if an error +occurred. +.Sp +The function arguments are as follows: +.RS 4 +.IP "buf" 4 +.IX Item "buf" +The buffer containing user input. +.IP "len" 4 +.IX Item "len" +The length of \fIbuf\fR in bytes. +.RE +.RS 4 +.RE +.IP "log_stdout" 4 +.IX Item "log_stdout" +.Vb 1 +\& int (*log_stdout)(const char *buf, unsigned int len); +.Ve +.Sp +The \fIlog_stdout\fR function is only used if the standard output does +not correspond to a tty device. It is called whenever data can be +read from the command but before it is written to the standard +output. This allows the plugin to reject data if it chooses to +(for instance if the output contains banned content). Returns \f(CW1\fR +if the data should be passed to the user, \f(CW0\fR if the data is +rejected (which will terminate the command) or \f(CW\*(C`\-1\*(C'\fR if an error +occurred. +.Sp +The function arguments are as follows: +.RS 4 +.IP "buf" 4 +.IX Item "buf" +The buffer containing command output. +.IP "len" 4 +.IX Item "len" +The length of \fIbuf\fR in bytes. +.RE +.RS 4 +.RE +.IP "log_stderr" 4 +.IX Item "log_stderr" +.Vb 1 +\& int (*log_stderr)(const char *buf, unsigned int len); +.Ve +.Sp +The \fIlog_stderr\fR function is only used if the standard error does +not correspond to a tty device. It is called whenever data can be +read from the command but before it is written to the standard +error. This allows the plugin to reject data if it chooses to +(for instance if the output contains banned content). Returns \f(CW1\fR +if the data should be passed to the user, \f(CW0\fR if the data is +rejected (which will terminate the command) or \f(CW\*(C`\-1\*(C'\fR if an error +occurred. +.Sp +The function arguments are as follows: +.RS 4 +.IP "buf" 4 +.IX Item "buf" +The buffer containing command output. +.IP "len" 4 +.IX Item "len" +The length of \fIbuf\fR in bytes. +.RE +.RS 4 +.RE +.PP +\fIVersion macros\fR +.IX Subsection "Version macros" +.PP +Same as for the \*(L"Policy Plugin \s-1API\s0\*(R". +.SS "Conversation \s-1API\s0" +.IX Subsection "Conversation API" +If the plugin needs to interact with the user, it may do so via the +conversation function. A plugin should not attempt to read directly +from the standard input or the user's tty (neither of which are +guaranteed to exist). The caller must include a trailing newline +in \f(CW\*(C`msg\*(C'\fR if one is to be printed. +.PP +A printf-style function is also available that can be used to display +informational or error messages to the user, which is usually more +convenient for simple messages where no use input is required. +.PP +.Vb 11 +\& struct sudo_conv_message { +\& #define SUDO_CONV_PROMPT_ECHO_OFF 0x0001 /* do not echo user input */ +\& #define SUDO_CONV_PROMPT_ECHO_ON 0x0002 /* echo user input */ +\& #define SUDO_CONV_ERROR_MSG 0x0003 /* error message */ +\& #define SUDO_CONV_INFO_MSG 0x0004 /* informational message */ +\& #define SUDO_CONV_PROMPT_MASK 0x0005 /* mask user input */ +\& #define SUDO_CONV_PROMPT_ECHO_OK 0x1000 /* flag: allow echo if no tty */ +\& int msg_type; +\& int timeout; +\& const char *msg; +\& }; +\& +\& struct sudo_conv_reply { +\& char *reply; +\& }; +\& +\& typedef int (*sudo_conv_t)(int num_msgs, +\& const struct sudo_conv_message msgs[], +\& struct sudo_conv_reply replies[]); +\& +\& typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...); +.Ve +.PP +Pointers to the conversation and printf-style functions are passed +in to the plugin's \f(CW\*(C`open\*(C'\fR function when the plugin is initialized. +.PP +To use the conversation function, the plugin must pass an array of +\&\f(CW\*(C`sudo_conv_message\*(C'\fR and \f(CW\*(C`sudo_conv_reply\*(C'\fR structures. There must +be a \f(CW\*(C`struct sudo_conv_message\*(C'\fR and \f(CW\*(C`struct sudo_conv_reply\*(C'\fR for +each message in the conversation. The plugin is responsible for +freeing the reply buffer filled in to the \f(CW\*(C`struct sudo_conv_reply\*(C'\fR, +if any. +.PP +The printf-style function uses the same underlying mechanism as the +conversation function but only supports \f(CW\*(C`SUDO_CONV_INFO_MSG\*(C'\fR and +\&\f(CW\*(C`SUDO_CONV_ERROR_MSG\*(C'\fR for the \fImsg_type\fR parameter. It can be +more convenient than using the conversation function if no user +reply is needed and supports standard \fIprintf()\fR escape sequences. +.PP +See the sample plugin for an example of the conversation function usage. +.SS "Sudoers Group Plugin \s-1API\s0" +.IX Subsection "Sudoers Group Plugin API" +The \fIsudoers\fR module supports a plugin interface to allow non-Unix +group lookups. This can be used to query a group source other than +the standard Unix group database. A sample group plugin is bundled +with \fBsudo\fR that implements file-based lookups. Third party group +plugins include a \s-1QAS\s0 \s-1AD\s0 plugin available from Quest Software. +.PP +A group plugin must declare and populate a \f(CW\*(C`sudoers_group_plugin\*(C'\fR +struct in the global scope. This structure contains pointers to +the functions that implement plugin initialization, cleanup and +group lookup. +.PP +.Vb 8 +\& struct sudoers_group_plugin { +\& unsigned int version; +\& int (*init)(int version, sudo_printf_t sudo_printf, +\& char *const argv[]); +\& void (*cleanup)(void); +\& int (*query)(const char *user, const char *group, +\& const struct passwd *pwd); +\&}; +.Ve +.PP +The \f(CW\*(C`sudoers_group_plugin\*(C'\fR struct has the following fields: +.IP "version" 4 +.IX Item "version" +The \f(CW\*(C`version\*(C'\fR field should be set to \s-1GROUP_API_VERSION\s0. +.Sp +This allows \fIsudoers\fR to determine the \s-1API\s0 version the group plugin +was built against. +.IP "init" 4 +.IX Item "init" +.Vb 2 +\& int (*init)(int version, sudo_printf_t plugin_printf, +\& char *const argv[]); +.Ve +.Sp +The \fIinit\fR function is called after \fIsudoers\fR has been parsed but +before any policy checks. It returns 1 on success, 0 on failure +(or if the plugin is not configured), and \-1 if a error occurred. +If an error occurs, the plugin may call the plugin_printf function +with \f(CW\*(C`SUDO_CONF_ERROR_MSG\*(C'\fR to present additional error information +to the user. +.Sp +The function arguments are as follows: +.RS 4 +.IP "version" 4 +.IX Item "version" +The version passed in by \fIsudoers\fR allows the plugin to determine the +major and minor version number of the group plugin \s-1API\s0 supported by +\&\fIsudoers\fR. +.IP "plugin_printf" 4 +.IX Item "plugin_printf" +A pointer to a printf-style function that may be used to display +informational or error message to the user. +Returns the number of characters printed on success and \-1 on failure. +.IP "argv" 4 +.IX Item "argv" +A NULL-terminated array of arguments generated from the \fIgroup_plugin\fR +option in \fIsudoers\fR. If no arguments were given, \fIargv\fR will be +\&\s-1NULL\s0. +.RE +.RS 4 +.RE +.IP "cleanup" 4 +.IX Item "cleanup" +.Vb 1 +\& void (*cleanup)(); +.Ve +.Sp +The \fIcleanup\fR function is called when \fIsudoers\fR has finished its +group checks. The plugin should free any memory it has allocated +and close open file handles. +.IP "query" 4 +.IX Item "query" +.Vb 2 +\& int (*query)(const char *user, const char *group, +\& const struct passwd *pwd); +.Ve +.Sp +The \fIquery\fR function is used to ask the group plugin whether \fIuser\fR +is a member of \fIgroup\fR. +.Sp +The function arguments are as follows: +.RS 4 +.IP "user" 4 +.IX Item "user" +The name of the user being looked up in the external group database. +.IP "group" 4 +.IX Item "group" +The name of the group being queried. +.IP "pwd" 4 +.IX Item "pwd" +The password database entry for \fIuser\fR, if any. If \fIuser\fR is not +present in the password database, \fIpwd\fR will be \f(CW\*(C`NULL\*(C'\fR. +.RE +.RS 4 +.RE +.PP +\fIVersion Macros\fR +.IX Subsection "Version Macros" +.PP +.Vb 5 +\& /* Sudoers group plugin version major/minor */ +\& #define GROUP_API_VERSION_MAJOR 1 +\& #define GROUP_API_VERSION_MINOR 0 +\& #define GROUP_API_VERSION ((GROUP_API_VERSION_MAJOR << 16) | \e +\& GROUP_API_VERSION_MINOR) +\& +\& /* Getters and setters for group version */ +\& #define GROUP_API_VERSION_GET_MAJOR(v) ((v) >> 16) +\& #define GROUP_API_VERSION_GET_MINOR(v) ((v) & 0xffff) +\& #define GROUP_API_VERSION_SET_MAJOR(vp, n) do { \e +\& *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \e +\& } while(0) +\& #define GROUP_API_VERSION_SET_MINOR(vp, n) do { \e +\& *(vp) = (*(vp) & 0xffff0000) | (n); \e +\& } while(0) +.Ve +.SH "SEE ALSO" +.IX Header "SEE ALSO" +\&\fIsudoers\fR\|(@mansectform@), \fIsudo\fR\|(@mansectsu@) +.SH "BUGS" +.IX Header "BUGS" +If you feel you have found a bug in \fBsudo\fR, please submit a bug report +at http://www.sudo.ws/sudo/bugs/ +.SH "SUPPORT" +.IX Header "SUPPORT" +Limited free support is available via the sudo-workers mailing list, +see http://www.sudo.ws/mailman/listinfo/sudo\-workers to subscribe or +search the archives. +.SH "DISCLAIMER" +.IX Header "DISCLAIMER" +\&\fBsudo\fR is provided ``\s-1AS\s0 \s-1IS\s0'' and any express or implied warranties, +including, but not limited to, the implied warranties of merchantability +and fitness for a particular purpose are disclaimed. See the \s-1LICENSE\s0 +file distributed with \fBsudo\fR or http://www.sudo.ws/sudo/license.html +for complete details. diff --git a/doc/sudo_plugin.pod b/doc/sudo_plugin.pod new file mode 100644 index 0000000..5702180 --- /dev/null +++ b/doc/sudo_plugin.pod @@ -0,0 +1,1246 @@ +Copyright (c) 2009-2011 Todd C. Miller + +Permission to use, copy, modify, and distribute this software for any +purpose with or without fee is hereby granted, provided that the above +copyright notice and this permission notice appear in all copies. + +THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +=pod + +=head1 NAME + +sudo_plugin - Sudo Plugin API + +=head1 DESCRIPTION + +Starting with version 1.8, B supports a plugin API +for policy and session logging. By default, the I policy +plugin and an associated I/O logging plugin are used. Via the plugin +API, B can be configured to use alternate policy and/or I/O +logging plugins provided by third parties. The plugins to be used +are specified via the F<@sysconfdir@/sudo.conf> file. + +The API is versioned with a major and minor number. The minor +version number is incremented when additions are made. The major +number is incremented when incompatible changes are made. A plugin +should be check the version passed to it and make sure that the +major version matches. + +The plugin API is defined by the C header file. + +=head2 The sudo.conf File + +The F<@sysconfdir@/sudo.conf> file contains plugin configuration directives. +Currently, the only supported keyword is the C directive, +which causes a plugin plugin to be loaded. + +A C line consists of the C keyword, followed by the +I and the I to the shared object containing the +plugin. The I is the name of the C +or C in the plugin shared object. The I +may be fully qualified or relative. If not fully qualified it is +relative to the F<@prefix@/libexec> directory. Any additional +parameters after the I are ignored. Lines that don't begin +with C or C are silently ignored. + +The same shared object may contain multiple plugins, each with a +different symbol name. The shared object file must be owned by uid +0 and only writable by its owner. Because of ambiguities that arise +from composite policies, only a single policy plugin may be specified. +This limitation does not apply to I/O plugins. + + # + # Default @sysconfdir@/sudo.conf file + # + # Format: + # Plugin plugin_name plugin_path + # Path askpass /path/to/askpass + # + # The plugin_path is relative to @prefix@/libexec unless + # fully qualified. + # The plugin_name corresponds to a global symbol in the plugin + # that contains the plugin interface structure. + # + Plugin sudoers_policy sudoers.so + Plugin sudoers_io sudoers.so + +=head2 Policy Plugin API + +A policy plugin must declare and populate a C struct +in the global scope. This structure contains pointers to the functions +that implement the B policy checks. The name of the symbol should +be specified in F<@sysconfdir@/sudo.conf> along with a path to the plugin +so that B can load it. + + struct policy_plugin { + #define SUDO_POLICY_PLUGIN 1 + unsigned int type; /* always SUDO_POLICY_PLUGIN */ + unsigned int version; /* always SUDO_API_VERSION */ + int (*open)(unsigned int version, sudo_conv_t conversation, + sudo_printf_t plugin_printf, char * const settings[], + char * const user_info[], char * const user_env[]); + void (*close)(int exit_status, int error); + int (*show_version)(int verbose); + int (*check_policy)(int argc, char * const argv[], + char *env_add[], char **command_info[], + char **argv_out[], char **user_env_out[]); + int (*list)(int argc, char * const argv[], int verbose, + const char *list_user); + int (*validate)(void); + void (*invalidate)(int remove); + int (*init_session)(struct passwd *pwd); + }; + +The policy_plugin struct has the following fields: + +=over 4 + +=item type + +The C field should always be set to SUDO_POLICY_PLUGIN. + +=item version + +The C field should be set to SUDO_API_VERSION. + +This allows B to determine the API version the plugin was +built against. + +=item open + + int (*open)(unsigned int version, sudo_conv_t conversation, + sudo_printf_t plugin_printf, char * const settings[], + char * const user_info[], char * const user_env[]); + +Returns 1 on success, 0 on failure, -1 if a general error occurred, +or -2 if there was a usage error. In the latter case, B will +print a usage message before it exits. If an error occurs, the +plugin may optionally call the conversation or plugin_printf function +with C to present additional error information +to the user. + +The function arguments are as follows: + +=over 4 + +=item version + +The version passed in by B allows the plugin to determine the +major and minor version number of the plugin API supported by +B. + +=item conversation + +A pointer to the conversation function that can be used by the +plugin to interact with the user (see below). +Returns 0 on success and -1 on failure. + +=item plugin_printf + +A pointer to a printf-style function that may be used to display +informational or error messages (see below). +Returns the number of characters printed on success and -1 on failure. + +=item settings + +A vector of user-supplied B settings in the form of "name=value" +strings. The vector is terminated by a C pointer. These +settings correspond to flags the user specified when running B. +As such, they will only be present when the corresponding flag has +been specified on the command line. + +When parsing I, the plugin should split on the B +equal sign ('=') since the I field will never include one +itself but the I might. + +=over 4 + +=item debug_level=number + +A numeric debug level, from 1-9, if specified via the C<-D> flag. + +=item runas_user=string + +The user name or uid to to run the command as, if specified via the +C<-u> flag. + +=item runas_group=string + +The group name or gid to to run the command as, if specified via +the C<-g> flag. + +=item prompt=string + +The prompt to use when requesting a password, if specified via +the C<-p> flag. + +=item set_home=bool + +Set to true if the user specified the C<-H> flag. If true, set the +C environment variable to the target user's home directory. + +=item preserve_environment=bool + +Set to true if the user specified the C<-E> flag, indicating that +the user wishes to preserve the environment. + +=item run_shell=bool + +Set to true if the user specified the C<-s> flag, indicating that +the user wishes to run a shell. + +=item login_shell=bool + +Set to true if the user specified the C<-i> flag, indicating that +the user wishes to run a login shell. + +=item implied_shell=bool + +If the user does not specify a program on the command line, B +will pass the plugin the path to the user's shell and set +I to true. This allows B with no arguments +to be used similarly to L. If the plugin does not to support +this usage, it may return a value of -2 from the C +function, which will cause B to print a usage message and +exit. + +=item preserve_groups=bool + +Set to true if the user specified the C<-P> flag, indicating that +the user wishes to preserve the group vector instead of setting it +based on the runas user. + +=item ignore_ticket=bool + +Set to true if the user specified the C<-k> flag along with a +command, indicating that the user wishes to ignore any cached +authentication credentials. + +=item noninteractive=bool + +Set to true if the user specified the C<-n> flag, indicating that +B should operate in non-interactive mode. The plugin may +reject a command run in non-interactive mode if user interaction +is required. + +=item login_class=string + +BSD login class to use when setting resource limits and nice value, +if specified by the C<-c> flag. + +=item selinux_role=string + +SELinux role to use when executing the command, if specified by +the C<-r> flag. + +=item selinux_type=string + +SELinux type to use when executing the command, if specified by +the C<-t> flag. + +=item bsdauth_type=string + +Authentication type, if specified by the C<-a> flag, to use on +systems where BSD authentication is supported. + +=item network_addrs=list + +A space-separated list of IP network addresses and netmasks in the +form "addr/netmask", e.g. "192.168.1.2/255.255.255.0". The address +and netmask pairs may be either IPv4 or IPv6, depending on what the +operating system supports. If the address contains a colon (':'), +it is an IPv6 address, else it is IPv4. + +=item progname=string + +The command name that sudo was run as, typically "sudo" or "sudoedit". + +=item sudoedit=bool + +Set to true when the C<-e> flag is is specified or if invoked as +B. The plugin shall substitute an editor into I +in the I function or return C<-2> with a usage error +if the plugin does not support I. For more information, +see the I section. + +=item closefrom=number + +If specified, the user has requested via the C<-C> flag that B +close all files descriptors with a value of I or higher. +The plugin may optionally pass this, or another value, back in the +I list. + +=back + +Additional settings may be added in the future so the plugin should +silently ignore settings that it does not recognize. + +=item user_info + +A vector of information about the user running the command in the form of +"name=value" strings. The vector is terminated by a C pointer. + +When parsing I, the plugin should split on the B +equal sign ('=') since the I field will never include one +itself but the I might. + +=over 4 + +=item user=string + +The name of the user invoking B. + +=item uid=uid_t + +The real user ID of the user invoking B. + +=item gid=gid_t + +The real group ID of the user invoking B. + +=item groups=list + +The user's supplementary group list formatted as a string of +comma-separated group IDs. + +=item cwd=string + +The user's current working directory. + +=item tty=string + +The path to the user's terminal device. If the user has no terminal +device associated with the session, the value will be empty, as in +C. + +=item host=string + +The local machine's hostname as returned by the C +system call. + +=item lines=int + +The number of lines the user's terminal supports. If there is +no terminal device available, a default value of 24 is used. + +=item cols=int + +The number of columns the user's terminal supports. If there is +no terminal device available, a default value of 80 is used. + +=back + +=item user_env + +The user's environment in the form of a C-terminated vector of +"name=value" strings. + +When parsing I, the plugin should split on the B +equal sign ('=') since the I field will never include one +itself but the I might. + +=back + +=item close + + void (*close)(int exit_status, int error); + +The C function is called when the command being run by B +finishes. + +The function arguments are as follows: + +=over 4 + +=item exit_status + +The command's exit status, as returned by the wait(2) system call. +The value of C is undefined if C is non-zero. + +=item error + +If the command could not be executed, this is set to the value of +C set by the execve(2) system call. The plugin is responsible +for displaying error information via the conversation or plugin_printf +function. If the command was successfully executed, the value of +C is 0. + +=back + +=item show_version + + int (*show_version)(int verbose); + +The C function is called by B when the user specifies +the C<-V> option. The plugin may display its version information +to the user via the conversation or plugin_printf function using +C. If the user requests detailed version +information, the verbose flag will be set. + +=item check_policy + + int (*check_policy)(int argc, char * const argv[] + char *env_add[], char **command_info[], + char **argv_out[], char **user_env_out[]); + +The I function is called by B to determine +whether the user is allowed to run the specified commands. + +If the I option was enabled in the I array +passed to the I function, the user has requested I +mode. I is a mechanism for editing one or more files +where an editor is run with the user's credentials instead of with +elevated privileges. B achieves this by creating user-writable +temporary copies of the files to be edited and then overwriting the +originals with the temporary copies after editing is complete. If +the plugin supports B, it should choose the editor to be +used, potentially from a variable in the user's environment, such +as C, and include it in I (note that environment +variables may include command line flags). The files to be edited +should be copied from I into I, separated from the +editor and its arguments by a C<"--"> element. The C<"--"> will +be removed by B before the editor is executed. The plugin +should also set I in the I list. + +The I function returns 1 if the command is allowed, +0 if not allowed, -1 for a general error, or -2 for a usage error +or if B was specified but is unsupported by the plugin. +In the latter case, B will print a usage message before it +exits. If an error occurs, the plugin may optionally call the +conversation or plugin_printf function with C +to present additional error information to the user. + +The function arguments are as follows: + +=over 4 + +=item argc + +The number of elements in I, not counting the final C +pointer. + +=item argv + +The argument vector describing the command the user wishes to run, +in the same form as what would be passed to the execve() system +call. The vector is terminated by a C pointer. + +=item env_add + +Additional environment variables specified by the user on the command +line in the form of a C-terminated vector of "name=value" +strings. The plugin may reject the command if one or more variables +are not allowed to be set, or it may silently ignore such variables. + +When parsing I, the plugin should split on the B +equal sign ('=') since the I field will never include one +itself but the I might. + +=item command_info + +Information about the command being run in the form of "name=value" +strings. These values are used by B to set the execution +environment when running a command. The plugin is responsible for +creating and populating the vector, which must be terminated with +a C pointer. The following values are recognized by B: + +=over 4 + +=item command=string + +Fully qualified path to the command to be executed. + +=item runas_uid=uid + +User ID to run the command as. + +=item runas_euid=uid + +Effective user ID to run the command as. +If not specified, the value of I is used. + +=item runas_gid=gid + +Group ID to run the command as. + +=item runas_egid=gid + +Effective group ID to run the command as. +If not specified, the value of I is used. + +=item runas_groups=list + +The supplementary group vector to use for the command in the form +of a comma-separated list of group IDs. If I +is set, this option is ignored. + +=item login_class=string + +BSD login class to use when setting resource limits and nice value +(optional). This option is only set on systems that support login +classes. + +=item preserve_groups=bool + +If set, B will preserve the user's group vector instead of +initializing the group vector based on C. + +=item cwd=string + +The current working directory to change to when executing the command. + +=item noexec=bool + +If set, prevent the command from executing other programs. + +=item chroot=string + +The root directory to use when running the command. + +=item nice=int + +Nice value (priority) to use when executing the command. The nice +value, if specified, overrides the priority associated with the +I on BSD systems. + +=item umask=octal + +The file creation mask to use when executing the command. + +=item selinux_role=string + +SELinux role to use when executing the command. + +=item selinux_type=string + +SELinux type to use when executing the command. + +=item timeout=int + +Command timeout. If non-zero then when the timeout expires the +command will be killed. + +=item sudoedit=bool + +Set to true when in I mode. The plugin may enable +I mode even if B was not invoked as B. +This allows the plugin to perform command substitution and transparently +enable I when the user attempts to run an editor. + +=item closefrom=number + +If specified, B will close all files descriptors with a value +of I or higher. + +=item iolog_compress=bool + +Set to true if the I/O logging plugins, if any, should compress the +log data. This is a hint to the I/O logging plugin which may choose +to ignore it. + +=item iolog_path=string + +Fully qualified path to the file or directory in which I/O log is +to be stored. This is a hint to the I/O logging plugin which may +choose to ignore it. If no I/O logging plugin is loaded, this +setting has no effect. + +=item iolog_stdin=bool + +Set to true if the I/O logging plugins, if any, should log the +standard input if it is not connected to a terminal device. This +is a hint to the I/O logging plugin which may choose to ignore it. + +=item iolog_stdout=bool + +Set to true if the I/O logging plugins, if any, should log the +standard output if it is not connected to a terminal device. This +is a hint to the I/O logging plugin which may choose to ignore it. + +=item iolog_stderr=bool + +Set to true if the I/O logging plugins, if any, should log the +standard error if it is not connected to a terminal device. This +is a hint to the I/O logging plugin which may choose to ignore it. + +=item iolog_ttyin=bool + +Set to true if the I/O logging plugins, if any, should log all +terminal input. This only includes input typed by the user and not +from a pipe or redirected from a file. This is a hint to the I/O +logging plugin which may choose to ignore it. + +=item iolog_ttyout=bool + +Set to true if the I/O logging plugins, if any, should log all +terminal output. This only includes output to the screen, not +output to a pipe or file. This is a hint to the I/O logging plugin +which may choose to ignore it. + +=item use_pty=bool + +Allocate a pseudo-tty to run the command in, regardless of whether +or not I/O logging is in use. By default, B will only run +the command in a pty when an I/O log plugin is loaded. + +=item set_utmp=bool + +Create a utmp (or utmpx) entry when a pseudo-tty is allocated. By +default, the new entry will be a copy of the user's existing utmp +entry (if any), with the tty, time, type and pid fields updated. + +=item utmp_user=string + +User name to use when constructing a new utmp (or utmpx) entry when +I is enabled. This option can be used to set the user +field in the utmp entry to the user the command runs as rather than +the invoking user. If not set, B will base the new entry on +the invoking user's existing entry. + +=back + +Unsupported values will be ignored. + +=item argv_out + +The C-terminated argument vector to pass to the execve() +system call when executing the command. The plugin is responsible +for allocating and populating the vector. + +=item user_env_out + +The C-terminated environment vector to use when executing the +command. The plugin is responsible for allocating and populating +the vector. + +=back + +=item list + + int (*list)(int verbose, const char *list_user, + int argc, char * const argv[]); + +List available privileges for the invoking user. Returns 1 on +success, 0 on failure and -1 on error. On error, the plugin may +optionally call the conversation or plugin_printf function with +C to present additional error information to +the user. + +Privileges should be output via the conversation or plugin_printf +function using C. + +=over 4 + +=item verbose + +Flag indicating whether to list in verbose mode or not. + +=item list_user + +The name of a different user to list privileges for if the policy +allows it. If C, the plugin should list the privileges of +the invoking user. + +=item argc + +The number of elements in I, not counting the final C +pointer. + +=item argv + +If non-C, an argument vector describing a command the user +wishes to check against the policy in the same form as what would +be passed to the execve() system call. If the command is permitted +by the policy, the fully-qualified path to the command should be +displayed along with any command line arguments. + +=back + +=item validate + + int (*validate)(void); + +The C function is called when B is run with the +C<-v> flag. For policy plugins such as I that cache +authentication credentials, this function will validate and cache +the credentials. + +The C function should be C if the plugin does not +support credential caching. + +Returns 1 on success, 0 on failure and -1 on error. +On error, the plugin may optionally call the conversation or plugin_printf +function with C to present additional +error information to the user. + +=item invalidate + + void (*invalidate)(int remove); + +The C function is called when B is called with +the C<-k> or C<-K> flag. For policy plugins such as I that +cache authentication credentials, this function will invalidate the +credentials. If the I flag is set, the plugin may remove +the credentials instead of simply invalidating them. + +The C function should be C if the plugin does not +support credential caching. + +=item init_session + + int (*init_session)(struct passwd *pwd); + +The C function is called when B sets up the +execution environment for the command, immediately before the +contents of the I list are applied (before the uid +changes). This can be used to do session setup that is not supported +by I, such as opening the PAM session. + +The I argument points to a passwd struct for the user the +command will be run as if the uid the command will run as was found +in the password database, otherwise it will be NULL. + +Returns 1 on success, 0 on failure and -1 on error. +On error, the plugin may optionally call the conversation or plugin_printf +function with C to present additional +error information to the user. + +=back + +=head3 Version macros + + #define SUDO_API_VERSION_GET_MAJOR(v) ((v) >> 16) + #define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffff) + #define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \ + *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \ + } while(0) + #define SUDO_VERSION_SET_MINOR(vp, n) do { \ + *(vp) = (*(vp) & 0xffff0000) | (n); \ + } while(0) + + #define SUDO_API_VERSION_MAJOR 1 + #define SUDO_API_VERSION_MINOR 0 + #define SUDO_API_VERSION ((SUDO_API_VERSION_MAJOR << 16) | \ + SUDO_API_VERSION_MINOR) + +=head2 I/O Plugin API + + struct io_plugin { + #define SUDO_IO_PLUGIN 2 + unsigned int type; /* always SUDO_IO_PLUGIN */ + unsigned int version; /* always SUDO_API_VERSION */ + int (*open)(unsigned int version, sudo_conv_t conversation + sudo_printf_t plugin_printf, char * const settings[], + char * const user_info[], int argc, char * const argv[], + char * const user_env[]); + void (*close)(int exit_status, int error); /* wait status or error */ + int (*show_version)(int verbose); + int (*log_ttyin)(const char *buf, unsigned int len); + int (*log_ttyout)(const char *buf, unsigned int len); + int (*log_stdin)(const char *buf, unsigned int len); + int (*log_stdout)(const char *buf, unsigned int len); + int (*log_stderr)(const char *buf, unsigned int len); + }; + +When an I/O plugin is loaded, B runs the command in a pseudo-tty. +This makes it possible to log the input and output from the user's +session. If any of the standard input, standard output or standard +error do not correspond to a tty, B will open a pipe to capture +the I/O for logging before passing it on. + +The log_ttyin function receives the raw user input from the terminal +device (note that this will include input even when echo is disabled, +such as when a password is read). The log_ttyout function receives +output from the pseudo-tty that is suitable for replaying the user's +session at a later time. The log_stdin, log_stdout and log_stderr +functions are only called if the standard input, standard output +or standard error respectively correspond to something other than +a tty. + +Any of the logging functions may be set to the NULL +pointer if no logging is to be performed. If the open function +returns C<0>, no I/O will be sent to the plugin. + +The io_plugin struct has the following fields: + +=over 4 + +=item type + +The C field should always be set to SUDO_IO_PLUGIN + +=item version + +The C field should be set to SUDO_API_VERSION. + +This allows B to determine the API version the plugin was +built against. + +=item open + + int (*open)(unsigned int version, sudo_conv_t conversation + sudo_printf_t plugin_printf, char * const settings[], + char * const user_info[], int argc, char * const argv[], + char * const user_env[]); + +The I function is run before the I, I +or I functions are called. It is only called if the +version is being requested or the I function has +returned successfully. It returns 1 on success, 0 on failure, -1 +if a general error occurred, or -2 if there was a usage error. In +the latter case, B will print a usage message before it exits. +If an error occurs, the plugin may optionally call the conversation +or plugin_printf function with C to present +additional error information to the user. + +The function arguments are as follows: + +=over 4 + +=item version + +The version passed in by B allows the plugin to determine the +major and minor version number of the plugin API supported by +B. + +=item conversation + +A pointer to the conversation function that may be used by the +I function to display version information (see +show_version below). The conversation function may also be used +to display additional error message to the user. +The conversation function returns 0 on success and -1 on failure. + +=item plugin_printf + +A pointer to a printf-style function that may be used by the +I function to display version information (see +show_version below). The plugin_printf function may also be used +to display additional error message to the user. +The plugin_printf function returns number of characters printed on +success and -1 on failure. + +=item settings + +A vector of user-supplied B settings in the form of "name=value" +strings. The vector is terminated by a C pointer. These +settings correspond to flags the user specified when running B. +As such, they will only be present when the corresponding flag has +been specified on the command line. + +When parsing I, the plugin should split on the B +equal sign ('=') since the I field will never include one +itself but the I might. + +See the L section for a list of all possible settings. + +=item user_info + +A vector of information about the user running the command in the form of +"name=value" strings. The vector is terminated by a C pointer. + +When parsing I, the plugin should split on the B +equal sign ('=') since the I field will never include one +itself but the I might. + +See the L section for a list of all possible strings. + +=item argc + +The number of elements in I, not counting the final C +pointer. + +=item argv + +If non-C, an argument vector describing a command the user +wishes to run in the same form as what would be passed to the +execve() system call. + +=item user_env + +The user's environment in the form of a C-terminated vector of +"name=value" strings. + +When parsing I, the plugin should split on the B +equal sign ('=') since the I field will never include one +itself but the I might. + +=back + +=item close + + void (*close)(int exit_status, int error); + +The C function is called when the command being run by B +finishes. + +The function arguments are as follows: + +=over 4 + +=item exit_status + +The command's exit status, as returned by the wait(2) system call. +The value of C is undefined if C is non-zero. + +=item error + +If the command could not be executed, this is set to the value of +C set by the execve(2) system call. If the command was +successfully executed, the value of C is 0. + +=back + +=item show_version + + int (*show_version)(int verbose); + +The C function is called by B when the user specifies +the C<-V> option. The plugin may display its version information +to the user via the conversation or plugin_printf function using +C. If the user requests detailed version +information, the verbose flag will be set. + +=item log_ttyin + + int (*log_ttyin)(const char *buf, unsigned int len); + +The I function is called whenever data can be read from +the user but before it is passed to the running command. This +allows the plugin to reject data if it chooses to (for instance +if the input contains banned content). Returns C<1> if the data +should be passed to the command, C<0> if the data is rejected +(which will terminate the command) or C<-1> if an error occurred. + +The function arguments are as follows: + +=over 4 + +=item buf + +The buffer containing user input. + +=item len + +The length of I in bytes. + +=back + +=item log_ttyout + + int (*log_ttyout)(const char *buf, unsigned int len); + +The I function is called whenever data can be read from +the command but before it is written to the user's terminal. This +allows the plugin to reject data if it chooses to (for instance +if the output contains banned content). Returns C<1> if the data +should be passed to the user, C<0> if the data is rejected +(which will terminate the command) or C<-1> if an error occurred. + +The function arguments are as follows: + +=over 4 + +=item buf + +The buffer containing command output. + +=item len + +The length of I in bytes. + +=back + +=item log_stdin + + int (*log_stdin)(const char *buf, unsigned int len); + +The I function is only used if the standard input does +not correspond to a tty device. It is called whenever data can be +read from the standard input but before it is passed to the running +command. This allows the plugin to reject data if it chooses to +(for instance if the input contains banned content). Returns C<1> +if the data should be passed to the command, C<0> if the data is +rejected (which will terminate the command) or C<-1> if an error +occurred. + +The function arguments are as follows: + +=over 4 + +=item buf + +The buffer containing user input. + +=item len + +The length of I in bytes. + +=back + +=item log_stdout + + int (*log_stdout)(const char *buf, unsigned int len); + +The I function is only used if the standard output does +not correspond to a tty device. It is called whenever data can be +read from the command but before it is written to the standard +output. This allows the plugin to reject data if it chooses to +(for instance if the output contains banned content). Returns C<1> +if the data should be passed to the user, C<0> if the data is +rejected (which will terminate the command) or C<-1> if an error +occurred. + +The function arguments are as follows: + +=over 4 + +=item buf + +The buffer containing command output. + +=item len + +The length of I in bytes. + +=back + +=item log_stderr + + int (*log_stderr)(const char *buf, unsigned int len); + +The I function is only used if the standard error does +not correspond to a tty device. It is called whenever data can be +read from the command but before it is written to the standard +error. This allows the plugin to reject data if it chooses to +(for instance if the output contains banned content). Returns C<1> +if the data should be passed to the user, C<0> if the data is +rejected (which will terminate the command) or C<-1> if an error +occurred. + +The function arguments are as follows: + +=over 4 + +=item buf + +The buffer containing command output. + +=item len + +The length of I in bytes. + +=back + +=back + +=head3 Version macros + +Same as for the L. + +=head2 Conversation API + +If the plugin needs to interact with the user, it may do so via the +conversation function. A plugin should not attempt to read directly +from the standard input or the user's tty (neither of which are +guaranteed to exist). The caller must include a trailing newline +in C if one is to be printed. + +A printf-style function is also available that can be used to display +informational or error messages to the user, which is usually more +convenient for simple messages where no use input is required. + + struct sudo_conv_message { + #define SUDO_CONV_PROMPT_ECHO_OFF 0x0001 /* do not echo user input */ + #define SUDO_CONV_PROMPT_ECHO_ON 0x0002 /* echo user input */ + #define SUDO_CONV_ERROR_MSG 0x0003 /* error message */ + #define SUDO_CONV_INFO_MSG 0x0004 /* informational message */ + #define SUDO_CONV_PROMPT_MASK 0x0005 /* mask user input */ + #define SUDO_CONV_PROMPT_ECHO_OK 0x1000 /* flag: allow echo if no tty */ + int msg_type; + int timeout; + const char *msg; + }; + + struct sudo_conv_reply { + char *reply; + }; + + typedef int (*sudo_conv_t)(int num_msgs, + const struct sudo_conv_message msgs[], + struct sudo_conv_reply replies[]); + + typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...); + +Pointers to the conversation and printf-style functions are passed +in to the plugin's C function when the plugin is initialized. + +To use the conversation function, the plugin must pass an array of +C and C structures. There must +be a C and C for +each message in the conversation. The plugin is responsible for +freeing the reply buffer filled in to the C, +if any. + +The printf-style function uses the same underlying mechanism as the +conversation function but only supports C and +C for the I parameter. It can be +more convenient than using the conversation function if no user +reply is needed and supports standard printf() escape sequences. + +See the sample plugin for an example of the conversation function usage. + +=head2 Sudoers Group Plugin API + +The I module supports a plugin interface to allow non-Unix +group lookups. This can be used to query a group source other than +the standard Unix group database. A sample group plugin is bundled +with B that implements file-based lookups. Third party group +plugins include a QAS AD plugin available from Quest Software. + +A group plugin must declare and populate a C +struct in the global scope. This structure contains pointers to +the functions that implement plugin initialization, cleanup and +group lookup. + + struct sudoers_group_plugin { + unsigned int version; + int (*init)(int version, sudo_printf_t sudo_printf, + char *const argv[]); + void (*cleanup)(void); + int (*query)(const char *user, const char *group, + const struct passwd *pwd); +}; + +The C struct has the following fields: + +=over 4 + +=item version + +The C field should be set to GROUP_API_VERSION. + +This allows I to determine the API version the group plugin +was built against. + +=item init + + int (*init)(int version, sudo_printf_t plugin_printf, + char *const argv[]); + +The I function is called after I has been parsed but +before any policy checks. It returns 1 on success, 0 on failure +(or if the plugin is not configured), and -1 if a error occurred. +If an error occurs, the plugin may call the plugin_printf function +with C to present additional error information +to the user. + +The function arguments are as follows: + +=over 4 + +=item version + +The version passed in by I allows the plugin to determine the +major and minor version number of the group plugin API supported by +I. + +=item plugin_printf + +A pointer to a printf-style function that may be used to display +informational or error message to the user. +Returns the number of characters printed on success and -1 on failure. + +=item argv + +A NULL-terminated array of arguments generated from the I +option in I. If no arguments were given, I will be +NULL. + +=back + +=item cleanup + + void (*cleanup)(); + +The I function is called when I has finished its +group checks. The plugin should free any memory it has allocated +and close open file handles. + +=item query + + int (*query)(const char *user, const char *group, + const struct passwd *pwd); + +The I function is used to ask the group plugin whether I +is a member of I. + +The function arguments are as follows: + +=over 4 + +=item user + +The name of the user being looked up in the external group database. + +=item group + +The name of the group being queried. + +=item pwd + +The password database entry for I, if any. If I is not +present in the password database, I will be C. + +=back + +=back + +=head3 Version Macros + + /* Sudoers group plugin version major/minor */ + #define GROUP_API_VERSION_MAJOR 1 + #define GROUP_API_VERSION_MINOR 0 + #define GROUP_API_VERSION ((GROUP_API_VERSION_MAJOR << 16) | \ + GROUP_API_VERSION_MINOR) + + /* Getters and setters for group version */ + #define GROUP_API_VERSION_GET_MAJOR(v) ((v) >> 16) + #define GROUP_API_VERSION_GET_MINOR(v) ((v) & 0xffff) + #define GROUP_API_VERSION_SET_MAJOR(vp, n) do { \ + *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \ + } while(0) + #define GROUP_API_VERSION_SET_MINOR(vp, n) do { \ + *(vp) = (*(vp) & 0xffff0000) | (n); \ + } while(0) + +=head1 SEE ALSO + +L, L + +=head1 BUGS + +If you feel you have found a bug in B, please submit a bug report +at http://www.sudo.ws/sudo/bugs/ + +=head1 SUPPORT + +Limited free support is available via the sudo-workers mailing list, +see http://www.sudo.ws/mailman/listinfo/sudo-workers to subscribe or +search the archives. + +=head1 DISCLAIMER + +B is provided ``AS IS'' and any express or implied warranties, +including, but not limited to, the implied warranties of merchantability +and fitness for a particular purpose are disclaimed. See the LICENSE +file distributed with B or http://www.sudo.ws/sudo/license.html +for complete details. diff --git a/sudoers.cat b/doc/sudoers.cat similarity index 81% rename from sudoers.cat rename to doc/sudoers.cat index 2a7a521..a30ffc7 100644 --- a/sudoers.cat +++ b/doc/sudoers.cat @@ -1,13 +1,103 @@ +SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - NNAAMMEE - sudoers - list of which users may execute what + sudoers - default sudo security policy module DDEESSCCRRIIPPTTIIOONN + The _s_u_d_o_e_r_s policy module determines a user's ssuuddoo privileges. It is + the default ssuuddoo policy plugin. The policy is driven by the + _/_e_t_c_/_s_u_d_o_e_r_s file or, optionally in LDAP. The policy format is + described in detail in the "SUDOERS FILE FORMAT" section. For + information on storing _s_u_d_o_e_r_s policy information in LDAP, please see + _s_u_d_o_e_r_s_._l_d_a_p(4). + + AAuutthheennttiiccaattiioonn aanndd LLooggggiinngg + The _s_u_d_o_e_r_s security policy requires that most users authenticate + themselves before they can use ssuuddoo. A password is not required if the + invoking user is root, if the target user is the same as the invoking + user, or if the policy has disabled authentication for the user or + command. Unlike _s_u(1), when _s_u_d_o_e_r_s requires authentication, it + validates the invoking user's credentials, not the target user's (or + root's) credentials. This can be changed via the _r_o_o_t_p_w, _t_a_r_g_e_t_p_w and + _r_u_n_a_s_p_w flags, described later. + + If a user who is not listed in the policy tries to run a command via + ssuuddoo, mail is sent to the proper authorities. The address used for + such mail is configurable via the _m_a_i_l_t_o Defaults entry (described + later) and defaults to root. + + Note that mail will not be sent if an unauthorized user tries to run + ssuuddoo with the --ll or --vv option. This allows users to determine for + themselves whether or not they are allowed to use ssuuddoo. + + If ssuuddoo is run by root and the SUDO_USER environment variable is set, + the _s_u_d_o_e_r_s policy will use this value to determine who the actual user + is. This can be used by a user to log commands through sudo even when + a root shell has been invoked. It also allows the --ee option to remain + useful even when invoked via a sudo-run script or program. Note, + however, that the _s_u_d_o_e_r_s lookup is still done for root, not the user + specified by SUDO_USER. + + _s_u_d_o_e_r_s uses time stamp files for credential caching. Once a user has + been authenticated, a time stamp is updated and the user may then use + sudo without a password for a short period of time (5 minutes unless + overridden by the _t_i_m_e_o_u_t option. By default, _s_u_d_o_e_r_s uses a tty-based + time stamp which means that there is a separate time stamp for each of + a user's login sessions. The _t_t_y___t_i_c_k_e_t_s option can be disabled to + force the use of a single time stamp for all of a user's sessions. + + _s_u_d_o_e_r_s can log both successful and unsuccessful attempts (as well as + errors) to _s_y_s_l_o_g(3), a log file, or both. By default, _s_u_d_o_e_r_s will + log via _s_y_s_l_o_g(3) but this is changeable via the _s_y_s_l_o_g and _l_o_g_f_i_l_e + Defaults settings. + + _s_u_d_o_e_r_s also supports logging a command's input and output streams. + I/O logging is not on by default but can be enabled using the _l_o_g___i_n_p_u_t + and _l_o_g___o_u_t_p_u_t Defaults flags as well as the LOG_INPUT and LOG_OUTPUT + command tags. + + CCoommmmaanndd EEnnvviirroonnmmeenntt + Since environment variables can influence program behavior, _s_u_d_o_e_r_s + provides a means to restrict which variables from the user's + environment are inherited by the command to be run. There are two + distinct ways _s_u_d_o_e_r_s can deal with environment variables. + + By default, the _e_n_v___r_e_s_e_t option is enabled. This causes commands to + be executed with a minimal environment containing TERM, PATH, HOME, + MAIL, SHELL, LOGNAME, USER and USERNAME in addition to variables from + the invoking process permitted by the _e_n_v___c_h_e_c_k and _e_n_v___k_e_e_p options. + This is effectively a whitelist for environment variables. + + If, however, the _e_n_v___r_e_s_e_t option is disabled, any variables not + explicitly denied by the _e_n_v___c_h_e_c_k and _e_n_v___d_e_l_e_t_e options are inherited + from the invoking process. In this case, _e_n_v___c_h_e_c_k and _e_n_v___d_e_l_e_t_e + behave like a blacklist. Since it is not possible to blacklist all + potentially dangerous environment variables, use of the default + _e_n_v___r_e_s_e_t behavior is encouraged. + + In all cases, environment variables with a value beginning with () are + removed as they could be interpreted as bbaasshh functions. The list of + environment variables that ssuuddoo allows or denies is contained in the + output of sudo -V when run as root. + + Note that the dynamic linker on most operating systems will remove + variables that can control dynamic linking from the environment of + setuid executables, including ssuuddoo. Depending on the operating system + this may include _RLD*, DYLD_*, LD_*, LDR_*, LIBPATH, SHLIB_PATH, and + others. These type of variables are removed from the environment + before ssuuddoo even begins execution and, as such, it is not possible for + ssuuddoo to preserve them. + + As a special case, If ssuuddoo's --ii option (initial login) is specified, + _s_u_d_o_e_r_s will initialize the environment regardless of the value of + _e_n_v___r_e_s_e_t. The _D_I_S_P_L_A_Y, _P_A_T_H and _T_E_R_M variables remain unchanged; + _H_O_M_E, _M_A_I_L, _S_H_E_L_L, _U_S_E_R, and _L_O_G_N_A_M_E are set based on the target user. + On Linux and AIX systems the contents of _/_e_t_c_/_e_n_v_i_r_o_n_m_e_n_t are also + included. All other environment variables are removed. + +SSUUDDOOEERRSS FFIILLEE FFOORRMMAATT The _s_u_d_o_e_r_s file is composed of two types of entries: aliases (basically variables) and user specifications (which specify who may run what). @@ -59,18 +149,6 @@ DDEESSCCRRIIPPTTIIOONN Host_Alias ::= NAME '=' Host_List - - -1.7.6 April 9, 2011 1 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - - Cmnd_Alias ::= NAME '=' Cmnd_List NAME ::= [A-Z]([A-Z][0-9]_)* @@ -115,9 +193,10 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) escaped hex mode, e.g. \x20 for space. When using double quotes, any prefix characters must be included inside the quotes. - The nonunix_group and nonunix_gid syntax depends on the underlying - implementation. For instance, the QAS AD backend supports the - following formats: + The actual nonunix_group and nonunix_gid syntax depends on the + underlying group provider plugin (see the _g_r_o_u_p___p_l_u_g_i_n description + below). For instance, the QAS AD plugin supports the following + formats: +o Group in the same domain: "Group Name" @@ -125,17 +204,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) +o Group SID: "S-1-2-34-5678901234-5678901234-5678901234-567" - - -1.7.6 April 9, 2011 2 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - Note that quotes around group names are optional. Unquoted strings must use a backslash (\) to escape spaces and special characters. See "Other special characters and reserved words" for a list of characters @@ -190,18 +258,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) Cmnd ',' Cmnd_List commandname ::= file name | - - - -1.7.6 April 9, 2011 3 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - file name args | file name '""' @@ -256,18 +312,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) Parameters may be ffllaaggss, iinntteeggeerr values, ssttrriinnggss, or lliissttss. Flags are implicitly boolean and can be turned off via the '!' operator. Some - - - -1.7.6 April 9, 2011 4 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - integer, string and list parameters may also be used in a boolean context to disable them. Values may be enclosed in double quotes (") when they contain multiple words. Special characters may be escaped @@ -322,18 +366,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) the group set to any listed in the Runas_List. If no Runas_Spec is specified the command may be run as rroooott and no group may be specified. - - - -1.7.6 April 9, 2011 5 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - A Runas_Spec sets the default for the commands that follow it. What this means is that for the entry: @@ -388,18 +420,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) user aallaann may run any command as either user root or bin, optionally setting the group to operator or system. - - - -1.7.6 April 9, 2011 6 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - SSEELLiinnuuxx__SSppeecc On systems with SELinux support, _s_u_d_o_e_r_s entries may optionally have an SELinux role and/or type associated with a command. If a role or type @@ -454,18 +474,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) aaron shanty = NOEXEC: /usr/bin/more, /usr/bin/vi See the "PREVENTING SHELL ESCAPES" section below for more details on - - - -1.7.6 April 9, 2011 7 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - how NOEXEC works and whether or not it will work on your system. _S_E_T_E_N_V _a_n_d _N_O_S_E_T_E_N_V @@ -521,17 +529,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) in the path name. When matching the command line arguments, however, a slash ddooeess get matched by wildcards. This is to make a path like: - - -1.7.6 April 9, 2011 8 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - /usr/bin/* match _/_u_s_r_/_b_i_n_/_w_h_o but not _/_u_s_r_/_b_i_n_/_X_1_1_/_x_t_e_r_m. @@ -586,18 +583,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) in the file names can be used to avoid such problems. Note that unlike files included via #include, vviissuuddoo will not edit the - - - -1.7.6 April 9, 2011 9 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - files in a #includedir directory unless one of them contains a syntax error. It is still possible to run vviissuuddoo with the -f flag to edit the files directly. @@ -652,18 +637,6 @@ SSUUDDOOEERRSS OOPPTTIIOONNSS authenticate If set, users must authenticate themselves via a password (or other means of authentication) before they - - - -1.7.6 April 9, 2011 10 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - may run commands. This default may be overridden via the PASSWD and NOPASSWD tags. This flag is _o_n by default. @@ -718,18 +691,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) flag is _o_f_f by default. fqdn Set this flag if you want to put fully qualified host - - - -1.7.6 April 9, 2011 11 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - names in the _s_u_d_o_e_r_s file. I.e., instead of myhost you would use myhost.mydomain.edu. You may still use the short form if you wish (and even mix the two). Beware @@ -777,7 +738,8 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) Input is logged to the directory specified by the _i_o_l_o_g___d_i_r option (_/_v_a_r_/_l_o_g_/_s_u_d_o_-_i_o by default) using a unique session ID that is included in the normal ssuuddoo - log line, prefixed with _T_S_I_D_=. + log line, prefixed with _T_S_I_D_=. The _i_o_l_o_g___f_i_l_e option + may be used to control the format of the session ID. Note that user input may contain sensitive information such as passwords (even if they are not echoed to the @@ -785,17 +747,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) unencrypted. In most cases, logging the command output via _l_o_g___o_u_t_p_u_t is all that is required. - - -1.7.6 April 9, 2011 12 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - log_output If set, ssuuddoo will run the command in a _p_s_e_u_d_o _t_t_y and log all output that is sent to the screen, similar to the _s_c_r_i_p_t(1) command. If the standard output or @@ -807,7 +758,8 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) Output is logged to the directory specified by the _i_o_l_o_g___d_i_r option (_/_v_a_r_/_l_o_g_/_s_u_d_o_-_i_o by default) using a unique session ID that is included in the normal ssuuddoo - log line, prefixed with _T_S_I_D_=. + log line, prefixed with _T_S_I_D_=. The _i_o_l_o_g___f_i_l_e option + may be used to control the format of the session ID. Output logs may be viewed with the _s_u_d_o_r_e_p_l_a_y(1m) utility, which can also be used to list or search the @@ -851,17 +803,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) well as the "PREVENTING SHELL ESCAPES" section at the end of this manual. This flag is _o_f_f by default. - - -1.7.6 April 9, 2011 13 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - path_info Normally, ssuuddoo will tell the user when a command could not be found in their PATH environment variable. Some sites may wish to disable this as it could be used to @@ -916,18 +857,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) by default. runaspw If set, ssuuddoo will prompt for the password of the user - - - -1.7.6 April 9, 2011 14 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - defined by the _r_u_n_a_s___d_e_f_a_u_l_t option (defaults to root) instead of the password of the invoking user. This flag is _o_f_f by default. @@ -953,13 +882,21 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) disabled, entries in the _e_n_v___k_e_e_p list will override the value of _s_e_t___l_o_g_n_a_m_e. This flag is _o_n by default. + set_utmp When enabled, ssuuddoo will create an entry in the utmp (or + utmpx) file when a pseudo-tty is allocated. A pseudo- + tty is allocated by ssuuddoo when the _l_o_g___i_n_p_u_t, _l_o_g___o_u_t_p_u_t + or _u_s_e___p_t_y flags are enabled. By default, the new + entry will be a copy of the user's existing utmp entry + (if any), with the tty, time, type and pid fields + updated. This flag is _o_n by default. + setenv Allow the user to disable the _e_n_v___r_e_s_e_t option from the - command line. Additionally, environment variables set - via the command line are not subject to the - restrictions imposed by _e_n_v___c_h_e_c_k, _e_n_v___d_e_l_e_t_e, or - _e_n_v___k_e_e_p. As such, only trusted users should be - allowed to set variables in this manner. This flag is - _o_f_f by default. + command line via the --EE option. Additionally, + environment variables set via the command line are not + subject to the restrictions imposed by _e_n_v___c_h_e_c_k, + _e_n_v___d_e_l_e_t_e, or _e_n_v___k_e_e_p. As such, only trusted users + should be allowed to set variables in this manner. + This flag is _o_f_f by default. shell_noargs If set and ssuuddoo is invoked with no arguments it acts as if the --ss option had been given. That is, it runs a @@ -982,18 +919,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) targetpw If set, ssuuddoo will prompt for the password of the user specified by the --uu option (defaults to root) instead of the password of the invoking user. In addition, the - - - -1.7.6 April 9, 2011 15 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - timestamp file name will include the target user's name. Note that this flag precludes the use of a uid not listed in the passwd database as an argument to the @@ -1023,7 +948,13 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) run under ssuuddoo could conceivably fork a background process that retains to the user's terminal device after the main program has finished executing. Use of - this option will make that impossible. + this option will make that impossible. This flag is + _o_f_f by default. + + utmp_runas If set, ssuuddoo will store the name of the runas user when + updating the utmp (or utmpx) file. By default, ssuuddoo + stores the name of the invoking user. This flag is _o_f_f + by default. visiblepw By default, ssuuddoo will refuse to run if the user must enter a password but it is not possible to disable echo @@ -1048,18 +979,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) IInntteeggeerrss tthhaatt ccaann bbee uusseedd iinn aa bboooolleeaann ccoonntteexxtt: - - - -1.7.6 April 9, 2011 16 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - loglinelen Number of characters per line for the file log. This value is used to decide when to wrap lines for nicer log files. This has no effect on the syslog log file, @@ -1104,38 +1023,77 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) possible, or the first editor in the list that exists and is executable. The default is "vi". - iolog_dir The directory in which to store input/output logs when - the _l_o_g___i_n_p_u_t or _l_o_g___o_u_t_p_u_t options are enabled or when - the LOG_INPUT or LOG_OUTPUT tags are present for a - command. The default is "/var/log/sudo-io". + iolog_dir The top-level directory to use when constructing the + path name for the input/output log directory. Only + used if the _l_o_g___i_n_p_u_t or _l_o_g___o_u_t_p_u_t options are enabled + or when the LOG_INPUT or LOG_OUTPUT tags are present + for a command. The session sequence number, if any, is + stored in the directory. The default is + "/var/log/sudo-io". - mailsub Subject of the mail sent to the _m_a_i_l_t_o user. The escape - %h will expand to the host name of the machine. - Default is *** SECURITY information for %h ***. + The following percent (`%') escape sequences are + supported: - noexec_file Path to a shared library containing dummy versions of + %{seq} + expanded to a monotonically increasing base-36 + sequence number, such as 0100A5, where every two + digits are used to form a new directory, e.g. + _0_1_/_0_0_/_A_5 + %{user} + expanded to the invoking user's login name + %{group} + expanded to the name of the invoking user's real + group ID -1.7.6 April 9, 2011 17 + %{runas_user} + expanded to the login name of the user the command + will be run as (e.g. root) + %{runas_group} + expanded to the group name of the user the command + will be run as (e.g. wheel) + %{hostname} + expanded to the local host name without the domain + name + + %{command} + expanded to the base name of the command being run + + In addition, any escape sequences supported by the + system's _s_t_r_f_t_i_m_e_(_) function will be expanded. + + To include a literal `%' character, the string `%%' + should be used. + Path names that end in six or more Xs will have the Xs + replaced with a unique combination of digits and + letters, similar to the _m_k_t_e_m_p_(_) function. + iolog_file The path name, relative to _i_o_l_o_g___d_i_r, in which to store + input/output logs when the _l_o_g___i_n_p_u_t or _l_o_g___o_u_t_p_u_t + options are enabled or when the LOG_INPUT or LOG_OUTPUT + tags are present for a command. Note that _i_o_l_o_g___f_i_l_e + may contain directory components. The default is + "%{seq}". -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) + See the _i_o_l_o_g___d_i_r option above for a list of supported + percent (`%') escape sequences. + mailsub Subject of the mail sent to the _m_a_i_l_t_o user. The escape + %h will expand to the host name of the machine. + Default is *** SECURITY information for %h ***. - the _e_x_e_c_v_(_), _e_x_e_c_v_e_(_) and _f_e_x_e_c_v_e_(_) library functions - that just return an error. This is used to implement - the _n_o_e_x_e_c functionality on systems that support - LD_PRELOAD or its equivalent. Defaults to - _/_u_s_r_/_l_o_c_a_l_/_l_i_b_e_x_e_c_/_s_u_d_o___n_o_e_x_e_c_._s_o. + noexec_file This option is deprecated and will be removed in a + future release of ssuuddoo. The path to the noexec file + should now be set in the _/_e_t_c_/_s_u_d_o_._c_o_n_f file. passprompt The default prompt to use when asking for a password; can be overridden via the --pp option or the SUDO_PROMPT environment variable. The following percent (`%') - escapes are supported: + escape sequences are supported: %H expanded to the local host name including the domain name (on if the machine's host name is fully @@ -1166,32 +1124,25 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) runas_default The default user to run commands as if the --uu option is not specified on the command line. This defaults to - root. Note that if _r_u_n_a_s___d_e_f_a_u_l_t is set it mmuusstt occur - before any Runas_Alias specifications. + root. syslog_badpri Syslog priority to use when user authenticates unsuccessfully. Defaults to alert. + The following syslog priorities are supported: aalleerrtt, + ccrriitt, ddeebbuugg, eemmeerrgg, eerrrr, iinnffoo, nnoottiiccee, and wwaarrnniinngg. + syslog_goodpri Syslog priority to use when user authenticates successfully. Defaults to notice. + See syslog_badpri for the list of supported syslog + priorities. + sudoers_locale Locale to use when parsing the sudoers file, logging commands, and sending email. Note that changing the locale may affect how sudoers is interpreted. Defaults to "C". - - - -1.7.6 April 9, 2011 18 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - timestampdir The directory in which ssuuddoo stores its timestamp files. The default is _/_v_a_r_/_a_d_m_/_s_u_d_o. @@ -1206,16 +1157,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) SSttrriinnggss tthhaatt ccaann bbee uusseedd iinn aa bboooolleeaann ccoonntteexxtt: - askpass The _a_s_k_p_a_s_s option specifies the fully qualified path to a - helper program used to read the user's password when no - terminal is available. This may be the case when ssuuddoo is - executed from a graphical (as opposed to text-based) - application. The program specified by _a_s_k_p_a_s_s should - display the argument passed to it as the prompt and write - the user's password to the standard output. The value of - _a_s_k_p_a_s_s may be overridden by the SUDO_ASKPASS environment - variable. - env_file The _e_n_v___f_i_l_e options specifies the fully qualified path to a file containing variables to be set in the environment of the program being run. Entries in this file should either @@ -1228,6 +1169,24 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) Users in this group are exempt from password and PATH requirements. This is not set by default. + group_plugin + A string containing a _s_u_d_o_e_r_s group plugin with optional + arguments. This can be used to implement support for the + nonunix_group syntax described earlier. The string should + consist of the plugin path, either fully-qualified or + relative to the _/_u_s_r_/_l_o_c_a_l_/_l_i_b_e_x_e_c directory, followed by + any configuration arguments the plugin requires. These + arguments (if any) will be passed to the plugin's + initialization function. If arguments are present, the + string must be enclosed in double quotes ("). + + For example, given _/_e_t_c_/_s_u_d_o_-_g_r_o_u_p, a group file in Unix + group format, the sample group plugin can be used: + + Defaults sudo_plugin="sample_group.so /etc/sudo-group" + + For more information see _s_u_d_o___p_l_u_g_i_n(4). + lecture This option controls when a short lecture will be printed along with the password prompt. It has the following possible values: @@ -1247,17 +1206,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) will be used in place of the standard lecture if the named file exists. By default, ssuuddoo uses a built-in lecture. - - -1.7.6 April 9, 2011 19 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - listpw This option controls when a password will be required when a user runs ssuuddoo with the --ll option. It has the following possible values: @@ -1309,21 +1257,14 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) syslog Syslog facility if syslog is being used for logging (negate to disable syslog logging). Defaults to auth. + The following syslog facilities are supported: aauutthhpprriivv (if + your OS supports it), aauutthh, ddaaeemmoonn, uusseerr, llooccaall00, llooccaall11, + llooccaall22, llooccaall33, llooccaall44, llooccaall55, llooccaall66, and llooccaall77. + verifypw This option controls when a password will be required when a user runs ssuuddoo with the --vv option. It has the following possible values: - - -1.7.6 April 9, 2011 20 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - all All the user's _s_u_d_o_e_r_s entries for the current host must have the NOPASSWD flag set to avoid entering a password. @@ -1378,29 +1319,10 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) be a double-quoted, space-separated list or a single value without double-quotes. The list can be replaced, added to, deleted from, or disabled by using the =, +=, - - - -1.7.6 April 9, 2011 21 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - -=, and ! operators respectively. The default list of variables to keep is displayed when ssuuddoo is run by root with the _-_V option. - When logging via _s_y_s_l_o_g(3), ssuuddoo accepts the following values for the - syslog facility (the value of the ssyysslloogg Parameter): aauutthhpprriivv (if your - OS supports it), aauutthh, ddaaeemmoonn, uusseerr, llooccaall00, llooccaall11, llooccaall22, llooccaall33, - llooccaall44, llooccaall55, llooccaall66, and llooccaall77. The following syslog priorities - are supported: aalleerrtt, ccrriitt, ddeebbuugg, eemmeerrgg, eerrrr, iinnffoo, nnoottiiccee, and - wwaarrnniinngg. - FFIILLEESS _/_e_t_c_/_s_u_d_o_e_r_s List of who can run what @@ -1410,6 +1332,12 @@ FFIILLEESS _/_v_a_r_/_l_o_g_/_s_u_d_o_-_i_o I/O log files + _/_v_a_r_/_a_d_m_/_s_u_d_o Directory containing time stamps for the + _s_u_d_o_e_r_s security policy + + _/_e_t_c_/_e_n_v_i_r_o_n_m_e_n_t Initial environment for --ii mode on Linux and + AIX + EEXXAAMMPPLLEESS Below are example _s_u_d_o_e_r_s entries. Admittedly, some of these are a bit contrived. First, we allow a few environment variables to pass and @@ -1444,18 +1372,6 @@ EEXXAAMMPPLLEESS Cmnd_Alias DUMPS = /usr/bin/mt, /usr/sbin/dump, /usr/sbin/rdump,\ /usr/sbin/restore, /usr/sbin/rrestore Cmnd_Alias KILL = /usr/bin/kill - - - -1.7.6 April 9, 2011 22 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - Cmnd_Alias PRINTING = /usr/sbin/lpc, /usr/bin/lprm Cmnd_Alias SHUTDOWN = /usr/sbin/shutdown Cmnd_Alias HALT = /usr/sbin/halt @@ -1510,18 +1426,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) The user jjaacckk may run any command on the machines in the _C_S_N_E_T_S alias (the networks 128.138.243.0, 128.138.204.0, and 128.138.242.0). Of those networks, only 128.138.204.0 has an explicit netmask (in CIDR - - - -1.7.6 April 9, 2011 23 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - notation) indicating it is a class C network. For the other networks in _C_S_N_E_T_S, the local machine's netmask will be used during matching. @@ -1576,18 +1480,6 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) john ALPHA = /usr/bin/su [!-]*, !/usr/bin/su *root* - - - -1.7.6 April 9, 2011 24 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - On the _A_L_P_H_A machines, user jjoohhnn may su to anyone except root but he is not allowed to specify any options to the _s_u(1) command. @@ -1642,18 +1534,6 @@ SSEECCUURRIITTYY NNOOTTEESS Furthermore, if the _f_a_s_t___g_l_o_b option is in use, it is not possible to reliably negate commands where the path name includes globbing (aka - - - -1.7.6 April 9, 2011 25 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - wildcard) characters. This is because the C library's _f_n_m_a_t_c_h(3) function cannot resolve relative paths. While this is typically only an inconvenience for rules that grant privileges, it can result in a @@ -1694,38 +1574,16 @@ PPRREEVVEENNTTIINNGG SSHHEELLLL EESSCCAAPPEESS executables and foreign executables running under binary emulation are not affected. - To tell whether or not ssuuddoo supports _n_o_e_x_e_c, you can run the - following as root: + The _n_o_e_x_e_c feature is known to work on SunOS, Solaris, *BSD, + Linux, IRIX, Tru64 UNIX, MacOS X, HP-UX 11.x and AIX 5.3 and + above. It should be supported on most operating systems that + support the LD_PRELOAD environment variable. Check your + operating system's manual pages for the dynamic linker + (usually ld.so, ld.so.1, dyld, dld.sl, rld, or loader) to see + if LD_PRELOAD is supported. - sudo -V | grep "dummy exec" - - If the resulting output contains a line that begins with: - - File containing dummy exec functions: - - then ssuuddoo may be able to replace the exec family of functions - in the standard library with its own that simply return an - error. Unfortunately, there is no foolproof way to know - whether or not _n_o_e_x_e_c will work at compile-time. _n_o_e_x_e_c - should work on SunOS, Solaris, *BSD, Linux, IRIX, Tru64 UNIX, - - - -1.7.6 April 9, 2011 26 - - - - - -SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) - - - MacOS X, and HP-UX 11.x. It is known nnoott to work on AIX and - UnixWare. _n_o_e_x_e_c is expected to work on most operating - systems that support the LD_PRELOAD environment variable. - Check your operating system's manual pages for the dynamic - linker (usually ld.so, ld.so.1, dyld, dld.sl, rld, or loader) - to see if LD_PRELOAD is supported. + On Solaris 10 and higher, _n_o_e_x_e_c uses Solaris privileges + instead of the LD_PRELOAD environment variable. To enable _n_o_e_x_e_c for a command, use the NOEXEC tag as documented in the User Specification section above. Here is @@ -1737,7 +1595,8 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) with _n_o_e_x_e_c enabled. This will prevent those two commands from executing other commands (such as a shell). If you are unsure whether or not your system is capable of supporting - _n_o_e_x_e_c you can always just try it out and see if it works. + _n_o_e_x_e_c you can always just try it out and check whether shell + escapes work when _n_o_e_x_e_c is enabled. Note that restricting shell escapes is not a panacea. Programs running as root are still capable of many potentially hazardous operations @@ -1745,8 +1604,53 @@ SUDOERS(4) MAINTENANCE COMMANDS SUDOERS(4) privilege escalation. In the specific case of an editor, a safer approach is to give the user permission to run ssuuddooeeddiitt. +SSEECCUURRIITTYY NNOOTTEESS + _s_u_d_o_e_r_s will check the ownership of its time stamp directory + (_/_v_a_r_/_a_d_m_/_s_u_d_o by default) and ignore the directory's contents if it is + not owned by root or if it is writable by a user other than root. On + systems that allow non-root users to give away files via _c_h_o_w_n(2), if + the time stamp directory is located in a world-writable directory + (e.g., _/_t_m_p), it is possible for a user to create the time stamp + directory before ssuuddoo is run. However, because _s_u_d_o_e_r_s checks the + ownership and mode of the directory and its contents, the only damage + that can be done is to "hide" files by putting them in the time stamp + dir. This is unlikely to happen since once the time stamp dir is owned + by root and inaccessible by any other user, the user placing files + there would be unable to get them back out. + + _s_u_d_o_e_r_s will not honor time stamps set far in the future. Time stamps + with a date greater than current_time + 2 * TIMEOUT will be ignored and + sudo will log and complain. This is done to keep a user from creating + his/her own time stamp with a bogus date on systems that allow users to + give away files if the time stamp directory is located in a world- + writable directory. + + On systems where the boot time is available, _s_u_d_o_e_r_s will ignore time + stamps that date from before the machine booted. + + Since time stamp files live in the file system, they can outlive a + user's login session. As a result, a user may be able to login, run a + command with ssuuddoo after authenticating, logout, login again, and run + ssuuddoo without authenticating so long as the time stamp file's + modification time is within 5 minutes (or whatever the timeout is set + to in _s_u_d_o_e_r_s). When the _t_t_y___t_i_c_k_e_t_s option is enabled, the time stamp + has per-tty granularity but still may outlive the user's session. On + Linux systems where the devpts filesystem is used, Solaris systems with + the devices filesystem, as well as other systems that utilize a devfs + filesystem that monotonically increase the inode number of devices as + they are created (such as Mac OS X), _s_u_d_o_e_r_s is able to determine when + a tty-based time stamp file is stale and will ignore it. + Administrators should not rely on this feature as it is not universally + available. + + If users have sudo ALL there is nothing to prevent them from creating + their own program that gives them a root shell (or making their own + copy of a shell) regardless of any '!' elements in the user + specification. + SSEEEE AALLSSOO - _r_s_h(1), _s_u(1), _f_n_m_a_t_c_h(3), _g_l_o_b(3), _s_u_d_o(1m), _v_i_s_u_d_o(8) + _r_s_h(1), _s_u(1), _f_n_m_a_t_c_h(3), _g_l_o_b(3), _m_k_t_e_m_p(3), _s_t_r_f_t_i_m_e(3), + _s_u_d_o_e_r_s_._l_d_a_p(4), _s_u_d_o___p_l_u_g_i_n(1m), _s_u_d_o(1m), _v_i_s_u_d_o(1m) CCAAVVEEAATTSS The _s_u_d_o_e_r_s file should aallwwaayyss be edited by the vviissuuddoo command which @@ -1777,6 +1681,4 @@ DDIISSCCLLAAIIMMEERR -1.7.6 April 9, 2011 27 - - +1.8.1p2 May 16, 2011 SUDOERS(4) diff --git a/sudoers.ldap.cat b/doc/sudoers.ldap.cat similarity index 94% rename from sudoers.ldap.cat rename to doc/sudoers.ldap.cat index 8b14333..19f3294 100644 --- a/sudoers.ldap.cat +++ b/doc/sudoers.ldap.cat @@ -1,9 +1,7 @@ +SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) -SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) - - NNAAMMEE sudoers.ldap - sudo LDAP configuration @@ -58,18 +56,6 @@ DDEESSCCRRIIPPTTIIOONN Sudo first looks for the cn=default entry in the SUDOers container. If found, the multi-valued sudoOption attribute is parsed in the same - - - -1.7.6 April 9, 2011 1 - - - - - -SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) - - manner as a global Defaults line in _/_e_t_c_/_s_u_d_o_e_r_s. In the following example, the SSH_AUTH_SOCK variable will be preserved in the environment for all users. @@ -124,18 +110,6 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) A timestamp in the form yyyymmddHHMMZ that can be used to provide a start date/time for when the sudoRole will be valid. If multiple sudoNotBefore entries are present, the earliest is used. Note that - - - -1.7.6 April 9, 2011 2 - - - - - -SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) - - timestamps must be in Coordinated Universal Time (UTC), not the local timezone. @@ -190,18 +164,6 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) that the user belongs to. (The special ALL tag is matched in this query too.) If no match is returned for the user's name and groups, a third query returns all entries containing user netgroups and checks to - - - -1.7.6 April 9, 2011 3 - - - - - -SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) - - see if the user belongs to any of them. If timed entries are enabled with the SSUUDDOOEERRSS__TTIIMMEEDD configuration @@ -255,19 +217,6 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) currently ignored. For example, the following attributes do not behave the way one might expect. - - - - -1.7.6 April 9, 2011 4 - - - - - -SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) - - # does not match all but joe # rather, does not match anyone sudoUser: !joe @@ -323,17 +272,6 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) commercial versions of Unix are only capable of supporting one or the other. - - -1.7.6 April 9, 2011 5 - - - - - -SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) - - HHOOSSTT name[:port] ... If no UURRII is specified, the HHOOSSTT parameter specifies a whitespace- delimited list of LDAP servers to connect to. Each host may @@ -388,18 +326,6 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) in a moderate amount of debugging information. A value of 2 shows the results of the matches themselves. This parameter should not be set in a production environment as the extra information is - - - -1.7.6 April 9, 2011 6 - - - - - -SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) - - likely to confuse users. BBIINNDDDDNN DN @@ -453,19 +379,6 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) TTLLSS__CCAACCEERRTT file name An alias for TTLLSS__CCAACCEERRTTFFIILLEE for OpenLDAP compatibility. - - - - -1.7.6 April 9, 2011 7 - - - - - -SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) - - TTLLSS__CCAACCEERRTTFFIILLEE file name The path to a certificate authority bundle which contains the certificates for all the Certificate Authorities the client knows @@ -519,19 +432,6 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) the OpenSSL manual for a list of valid ciphers. This option is only supported by the OpenLDAP libraries. - - - - -1.7.6 April 9, 2011 8 - - - - - -SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) - - UUSSEE__SSAASSLL on/true/yes/off/false/no Enable UUSSEE__SSAASSLL for LDAP servers that support SASL authentication. @@ -586,18 +486,6 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) sudoers: files - - - -1.7.6 April 9, 2011 9 - - - - - -SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) - - Note that _/_e_t_c_/_n_s_s_w_i_t_c_h_._c_o_n_f is supported even when the underlying operating system does not use an nsswitch.conf file. @@ -652,18 +540,6 @@ EEXXAAMMPPLLEESS #uri ldaps://secureldapserver #uri ldaps://secureldapserver ldap://ldapserver # - - - -1.7.6 April 9, 2011 10 - - - - - -SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) - - # The amount of time, in seconds, to wait while trying to connect to # an LDAP server. bind_timelimit 30 @@ -718,18 +594,6 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) #tls_randfile /etc/egd-pool # # You may restrict which ciphers are used. Consult your SSL - - - -1.7.6 April 9, 2011 11 - - - - - -SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) - - # documentation for which options go here. # Only supported when using OpenLDAP. # @@ -784,18 +648,6 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) attributetype ( 1.3.6.1.4.1.15953.9.1.2 NAME 'sudoHost' - - - -1.7.6 April 9, 2011 12 - - - - - -SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) - - DESC 'Host(s) who may run sudo' EQUALITY caseExactIA5Match SUBSTR caseExactIA5SubstringsMatch @@ -850,18 +702,6 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) DESC 'an integer to order the sudoRole entries' EQUALITY integerMatch ORDERING integerOrderingMatch - - - -1.7.6 April 9, 2011 13 - - - - - -SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) - - SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 ) objectclass ( 1.3.6.1.4.1.15953.9.2.1 NAME 'sudoRole' SUP top STRUCTURAL @@ -873,7 +713,7 @@ SUDOERS.LDAP(4) MAINTENANCE COMMANDS SUDOERS.LDAP(4) ) SSEEEE AALLSSOO - _l_d_a_p_._c_o_n_f(4), _s_u_d_o_e_r_s(5) + _l_d_a_p_._c_o_n_f(4), _s_u_d_o_e_r_s(4) CCAAVVEEAATTSS Note that there are differences in the way that LDAP-based _s_u_d_o_e_r_s is @@ -898,27 +738,4 @@ DDIISSCCLLAAIIMMEERR - - - - - - - - - - - - - - - - - - - - - -1.7.6 April 9, 2011 14 - - +1.8.1p2 May 16, 2011 SUDOERS.LDAP(4) diff --git a/sudoers.ldap.man.in b/doc/sudoers.ldap.man.in similarity index 99% rename from sudoers.ldap.man.in rename to doc/sudoers.ldap.man.in index 74cafec..4ad1a47 100644 --- a/sudoers.ldap.man.in +++ b/doc/sudoers.ldap.man.in @@ -140,7 +140,7 @@ .\" ======================================================================== .\" .IX Title "SUDOERS.LDAP @mansectform@" -.TH SUDOERS.LDAP @mansectform@ "April 9, 2011" "1.7.6" "MAINTENANCE COMMANDS" +.TH SUDOERS.LDAP @mansectform@ "May 16, 2011" "1.8.1p2" "MAINTENANCE COMMANDS" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -894,7 +894,7 @@ proper \f(CW\*(C`include\*(C'\fR line in \f(CW\*(C`slapd.conf\*(C'\fR and restar .Ve .SH "SEE ALSO" .IX Header "SEE ALSO" -\&\fIldap.conf\fR\|(@mansectform@), \fIsudoers\fR\|(5) +\&\fIldap.conf\fR\|(@mansectform@), \fIsudoers\fR\|(@mansectform@) .SH "CAVEATS" .IX Header "CAVEATS" Note that there are differences in the way that LDAP-based \fIsudoers\fR diff --git a/sudoers.ldap.pod b/doc/sudoers.ldap.pod similarity index 100% rename from sudoers.ldap.pod rename to doc/sudoers.ldap.pod diff --git a/sudoers.man.in b/doc/sudoers.man.in similarity index 83% rename from sudoers.man.in rename to doc/sudoers.man.in index 531ead6..90868c8 100644 --- a/sudoers.man.in +++ b/doc/sudoers.man.in @@ -148,15 +148,111 @@ .\" ======================================================================== .\" .IX Title "SUDOERS @mansectform@" -.TH SUDOERS @mansectform@ "April 9, 2011" "1.7.6" "MAINTENANCE COMMANDS" +.TH SUDOERS @mansectform@ "May 16, 2011" "1.8.1p2" "MAINTENANCE COMMANDS" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l .nh .SH "NAME" -sudoers \- list of which users may execute what +sudoers \- default sudo security policy module .SH "DESCRIPTION" .IX Header "DESCRIPTION" +The \fIsudoers\fR policy module determines a user's \fBsudo\fR privileges. +It is the default \fBsudo\fR policy plugin. The policy is driven by +the \fI@sysconfdir@/sudoers\fR file or, optionally in \s-1LDAP\s0. The policy +format is described in detail in the \*(L"\s-1SUDOERS\s0 \s-1FILE\s0 \s-1FORMAT\s0\*(R" +section. For information on storing \fIsudoers\fR policy information +in \s-1LDAP\s0, please see \fIsudoers.ldap\fR\|(@mansectform@). +.SS "Authentication and Logging" +.IX Subsection "Authentication and Logging" +The \fIsudoers\fR security policy requires that most users authenticate +themselves before they can use \fBsudo\fR. A password is not required +if the invoking user is root, if the target user is the same as the +invoking user, or if the policy has disabled authentication for the +user or command. Unlike \fIsu\fR\|(1), when \fIsudoers\fR requires +authentication, it validates the invoking user's credentials, not +the target user's (or root's) credentials. This can be changed via +the \fIrootpw\fR, \fItargetpw\fR and \fIrunaspw\fR flags, described later. +.PP +If a user who is not listed in the policy tries to run a command +via \fBsudo\fR, mail is sent to the proper authorities. The address +used for such mail is configurable via the \fImailto\fR Defaults entry +(described later) and defaults to \f(CW\*(C`@mailto@\*(C'\fR. +.PP +Note that mail will not be sent if an unauthorized user tries to +run \fBsudo\fR with the \fB\-l\fR or \fB\-v\fR option. This allows users to +determine for themselves whether or not they are allowed to use +\&\fBsudo\fR. +.PP +If \fBsudo\fR is run by root and the \f(CW\*(C`SUDO_USER\*(C'\fR environment variable +is set, the \fIsudoers\fR policy will use this value to determine who +the actual user is. This can be used by a user to log commands +through sudo even when a root shell has been invoked. It also +allows the \fB\-e\fR option to remain useful even when invoked via a +sudo-run script or program. Note, however, that the \fIsudoers\fR +lookup is still done for root, not the user specified by \f(CW\*(C`SUDO_USER\*(C'\fR. +.PP +\&\fIsudoers\fR uses time stamp files for credential caching. Once a +user has been authenticated, a time stamp is updated and the user +may then use sudo without a password for a short period of time +(\f(CW\*(C`@timeout@\*(C'\fR minutes unless overridden by the \fItimeout\fR option. +By default, \fIsudoers\fR uses a tty-based time stamp which means that +there is a separate time stamp for each of a user's login sessions. +The \fItty_tickets\fR option can be disabled to force the use of a +single time stamp for all of a user's sessions. +.PP +\&\fIsudoers\fR can log both successful and unsuccessful attempts (as well +as errors) to \fIsyslog\fR\|(3), a log file, or both. By default, \fIsudoers\fR +will log via \fIsyslog\fR\|(3) but this is changeable via the \fIsyslog\fR +and \fIlogfile\fR Defaults settings. +.PP +\&\fIsudoers\fR also supports logging a command's input and output +streams. I/O logging is not on by default but can be enabled using +the \fIlog_input\fR and \fIlog_output\fR Defaults flags as well as the +\&\f(CW\*(C`LOG_INPUT\*(C'\fR and \f(CW\*(C`LOG_OUTPUT\*(C'\fR command tags. +.SS "Command Environment" +.IX Subsection "Command Environment" +Since environment variables can influence program behavior, \fIsudoers\fR +provides a means to restrict which variables from the user's +environment are inherited by the command to be run. There are two +distinct ways \fIsudoers\fR can deal with environment variables. +.PP +By default, the \fIenv_reset\fR option is enabled. This causes commands +to be executed with a minimal environment containing \f(CW\*(C`TERM\*(C'\fR, +\&\f(CW\*(C`PATH\*(C'\fR, \f(CW\*(C`HOME\*(C'\fR, \f(CW\*(C`MAIL\*(C'\fR, \f(CW\*(C`SHELL\*(C'\fR, \f(CW\*(C`LOGNAME\*(C'\fR, \f(CW\*(C`USER\*(C'\fR and \f(CW\*(C`USERNAME\*(C'\fR in +addition to variables from the invoking process permitted by the +\&\fIenv_check\fR and \fIenv_keep\fR options. This is effectively a whitelist +for environment variables. +.PP +If, however, the \fIenv_reset\fR option is disabled, any variables not +explicitly denied by the \fIenv_check\fR and \fIenv_delete\fR options are +inherited from the invoking process. In this case, \fIenv_check\fR +and \fIenv_delete\fR behave like a blacklist. Since it is not possible +to blacklist all potentially dangerous environment variables, use +of the default \fIenv_reset\fR behavior is encouraged. +.PP +In all cases, environment variables with a value beginning with +\&\f(CW\*(C`()\*(C'\fR are removed as they could be interpreted as \fBbash\fR functions. +The list of environment variables that \fBsudo\fR allows or denies is +contained in the output of \f(CW\*(C`sudo \-V\*(C'\fR when run as root. +.PP +Note that the dynamic linker on most operating systems will remove +variables that can control dynamic linking from the environment of +setuid executables, including \fBsudo\fR. Depending on the operating +system this may include \f(CW\*(C`_RLD*\*(C'\fR, \f(CW\*(C`DYLD_*\*(C'\fR, \f(CW\*(C`LD_*\*(C'\fR, \f(CW\*(C`LDR_*\*(C'\fR, +\&\f(CW\*(C`LIBPATH\*(C'\fR, \f(CW\*(C`SHLIB_PATH\*(C'\fR, and others. These type of variables are +removed from the environment before \fBsudo\fR even begins execution +and, as such, it is not possible for \fBsudo\fR to preserve them. +.PP +As a special case, If \fBsudo\fR's \fB\-i\fR option (initial login) is +specified, \fIsudoers\fR will initialize the environment regardless +of the value of \fIenv_reset\fR. The \fI\s-1DISPLAY\s0\fR, \fI\s-1PATH\s0\fR and \fI\s-1TERM\s0\fR +variables remain unchanged; \fI\s-1HOME\s0\fR, \fI\s-1MAIL\s0\fR, \fI\s-1SHELL\s0\fR, \fI\s-1USER\s0\fR, +and \fI\s-1LOGNAME\s0\fR are set based on the target user. On Linux and \s-1AIX\s0 +systems the contents of \fI/etc/environment\fR are also included. All +other environment variables are removed. +.SH "SUDOERS FILE FORMAT" +.IX Header "SUDOERS FILE FORMAT" The \fIsudoers\fR file is composed of two types of entries: aliases (basically variables) and user specifications (which specify who may run what). @@ -270,9 +366,10 @@ may be specified in escaped hex mode, e.g. \ex20 for space. When using double quotes, any prefix characters must be included inside the quotes. .PP -The \f(CW\*(C`nonunix_group\*(C'\fR and \f(CW\*(C`nonunix_gid\*(C'\fR syntax depends on the -underlying implementation. For instance, the \s-1QAS\s0 \s-1AD\s0 backend supports -the following formats: +The actual \f(CW\*(C`nonunix_group\*(C'\fR and \f(CW\*(C`nonunix_gid\*(C'\fR syntax depends on +the underlying group provider plugin (see the \fIgroup_plugin\fR +description below). For instance, the \s-1QAS\s0 \s-1AD\s0 plugin supports the +following formats: .IP "\(bu" 4 Group in the same domain: \*(L"Group Name\*(R" .IP "\(bu" 4 @@ -885,6 +982,8 @@ input is also captured and stored in a separate log file. Input is logged to the directory specified by the \fIiolog_dir\fR option (\fI@iolog_dir@\fR by default) using a unique session \s-1ID\s0 that is included in the normal \fBsudo\fR log line, prefixed with \fITSID=\fR. +The \fIiolog_file\fR option may be used to control the format of the +session \s-1ID\s0. .Sp Note that user input may contain sensitive information such as passwords (even if they are not echoed to the screen), which will @@ -902,6 +1001,8 @@ log files. Output is logged to the directory specified by the \fIiolog_dir\fR option (\fI@iolog_dir@\fR by default) using a unique session \s-1ID\s0 that is included in the normal \fBsudo\fR log line, prefixed with \fITSID=\fR. +The \fIiolog_file\fR option may be used to control the format of the +session \s-1ID\s0. .Sp Output logs may be viewed with the \fIsudoreplay\fR\|(@mansectsu@) utility, which can also be used to list or search the available logs. @@ -1024,14 +1125,22 @@ change this behavior. This can be done by negating the set_logname option. Note that if the \fIenv_reset\fR option has not been disabled, entries in the \fIenv_keep\fR list will override the value of \&\fIset_logname\fR. This flag is \fIon\fR by default. +.IP "set_utmp" 16 +.IX Item "set_utmp" +When enabled, \fBsudo\fR will create an entry in the utmp (or utmpx) +file when a pseudo-tty is allocated. A pseudo-tty is allocated by +\&\fBsudo\fR when the \fIlog_input\fR, \fIlog_output\fR or \fIuse_pty\fR flags +are enabled. By default, the new entry will be a copy of the user's +existing utmp entry (if any), with the tty, time, type and pid +fields updated. This flag is \fIon\fR by default. .IP "setenv" 16 .IX Item "setenv" Allow the user to disable the \fIenv_reset\fR option from the command -line. Additionally, environment variables set via the command line -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. This flag is \fIoff\fR -by default. +line via the \fB\-E\fR option. Additionally, environment variables set +via the command line 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. +This flag is \fIoff\fR by default. .IP "shell_noargs" 16 .IX Item "shell_noargs" If set and \fBsudo\fR is invoked with no arguments it acts as if the @@ -1085,7 +1194,12 @@ If set, \fBsudo\fR will run the command in a pseudo-pty even if no I/O logging is being gone. A malicious program run under \fBsudo\fR could conceivably fork a background process that retains to the user's terminal device after the main program has finished executing. Use -of this option will make that impossible. +of this option will make that impossible. This flag is \fIoff\fR by default. +.IP "utmp_runas" 16 +.IX Item "utmp_runas" +If set, \fBsudo\fR will store the name of the runas user when updating +the utmp (or utmpx) file. By default, \fBsudo\fR stores the name of +the invoking user. This flag is \fIoff\fR by default. .IP "visiblepw" 16 .IX Item "visiblepw" By default, \fBsudo\fR will refuse to run if the user must enter a @@ -1153,10 +1267,69 @@ A colon (':') separated list of editors allowed to be used with list that exists and is executable. The default is \f(CW"@editor@"\fR. .IP "iolog_dir" 16 .IX Item "iolog_dir" -The directory in which to store input/output logs when the \fIlog_input\fR -or \fIlog_output\fR options are enabled or when the \f(CW\*(C`LOG_INPUT\*(C'\fR or -\&\f(CW\*(C`LOG_OUTPUT\*(C'\fR tags are present for a command. +The top-level directory to use when constructing the path name for +the input/output log directory. Only used if the \fIlog_input\fR or +\&\fIlog_output\fR options are enabled or when the \f(CW\*(C`LOG_INPUT\*(C'\fR or +\&\f(CW\*(C`LOG_OUTPUT\*(C'\fR tags are present for a command. The session sequence +number, if any, is stored in the directory. The default is \f(CW"@iolog_dir@"\fR. +.Sp +The following percent (`\f(CW\*(C`%\*(C'\fR') escape sequences are supported: +.RS 16 +.ie n .IP "\*(C`%{seq}\*(C'" 4 +.el .IP "\f(CW\*(C`%{seq}\*(C'\fR" 4 +.IX Item "%{seq}" +expanded to a monotonically increasing base\-36 sequence number, such as 0100A5, +where every two digits are used to form a new directory, e.g. \fI01/00/A5\fR +.ie n .IP "\*(C`%{user}\*(C'" 4 +.el .IP "\f(CW\*(C`%{user}\*(C'\fR" 4 +.IX Item "%{user}" +expanded to the invoking user's login name +.ie n .IP "\*(C`%{group}\*(C'" 4 +.el .IP "\f(CW\*(C`%{group}\*(C'\fR" 4 +.IX Item "%{group}" +expanded to the name of the invoking user's real group \s-1ID\s0 +.ie n .IP "\*(C`%{runas_user}\*(C'" 4 +.el .IP "\f(CW\*(C`%{runas_user}\*(C'\fR" 4 +.IX Item "%{runas_user}" +expanded to the login name of the user the command will +be run as (e.g. root) +.ie n .IP "\*(C`%{runas_group}\*(C'" 4 +.el .IP "\f(CW\*(C`%{runas_group}\*(C'\fR" 4 +.IX Item "%{runas_group}" +expanded to the group name of the user the command will +be run as (e.g. wheel) +.ie n .IP "\*(C`%{hostname}\*(C'" 4 +.el .IP "\f(CW\*(C`%{hostname}\*(C'\fR" 4 +.IX Item "%{hostname}" +expanded to the local host name without the domain name +.ie n .IP "\*(C`%{command}\*(C'" 4 +.el .IP "\f(CW\*(C`%{command}\*(C'\fR" 4 +.IX Item "%{command}" +expanded to the base name of the command being run +.RE +.RS 16 +.Sp +In addition, any escape sequences supported by the system's \fIstrftime()\fR +function will be expanded. +.Sp +To include a literal `\f(CW\*(C`%\*(C'\fR' character, the string `\f(CW\*(C`%%\*(C'\fR' should +be used. +.Sp +Path names that end in six or more \f(CW\*(C`X\*(C'\fRs will have the \f(CW\*(C`X\*(C'\fRs replaced +with a unique combination of digits and letters, similar to the +\&\fImktemp()\fR function. +.RE +.IP "iolog_file" 16 +.IX Item "iolog_file" +The path name, relative to \fIiolog_dir\fR, in which to store input/output +logs when the \fIlog_input\fR or \fIlog_output\fR options are enabled or +when the \f(CW\*(C`LOG_INPUT\*(C'\fR or \f(CW\*(C`LOG_OUTPUT\*(C'\fR tags are present for a command. +Note that \fIiolog_file\fR may contain directory components. +The default is \f(CW"%{seq}"\fR. +.Sp +See the \fIiolog_dir\fR option above for a list of supported percent +(`\f(CW\*(C`%\*(C'\fR') escape sequences. .IP "mailsub" 16 .IX Item "mailsub" Subject of the mail sent to the \fImailto\fR user. The escape \f(CW%h\fR @@ -1164,15 +1337,14 @@ will expand to the host name of the machine. Default is \f(CW\*(C`@mailsub@\*(C'\fR. .IP "noexec_file" 16 .IX Item "noexec_file" -Path to a shared library containing dummy versions of the \fIexecv()\fR, -\&\fIexecve()\fR and \fIfexecve()\fR library functions that just return an error. -This is used to implement the \fInoexec\fR functionality on systems that -support \f(CW\*(C`LD_PRELOAD\*(C'\fR or its equivalent. Defaults to \fI@noexec_file@\fR. +This option is deprecated and will be removed in a future release +of \fBsudo\fR. The path to the noexec file should now be set in the +\&\fI@sysconfdir@/sudo.conf\fR file. .IP "passprompt" 16 .IX Item "passprompt" The default prompt to use when asking for a password; can be overridden via the \fB\-p\fR option or the \f(CW\*(C`SUDO_PROMPT\*(C'\fR environment variable. -The following percent (`\f(CW\*(C`%\*(C'\fR') escapes are supported: +The following percent (`\f(CW\*(C`%\*(C'\fR') escape sequences are supported: .RS 16 .ie n .IP "%H" 4 .el .IP "\f(CW%H\fR" 4 @@ -1219,16 +1391,19 @@ This option is only available whe \fBsudo\fR is built with SELinux support. .IX Item "runas_default" The default user to run commands as if the \fB\-u\fR option is not specified on the command line. This defaults to \f(CW\*(C`@runas_default@\*(C'\fR. -Note that if \fIrunas_default\fR is set it \fBmust\fR occur before -any \f(CW\*(C`Runas_Alias\*(C'\fR specifications. .IP "syslog_badpri" 16 .IX Item "syslog_badpri" Syslog priority to use when user authenticates unsuccessfully. Defaults to \f(CW\*(C`@badpri@\*(C'\fR. +.Sp +The following syslog priorities are supported: \fBalert\fR, \fBcrit\fR, +\&\fBdebug\fR, \fBemerg\fR, \fBerr\fR, \fBinfo\fR, \fBnotice\fR, and \fBwarning\fR. .IP "syslog_goodpri" 16 .IX Item "syslog_goodpri" Syslog priority to use when user authenticates successfully. Defaults to \f(CW\*(C`@goodpri@\*(C'\fR. +.Sp +See syslog_badpri for the list of supported syslog priorities. .IP "sudoers_locale" 16 .IX Item "sudoers_locale" Locale to use when parsing the sudoers file, logging commands, and @@ -1252,16 +1427,6 @@ This option is only available whe \fBsudo\fR is built with SELinux support. \} .PP \&\fBStrings that can be used in a boolean context\fR: -.IP "askpass" 12 -.IX Item "askpass" -The \fIaskpass\fR option specifies the fully qualified path to a helper -program used to read the user's password when no terminal is -available. This may be the case when \fBsudo\fR is executed from a -graphical (as opposed to text-based) application. The program -specified by \fIaskpass\fR should display the argument passed to it -as the prompt and write the user's password to the standard output. -The value of \fIaskpass\fR may be overridden by the \f(CW\*(C`SUDO_ASKPASS\*(C'\fR -environment variable. .IP "env_file" 12 .IX Item "env_file" The \fIenv_file\fR options specifies the fully qualified path to a @@ -1275,6 +1440,25 @@ as \fIenv_keep\fR and \fIenv_check\fR. .IX Item "exempt_group" Users in this group are exempt from password and \s-1PATH\s0 requirements. This is not set by default. +.IP "group_plugin" 12 +.IX Item "group_plugin" +A string containing a \fIsudoers\fR group plugin with optional arguments. +This can be used to implement support for the \f(CW\*(C`nonunix_group\*(C'\fR +syntax described earlier. The string should consist of the plugin +path, either fully-qualified or relative to the \fI@prefix@/libexec\fR +directory, followed by any configuration arguments the plugin +requires. These arguments (if any) will be passed to the plugin's +initialization function. If arguments are present, the string must +be enclosed in double quotes (\f(CW\*(C`"\*(C'\fR). +.Sp +For example, given \fI/etc/sudo\-group\fR, a group file in Unix group +format, the sample group plugin can be used: +.Sp +.Vb 1 +\& Defaults sudo_plugin="sample_group.so /etc/sudo\-group" +.Ve +.Sp +For more information see \fIsudo_plugin\fR\|(@mansectform@). .IP "lecture" 12 .IX Item "lecture" This option controls when a short lecture will be printed along with @@ -1362,6 +1546,10 @@ This option is @secure_path@ by default. .IX Item "syslog" Syslog facility if syslog is being used for logging (negate to disable syslog logging). Defaults to \f(CW\*(C`@logfac@\*(C'\fR. +.Sp +The following syslog facilities are supported: \fBauthpriv\fR (if your +\&\s-1OS\s0 supports it), \fBauth\fR, \fBdaemon\fR, \fBuser\fR, \fBlocal0\fR, \fBlocal1\fR, +\&\fBlocal2\fR, \fBlocal3\fR, \fBlocal4\fR, \fBlocal5\fR, \fBlocal6\fR, and \fBlocal7\fR. .IP "verifypw" 12 .IX Item "verifypw" This option controls when a password will be required when a user runs @@ -1426,14 +1614,6 @@ single value without double-quotes. The list can be replaced, added to, deleted from, or disabled by using the \f(CW\*(C`=\*(C'\fR, \f(CW\*(C`+=\*(C'\fR, \f(CW\*(C`\-=\*(C'\fR, and \&\f(CW\*(C`!\*(C'\fR operators respectively. The default list of variables to keep is displayed when \fBsudo\fR is run by root with the \fI\-V\fR option. -.PP -When logging via \fIsyslog\fR\|(3), \fBsudo\fR accepts the following values -for the syslog facility (the value of the \fBsyslog\fR Parameter): -\&\fBauthpriv\fR (if your \s-1OS\s0 supports it), \fBauth\fR, \fBdaemon\fR, \fBuser\fR, -\&\fBlocal0\fR, \fBlocal1\fR, \fBlocal2\fR, \fBlocal3\fR, \fBlocal4\fR, \fBlocal5\fR, -\&\fBlocal6\fR, and \fBlocal7\fR. The following syslog priorities are -supported: \fBalert\fR, \fBcrit\fR, \fBdebug\fR, \fBemerg\fR, \fBerr\fR, \fBinfo\fR, -\&\fBnotice\fR, and \fBwarning\fR. .SH "FILES" .IX Header "FILES" .ie n .IP "\fI@sysconfdir@/sudoers\fR" 24 @@ -1450,6 +1630,13 @@ List of network groups .el .IP "\fI@iolog_dir@\fR" 24 .IX Item "@iolog_dir@" I/O log files +.ie n .IP "\fI@timedir@\fR" 24 +.el .IP "\fI@timedir@\fR" 24 +.IX Item "@timedir@" +Directory containing time stamps for the \fIsudoers\fR security policy +.IP "\fI/etc/environment\fR" 24 +.IX Item "/etc/environment" +Initial environment for \fB\-i\fR mode on Linux and \s-1AIX\s0 .SH "EXAMPLES" .IX Header "EXAMPLES" Below are example \fIsudoers\fR entries. Admittedly, some of @@ -1738,30 +1925,16 @@ Note, however, that this applies only to native dynamically-linked executables. Statically-linked executables and foreign executables running under binary emulation are not affected. .Sp -To tell whether or not \fBsudo\fR supports \fInoexec\fR, you can run -the following as root: -.Sp -.Vb 1 -\& sudo \-V | grep "dummy exec" -.Ve -.Sp -If the resulting output contains a line that begins with: -.Sp -.Vb 1 -\& File containing dummy exec functions: -.Ve -.Sp -then \fBsudo\fR may be able to replace the exec family of functions -in the standard library with its own that simply return an error. -Unfortunately, there is no foolproof way to know whether or not -\&\fInoexec\fR will work at compile-time. \fInoexec\fR should work on -SunOS, Solaris, *BSD, Linux, \s-1IRIX\s0, Tru64 \s-1UNIX\s0, MacOS X, and HP-UX -11.x. It is known \fBnot\fR to work on \s-1AIX\s0 and UnixWare. \fInoexec\fR -is expected to work on most operating systems that support the +The \fInoexec\fR feature is known to work on SunOS, Solaris, *BSD, +Linux, \s-1IRIX\s0, Tru64 \s-1UNIX\s0, MacOS X, HP-UX 11.x and \s-1AIX\s0 5.3 and above. +It should be supported on most operating systems that support the \&\f(CW\*(C`LD_PRELOAD\*(C'\fR environment variable. Check your operating system's manual pages for the dynamic linker (usually ld.so, ld.so.1, dyld, dld.sl, rld, or loader) to see if \f(CW\*(C`LD_PRELOAD\*(C'\fR is supported. .Sp +On Solaris 10 and higher, \fInoexec\fR uses Solaris privileges instead +of the \f(CW\*(C`LD_PRELOAD\*(C'\fR environment variable. +.Sp To enable \fInoexec\fR for a command, use the \f(CW\*(C`NOEXEC\*(C'\fR tag as documented in the User Specification section above. Here is that example again: .Sp @@ -1773,7 +1946,8 @@ This allows user \fBaaron\fR to run \fI/usr/bin/more\fR and \fI/usr/bin/vi\fR with \fInoexec\fR enabled. This will prevent those two commands from executing other commands (such as a shell). If you are unsure whether or not your system is capable of supporting \fInoexec\fR you -can always just try it out and see if it works. +can always just try it out and check whether shell escapes work +when \fInoexec\fR is enabled. .PP Note that restricting shell escapes is not a panacea. Programs running as root are still capable of many potentially hazardous @@ -1781,9 +1955,55 @@ operations (such as changing or overwriting files) that could lead to unintended privilege escalation. In the specific case of an editor, a safer approach is to give the user permission to run \&\fBsudoedit\fR. +.SH "SECURITY NOTES" +.IX Header "SECURITY NOTES" +\&\fIsudoers\fR will check the ownership of its time stamp directory +(\fI@timedir@\fR by default) and ignore the directory's contents if +it is not owned by root or if it is writable by a user other than +root. On systems that allow non-root users to give away files via +\&\fIchown\fR\|(2), if the time stamp directory is located in a world-writable +directory (e.g., \fI/tmp\fR), it is possible for a user to create the +time stamp directory before \fBsudo\fR is run. However, because +\&\fIsudoers\fR checks the ownership and mode of the directory and its +contents, the only damage that can be done is to \*(L"hide\*(R" files by +putting them in the time stamp dir. This is unlikely to happen +since once the time stamp dir is owned by root and inaccessible by +any other user, the user placing files there would be unable to get +them back out. +.PP +\&\fIsudoers\fR will not honor time stamps set far in the future. Time +stamps with a date greater than current_time + 2 * \f(CW\*(C`TIMEOUT\*(C'\fR will +be ignored and sudo will log and complain. This is done to keep a +user from creating his/her own time stamp with a bogus date on +systems that allow users to give away files if the time stamp directory +is located in a world-writable directory. +.PP +On systems where the boot time is available, \fIsudoers\fR will ignore +time stamps that date from before the machine booted. +.PP +Since time stamp files live in the file system, they can outlive a +user's login session. As a result, a user may be able to login, +run a command with \fBsudo\fR after authenticating, logout, login +again, and run \fBsudo\fR without authenticating so long as the time +stamp file's modification time is within \f(CW\*(C`@timeout@\*(C'\fR minutes (or +whatever the timeout is set to in \fIsudoers\fR). When the \fItty_tickets\fR +option is enabled, the time stamp has per-tty granularity but still +may outlive the user's session. On Linux systems where the devpts +filesystem is used, Solaris systems with the devices filesystem, +as well as other systems that utilize a devfs filesystem that +monotonically increase the inode number of devices as they are +created (such as Mac \s-1OS\s0 X), \fIsudoers\fR is able to determine when a +tty-based time stamp file is stale and will ignore it. Administrators +should not rely on this feature as it is not universally available. +.PP +If users have sudo \f(CW\*(C`ALL\*(C'\fR there is nothing to prevent them from +creating their own program that gives them a root shell (or making +their own copy of a shell) regardless of any '!' elements in the +user specification. .SH "SEE ALSO" .IX Header "SEE ALSO" -\&\fIrsh\fR\|(1), \fIsu\fR\|(1), \fIfnmatch\fR\|(3), \fIglob\fR\|(3), \fIsudo\fR\|(@mansectsu@), \fIvisudo\fR\|(8) +\&\fIrsh\fR\|(1), \fIsu\fR\|(1), \fIfnmatch\fR\|(3), \fIglob\fR\|(3), \fImktemp\fR\|(3), \fIstrftime\fR\|(3), +\&\fIsudoers.ldap\fR\|(@mansectform@), \fIsudo_plugin\fR\|(@mansectsu@), \fIsudo\fR\|(@mansectsu@), \fIvisudo\fR\|(@mansectsu@) .SH "CAVEATS" .IX Header "CAVEATS" The \fIsudoers\fR file should \fBalways\fR be edited by the \fBvisudo\fR diff --git a/sudoers.man.pl b/doc/sudoers.man.pl similarity index 100% rename from sudoers.man.pl rename to doc/sudoers.man.pl diff --git a/sudoers.pod b/doc/sudoers.pod similarity index 82% rename from sudoers.pod rename to doc/sudoers.pod index ef250cd..12509ca 100644 --- a/sudoers.pod +++ b/doc/sudoers.pod @@ -22,10 +22,109 @@ Materiel Command, USAF, under agreement number F39502-99-1-0512. =head1 NAME -sudoers - list of which users may execute what +sudoers - default sudo security policy module =head1 DESCRIPTION +The I policy module determines a user's B privileges. +It is the default B policy plugin. The policy is driven by +the F<@sysconfdir@/sudoers> file or, optionally in LDAP. The policy +format is described in detail in the L<"SUDOERS FILE FORMAT"> +section. For information on storing I policy information +in LDAP, please see L. + +=head2 Authentication and Logging + +The I security policy requires that most users authenticate +themselves before they can use B. A password is not required +if the invoking user is root, if the target user is the same as the +invoking user, or if the policy has disabled authentication for the +user or command. Unlike L, when I requires +authentication, it validates the invoking user's credentials, not +the target user's (or root's) credentials. This can be changed via +the I, I and I flags, described later. + +If a user who is not listed in the policy tries to run a command +via B, mail is sent to the proper authorities. The address +used for such mail is configurable via the I Defaults entry +(described later) and defaults to C<@mailto@>. + +Note that mail will not be sent if an unauthorized user tries to +run B with the B<-l> or B<-v> option. This allows users to +determine for themselves whether or not they are allowed to use +B. + +If B is run by root and the C environment variable +is set, the I policy will use this value to determine who +the actual user is. This can be used by a user to log commands +through sudo even when a root shell has been invoked. It also +allows the B<-e> option to remain useful even when invoked via a +sudo-run script or program. Note, however, that the I +lookup is still done for root, not the user specified by C. + +I uses time stamp files for credential caching. Once a +user has been authenticated, a time stamp is updated and the user +may then use sudo without a password for a short period of time +(C<@timeout@> minutes unless overridden by the I option. +By default, I uses a tty-based time stamp which means that +there is a separate time stamp for each of a user's login sessions. +The I option can be disabled to force the use of a +single time stamp for all of a user's sessions. + +I can log both successful and unsuccessful attempts (as well +as errors) to syslog(3), a log file, or both. By default, I +will log via syslog(3) but this is changeable via the I +and I Defaults settings. + +I also supports logging a command's input and output +streams. I/O logging is not on by default but can be enabled using +the I and I Defaults flags as well as the +C and C command tags. + +=head2 Command Environment + +Since environment variables can influence program behavior, I +provides a means to restrict which variables from the user's +environment are inherited by the command to be run. There are two +distinct ways I can deal with environment variables. + +By default, the I option is enabled. This causes commands +to be executed with a minimal environment containing C, +C, C, C, C, C, C and C in +addition to variables from the invoking process permitted by the +I and I options. This is effectively a whitelist +for environment variables. + +If, however, the I option is disabled, any variables not +explicitly denied by the I and I options are +inherited from the invoking process. In this case, I +and I behave like a blacklist. Since it is not possible +to blacklist all potentially dangerous environment variables, use +of the default I behavior is encouraged. + +In all cases, environment variables with a value beginning with +C<()> are removed as they could be interpreted as B functions. +The list of environment variables that B allows or denies is +contained in the output of C when run as root. + +Note that the dynamic linker on most operating systems will remove +variables that can control dynamic linking from the environment of +setuid executables, including B. Depending on the operating +system this may include C<_RLD*>, C, C, C, +C, C, and others. These type of variables are +removed from the environment before B even begins execution +and, as such, it is not possible for B to preserve them. + +As a special case, If B's B<-i> option (initial login) is +specified, I will initialize the environment regardless +of the value of I. The I, I and I +variables remain unchanged; I, I, I, I, +and I are set based on the target user. On Linux and AIX +systems the contents of F are also included. All +other environment variables are removed. + +=head1 SUDOERS FILE FORMAT + The I file is composed of two types of entries: aliases (basically variables) and user specifications (which specify who may run what). @@ -135,9 +234,10 @@ may be specified in escaped hex mode, e.g. \x20 for space. When using double quotes, any prefix characters must be included inside the quotes. -The C and C syntax depends on the -underlying implementation. For instance, the QAS AD backend supports -the following formats: +The actual C and C syntax depends on +the underlying group provider plugin (see the I +description below). For instance, the QAS AD plugin supports the +following formats: =over 4 @@ -749,6 +849,8 @@ input is also captured and stored in a separate log file. Input is logged to the directory specified by the I option (F<@iolog_dir@> by default) using a unique session ID that is included in the normal B log line, prefixed with I. +The I option may be used to control the format of the +session ID. Note that user input may contain sensitive information such as passwords (even if they are not echoed to the screen), which will @@ -767,6 +869,8 @@ log files. Output is logged to the directory specified by the I option (F<@iolog_dir@> by default) using a unique session ID that is included in the normal B log line, prefixed with I. +The I option may be used to control the format of the +session ID. Output logs may be viewed with the L utility, which can also be used to list or search the available logs. @@ -908,14 +1012,23 @@ option. Note that if the I option has not been disabled, entries in the I list will override the value of I. This flag is I by default. +=item set_utmp + +When enabled, B will create an entry in the utmp (or utmpx) +file when a pseudo-tty is allocated. A pseudo-tty is allocated by +B when the I, I or I flags +are enabled. By default, the new entry will be a copy of the user's +existing utmp entry (if any), with the tty, time, type and pid +fields updated. This flag is I by default. + =item setenv Allow the user to disable the I option from the command -line. Additionally, environment variables set via the command line -are not subject to the restrictions imposed by I, -I, or I. As such, only trusted users should -be allowed to set variables in this manner. This flag is I -by default. +line via the B<-E> option. Additionally, environment variables set +via the command line are not subject to the restrictions imposed +by I, I, or I. As such, only +trusted users should be allowed to set variables in this manner. +This flag is I by default. =item shell_noargs @@ -974,7 +1087,13 @@ If set, B will run the command in a pseudo-pty even if no I/O logging is being gone. A malicious program run under B could conceivably fork a background process that retains to the user's terminal device after the main program has finished executing. Use -of this option will make that impossible. +of this option will make that impossible. This flag is I by default. + +=item utmp_runas + +If set, B will store the name of the runas user when updating +the utmp (or utmpx) file. By default, B stores the name of +the invoking user. This flag is I by default. =item visiblepw @@ -1064,11 +1183,71 @@ list that exists and is executable. The default is C<"@editor@">. =item iolog_dir -The directory in which to store input/output logs when the I -or I options are enabled or when the C or -C tags are present for a command. +The top-level directory to use when constructing the path name for +the input/output log directory. Only used if the I or +I options are enabled or when the C or +C tags are present for a command. The session sequence +number, if any, is stored in the directory. The default is C<"@iolog_dir@">. +The following percent (`C<%>') escape sequences are supported: + +=over 4 + +=item C<%{seq}> + +expanded to a monotonically increasing base-36 sequence number, such as 0100A5, +where every two digits are used to form a new directory, e.g. F<01/00/A5> + +=item C<%{user}> + +expanded to the invoking user's login name + +=item C<%{group}> + +expanded to the name of the invoking user's real group ID + +=item C<%{runas_user}> + +expanded to the login name of the user the command will +be run as (e.g. root) + +=item C<%{runas_group}> + +expanded to the group name of the user the command will +be run as (e.g. wheel) + +=item C<%{hostname}> + +expanded to the local host name without the domain name + +=item C<%{command}> + +expanded to the base name of the command being run + +=back + +In addition, any escape sequences supported by the system's strftime() +function will be expanded. + +To include a literal `C<%>' character, the string `C<%%>' should +be used. + +Path names that end in six or more Cs will have the Cs replaced +with a unique combination of digits and letters, similar to the +mktemp() function. + +=item iolog_file + +The path name, relative to I, in which to store input/output +logs when the I or I options are enabled or +when the C or C tags are present for a command. +Note that I may contain directory components. +The default is C<"%{seq}">. + +See the I option above for a list of supported percent +(`C<%>') escape sequences. + =item mailsub Subject of the mail sent to the I user. The escape C<%h> @@ -1077,16 +1256,15 @@ Default is C<@mailsub@>. =item noexec_file -Path to a shared library containing dummy versions of the execv(), -execve() and fexecve() library functions that just return an error. -This is used to implement the I functionality on systems that -support C or its equivalent. Defaults to F<@noexec_file@>. +This option is deprecated and will be removed in a future release +of B. The path to the noexec file should now be set in the +F<@sysconfdir@/sudo.conf> file. =item passprompt The default prompt to use when asking for a password; can be overridden via the B<-p> option or the C environment variable. -The following percent (`C<%>') escapes are supported: +The following percent (`C<%>') escape sequences are supported: =over 4 @@ -1133,19 +1311,22 @@ This option is only available whe B is built with SELinux support. The default user to run commands as if the B<-u> option is not specified on the command line. This defaults to C<@runas_default@>. -Note that if I is set it B occur before -any C specifications. =item syslog_badpri Syslog priority to use when user authenticates unsuccessfully. Defaults to C<@badpri@>. +The following syslog priorities are supported: B, B, +B, B, B, B, B, and B. + =item syslog_goodpri Syslog priority to use when user authenticates successfully. Defaults to C<@goodpri@>. +See L for the list of supported syslog priorities. + =item sudoers_locale Locale to use when parsing the sudoers file, logging commands, and @@ -1175,17 +1356,6 @@ B: =over 12 -=item askpass - -The I option specifies the fully qualified path to a helper -program used to read the user's password when no terminal is -available. This may be the case when B is executed from a -graphical (as opposed to text-based) application. The program -specified by I should display the argument passed to it -as the prompt and write the user's password to the standard output. -The value of I may be overridden by the C -environment variable. - =item env_file The I options specifies the fully qualified path to a @@ -1201,6 +1371,24 @@ as I and I. Users in this group are exempt from password and PATH requirements. This is not set by default. +=item group_plugin + +A string containing a I group plugin with optional arguments. +This can be used to implement support for the C +syntax described earlier. The string should consist of the plugin +path, either fully-qualified or relative to the F<@prefix@/libexec> +directory, followed by any configuration arguments the plugin +requires. These arguments (if any) will be passed to the plugin's +initialization function. If arguments are present, the string must +be enclosed in double quotes (C<">). + +For example, given F, a group file in Unix group +format, the sample group plugin can be used: + + Defaults sudo_plugin="sample_group.so /etc/sudo-group" + +For more information see L. + =item lecture This option controls when a short lecture will be printed along with @@ -1305,6 +1493,10 @@ This option is @secure_path@ by default. Syslog facility if syslog is being used for logging (negate to disable syslog logging). Defaults to C<@logfac@>. +The following syslog facilities are supported: B (if your +OS supports it), B, B, B, B, B, +B, B, B, B, B, and B. + =item verifypw This option controls when a password will be required when a user runs @@ -1383,14 +1575,6 @@ is displayed when B is run by root with the I<-V> option. =back -When logging via L, B accepts the following values -for the syslog facility (the value of the B Parameter): -B (if your OS supports it), B, B, B, -B, B, B, B, B, B, -B, and B. The following syslog priorities are -supported: B, B, B, B, B, B, -B, and B. - =head1 FILES =over 24 @@ -1411,6 +1595,14 @@ List of network groups I/O log files +=item F<@timedir@> + +Directory containing time stamps for the I security policy + +=item F + +Initial environment for B<-i> mode on Linux and AIX + =back =head1 EXAMPLES @@ -1661,26 +1853,16 @@ Note, however, that this applies only to native dynamically-linked executables. Statically-linked executables and foreign executables running under binary emulation are not affected. -To tell whether or not B supports I, you can run -the following as root: - - sudo -V | grep "dummy exec" - -If the resulting output contains a line that begins with: - - File containing dummy exec functions: - -then B may be able to replace the exec family of functions -in the standard library with its own that simply return an error. -Unfortunately, there is no foolproof way to know whether or not -I will work at compile-time. I should work on -SunOS, Solaris, *BSD, Linux, IRIX, Tru64 UNIX, MacOS X, and HP-UX -11.x. It is known B to work on AIX and UnixWare. I -is expected to work on most operating systems that support the +The I feature is known to work on SunOS, Solaris, *BSD, +Linux, IRIX, Tru64 UNIX, MacOS X, HP-UX 11.x and AIX 5.3 and above. +It should be supported on most operating systems that support the C environment variable. Check your operating system's manual pages for the dynamic linker (usually ld.so, ld.so.1, dyld, dld.sl, rld, or loader) to see if C is supported. +On Solaris 10 and higher, I uses Solaris privileges instead +of the C environment variable. + To enable I for a command, use the C tag as documented in the User Specification section above. Here is that example again: @@ -1690,7 +1872,8 @@ This allows user B to run F and F with I enabled. This will prevent those two commands from executing other commands (such as a shell). If you are unsure whether or not your system is capable of supporting I you -can always just try it out and see if it works. +can always just try it out and check whether shell escapes work +when I is enabled. =back @@ -1701,9 +1884,56 @@ to unintended privilege escalation. In the specific case of an editor, a safer approach is to give the user permission to run B. +=head1 SECURITY NOTES + +I will check the ownership of its time stamp directory +(F<@timedir@> by default) and ignore the directory's contents if +it is not owned by root or if it is writable by a user other than +root. On systems that allow non-root users to give away files via +L, if the time stamp directory is located in a world-writable +directory (e.g., F), it is possible for a user to create the +time stamp directory before B is run. However, because +I checks the ownership and mode of the directory and its +contents, the only damage that can be done is to "hide" files by +putting them in the time stamp dir. This is unlikely to happen +since once the time stamp dir is owned by root and inaccessible by +any other user, the user placing files there would be unable to get +them back out. + +I will not honor time stamps set far in the future. Time +stamps with a date greater than current_time + 2 * C will +be ignored and sudo will log and complain. This is done to keep a +user from creating his/her own time stamp with a bogus date on +systems that allow users to give away files if the time stamp directory +is located in a world-writable directory. + +On systems where the boot time is available, I will ignore +time stamps that date from before the machine booted. + +Since time stamp files live in the file system, they can outlive a +user's login session. As a result, a user may be able to login, +run a command with B after authenticating, logout, login +again, and run B without authenticating so long as the time +stamp file's modification time is within C<@timeout@> minutes (or +whatever the timeout is set to in I). When the I +option is enabled, the time stamp has per-tty granularity but still +may outlive the user's session. On Linux systems where the devpts +filesystem is used, Solaris systems with the devices filesystem, +as well as other systems that utilize a devfs filesystem that +monotonically increase the inode number of devices as they are +created (such as Mac OS X), I is able to determine when a +tty-based time stamp file is stale and will ignore it. Administrators +should not rely on this feature as it is not universally available. + +If users have sudo C there is nothing to prevent them from +creating their own program that gives them a root shell (or making +their own copy of a shell) regardless of any '!' elements in the +user specification. + =head1 SEE ALSO -L, L, L, L, L, L +L, L, L, L, L, L, +L, L, L, L =head1 CAVEATS diff --git a/sudoreplay.cat b/doc/sudoreplay.cat similarity index 91% rename from sudoreplay.cat rename to doc/sudoreplay.cat index aee5497..254544c 100644 --- a/sudoreplay.cat +++ b/doc/sudoreplay.cat @@ -1,9 +1,7 @@ +SUDOREPLAY(1m) MAINTENANCE COMMANDS SUDOREPLAY(1m) -SUDOREPLAY(1m) MAINTENANCE COMMANDS SUDOREPLAY(1m) - - NNAAMMEE sudoreplay - replay sudo session logs @@ -14,12 +12,17 @@ SSYYNNOOPPSSIISS ssuuddoorreeppllaayy [--hh] [--dd _d_i_r_e_c_t_o_r_y] -l [search expression] DDEESSCCRRIIPPTTIIOONN - ssuuddoorreeppllaayy plays back or lists the session logs created by ssuuddoo. When + ssuuddoorreeppllaayy plays back or lists the output logs created by ssuuddoo. When replaying, ssuuddoorreeppllaayy can play the session back in real-time, or the playback speed may be adjusted (faster or slower) based on the command - line options. The _I_D should be a six character sequence of digits and - upper case letters, e.g. 0100A5, which is logged by ssuuddoo when a - command is run with session logging enabled. + line options. + + The _I_D should either be a six character sequence of digits and upper + case letters, e.g. 0100A5, or a pattern matching the _i_o_l_o_g___f_i_l_e option + in the _s_u_d_o_e_r_s file. When a command is run via ssuuddoo with _l_o_g___o_u_t_p_u_t + enabled in the _s_u_d_o_e_r_s file, a TSID=ID string is logged via syslog or + to the ssuuddoo log file. The _I_D may also be determined using ssuuddoorreeppllaayy's + list mode. In list mode, ssuuddoorreeppllaayy can be used to find the ID of a session based on a number of criteria such as the user, tty or command run. @@ -57,19 +60,6 @@ OOPPTTIIOONNSS displayed. An expression is composed of the following predicates: - - - - -1.7.6 April 9, 2011 1 - - - - - -SUDOREPLAY(1m) MAINTENANCE COMMANDS SUDOREPLAY(1m) - - command _c_o_m_m_a_n_d _p_a_t_t_e_r_n Evaluates to true if the command run matches _c_o_m_m_a_n_d _p_a_t_t_e_r_n. On systems with POSIX regular @@ -124,18 +114,6 @@ SUDOREPLAY(1m) MAINTENANCE COMMANDS SUDOREPLAY(1m) -m _m_a_x___w_a_i_t Specify an upper bound on how long to wait between key presses or output data. By default, ssuuddoo__rreeppllaayy will - - - -1.7.6 April 9, 2011 2 - - - - - -SUDOREPLAY(1m) MAINTENANCE COMMANDS SUDOREPLAY(1m) - - accurately reproduce the delays between key presses or program output. However, this can be tedious when the session includes long pauses. When the _-_m option is @@ -191,17 +169,6 @@ SUDOREPLAY(1m) MAINTENANCE COMMANDS SUDOREPLAY(1m) 2 hours ago 2 hours ago. - - -1.7.6 April 9, 2011 3 - - - - - -SUDOREPLAY(1m) MAINTENANCE COMMANDS SUDOREPLAY(1m) - - next Friday The first second of the next Friday. @@ -257,17 +224,6 @@ EEXXAAMMPPLLEESS sudoreplay -l user millert - - -1.7.6 April 9, 2011 4 - - - - - -SUDOREPLAY(1m) MAINTENANCE COMMANDS SUDOREPLAY(1m) - - List sessions run by user _b_o_b with a command containing the string vi: sudoreplay -l user bob command vi @@ -304,27 +260,4 @@ DDIISSCCLLAAIIMMEERR - - - - - - - - - - - - - - - - - - - - - -1.7.6 April 9, 2011 5 - - +1.8.1p2 May 16, 2011 SUDOREPLAY(1m) diff --git a/sudoreplay.man.in b/doc/sudoreplay.man.in similarity index 94% rename from sudoreplay.man.in rename to doc/sudoreplay.man.in index 89418d8..1c7557a 100644 --- a/sudoreplay.man.in +++ b/doc/sudoreplay.man.in @@ -1,4 +1,4 @@ -.\" Copyright (c) 2009-2010 Todd C. Miller +.\" Copyright (c) 2009-2011 Todd C. Miller .\" .\" Permission to use, copy, modify, and distribute this software for any .\" purpose with or without fee is hereby granted, provided that the above @@ -139,7 +139,7 @@ .\" ======================================================================== .\" .IX Title "SUDOREPLAY @mansectsu@" -.TH SUDOREPLAY @mansectsu@ "April 9, 2011" "1.7.6" "MAINTENANCE COMMANDS" +.TH SUDOREPLAY @mansectsu@ "May 16, 2011" "1.8.1p2" "MAINTENANCE COMMANDS" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -153,13 +153,17 @@ sudoreplay \- replay sudo session logs \&\fBsudoreplay\fR [\fB\-h\fR] [\fB\-d\fR \fIdirectory\fR] \-l [search expression] .SH "DESCRIPTION" .IX Header "DESCRIPTION" -\&\fBsudoreplay\fR plays back or lists the session logs created by -\&\fBsudo\fR. When replaying, \fBsudoreplay\fR can play the session back -in real-time, or the playback speed may be adjusted (faster or -slower) based on the command line options. The \fI\s-1ID\s0\fR should be -a six character sequence of digits and upper case letters, e.g. -0100A5, which is logged by \fBsudo\fR when a command is run with -session logging enabled. +\&\fBsudoreplay\fR plays back or lists the output logs created by \fBsudo\fR. +When replaying, \fBsudoreplay\fR can play the session back in real-time, +or the playback speed may be adjusted (faster or slower) based on +the command line options. +.PP +The \fI\s-1ID\s0\fR should either be a six character sequence of digits and +upper case letters, e.g. \f(CW\*(C`0100A5\*(C'\fR, or a pattern matching the +\&\fIiolog_file\fR option in the \fIsudoers\fR file. When a command is run +via \fBsudo\fR with \fIlog_output\fR enabled in the \fIsudoers\fR file, a +\&\f(CW\*(C`TSID=ID\*(C'\fR string is logged via syslog or to the \fBsudo\fR log file. +The \fI\s-1ID\s0\fR may also be determined using \fBsudoreplay\fR's list mode. .PP In list mode, \fBsudoreplay\fR can be used to find the \s-1ID\s0 of a session based on a number of criteria such as the user, tty or command run. diff --git a/sudoreplay.pod b/doc/sudoreplay.pod similarity index 92% rename from sudoreplay.pod rename to doc/sudoreplay.pod index 5eb6e1e..d01e498 100644 --- a/sudoreplay.pod +++ b/doc/sudoreplay.pod @@ -1,4 +1,4 @@ -Copyright (c) 2009-2010 Todd C. Miller +Copyright (c) 2009-2011 Todd C. Miller Permission to use, copy, modify, and distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -27,13 +27,17 @@ B [B<-h>] [B<-d> I] -l [search expression] =head1 DESCRIPTION -B plays back or lists the session logs created by -B. When replaying, B can play the session back -in real-time, or the playback speed may be adjusted (faster or -slower) based on the command line options. The I should be -a six character sequence of digits and upper case letters, e.g. -0100A5, which is logged by B when a command is run with -session logging enabled. +B plays back or lists the output logs created by B. +When replaying, B can play the session back in real-time, +or the playback speed may be adjusted (faster or slower) based on +the command line options. + +The I should either be a six character sequence of digits and +upper case letters, e.g. C<0100A5>, or a pattern matching the +I option in the I file. When a command is run +via B with I enabled in the I file, a +C string is logged via syslog or to the B log file. +The I may also be determined using B's list mode. In list mode, B can be used to find the ID of a session based on a number of criteria such as the user, tty or command run. diff --git a/visudo.cat b/doc/visudo.cat similarity index 94% rename from visudo.cat rename to doc/visudo.cat index ce7c1a3..5aa5f0f 100644 --- a/visudo.cat +++ b/doc/visudo.cat @@ -1,9 +1,7 @@ +VISUDO(1m) MAINTENANCE COMMANDS VISUDO(1m) -VISUDO(1m) MAINTENANCE COMMANDS VISUDO(1m) - - NNAAMMEE visudo - edit the sudoers file @@ -58,18 +56,6 @@ OOPPTTIIOONNSS --ff may be "-", indicating that _s_u_d_o_e_r_s will be read from the standard input. - - - -1.7.6 April 9, 2011 1 - - - - - -VISUDO(1m) MAINTENANCE COMMANDS VISUDO(1m) - - -h The --hh (_h_e_l_p) option causes vviissuuddoo to print a short help message to the standard output and exit. @@ -123,21 +109,8 @@ DDIIAAGGNNOOSSTTIICCSS used. You may wish to comment out or remove the unused alias. In --ss (strict) mode this is an error, not a warning. - - - - -1.7.6 April 9, 2011 2 - - - - - -VISUDO(1m) MAINTENANCE COMMANDS VISUDO(1m) - - SSEEEE AALLSSOO - _v_i(1), _s_u_d_o_e_r_s(4), _s_u_d_o(1m), _v_i_p_w(8) + _v_i(1), _s_u_d_o_e_r_s(4), _s_u_d_o(1m), _v_i_p_w(1m) AAUUTTHHOORR Many people have worked on _s_u_d_o over the years; this version of vviissuuddoo @@ -170,29 +143,4 @@ DDIISSCCLLAAIIMMEERR - - - - - - - - - - - - - - - - - - - - - - - -1.7.6 April 9, 2011 3 - - +1.8.1p2 May 16, 2011 VISUDO(1m) diff --git a/visudo.man.in b/doc/visudo.man.in similarity index 98% rename from visudo.man.in rename to doc/visudo.man.in index c8ee72e..9003ea8 100644 --- a/visudo.man.in +++ b/doc/visudo.man.in @@ -1,4 +1,4 @@ -.\" Copyright (c) 1996,1998-2005, 2007-2010 +.\" Copyright (c) 1996,1998-2005, 2007-2011 .\" Todd C. Miller .\" .\" Permission to use, copy, modify, and distribute this software for any @@ -144,7 +144,7 @@ .\" ======================================================================== .\" .IX Title "VISUDO @mansectsu@" -.TH VISUDO @mansectsu@ "April 9, 2011" "1.7.6" "MAINTENANCE COMMANDS" +.TH VISUDO @mansectsu@ "May 16, 2011" "1.8.1p2" "MAINTENANCE COMMANDS" .\" For nroff, turn off justification. Always turn off hyphenation; it makes .\" way too many mistakes in technical documents. .if n .ad l @@ -273,7 +273,7 @@ used. You may wish to comment out or remove the unused alias. In \&\fB\-s\fR (strict) mode this is an error, not a warning. .SH "SEE ALSO" .IX Header "SEE ALSO" -\&\fIvi\fR\|(1), \fIsudoers\fR\|(@mansectform@), \fIsudo\fR\|(@mansectsu@), \fIvipw\fR\|(8) +\&\fIvi\fR\|(1), \fIsudoers\fR\|(@mansectform@), \fIsudo\fR\|(@mansectsu@), \fIvipw\fR\|(@mansectsu@) .SH "AUTHOR" .IX Header "AUTHOR" Many people have worked on \fIsudo\fR over the years; this version of diff --git a/visudo.pod b/doc/visudo.pod similarity index 99% rename from visudo.pod rename to doc/visudo.pod index 708d954..cffb321 100644 --- a/visudo.pod +++ b/doc/visudo.pod @@ -1,4 +1,4 @@ -Copyright (c) 1996,1998-2005, 2007-2010 +Copyright (c) 1996,1998-2005, 2007-2011 Todd C. Miller Permission to use, copy, modify, and distribute this software for any diff --git a/getprogname.c b/getprogname.c deleted file mode 100644 index 0790222..0000000 --- a/getprogname.c +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2003-2005 Todd C. Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Sponsored in part by the Defense Advanced Research Projects - * Agency (DARPA) and Air Force Research Laboratory, Air Force - * Materiel Command, USAF, under agreement number F39502-99-1-0512. - */ - -#include - -#include - -#include -#include - -#include "missing.h" - -const char * -getprogname() -{ - static const char *progname; - extern int Argc; - extern char **Argv; - - if (progname == NULL) { - if (Argc < 0) - progname = "sudo"; - else if ((progname = strrchr(Argv[0], '/')) != NULL) - progname++; - else - progname = Argv[0]; - } - return progname; -} diff --git a/gettime.c b/gettime.c deleted file mode 100644 index 6cb15d7..0000000 --- a/gettime.c +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2004-2005, 2008, 2010 - * Todd C. Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include - -#include -#include -#include -#if TIME_WITH_SYS_TIME -# include -#endif - -#include "missing.h" - -/* - * Get the current time via gettimeofday() for systems with - * timespecs in struct stat or, otherwise, using time(). - */ -int -gettime(tv) - struct timeval *tv; -{ - int rval; -#if defined(HAVE_GETTIMEOFDAY) && (defined(HAVE_ST_MTIM) || defined(HAVE_ST_MTIMESPEC)) - rval = gettimeofday(tv, NULL); -#else - rval = (int)time(&tv->tv_sec); - tv->tv_usec = 0; -#endif - return rval; -} diff --git a/include/Makefile.in b/include/Makefile.in new file mode 100644 index 0000000..150ca62 --- /dev/null +++ b/include/Makefile.in @@ -0,0 +1,82 @@ +# +# Copyright (c) 2011 Todd C. Miller +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# @configure_input@ +# + +#### Start of system configuration section. #### + +srcdir = @srcdir@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +includedir = @includedir@ + +# Our install program supports extra flags... +INSTALL = $(SHELL) $(top_srcdir)/install-sh -c + +# Where to install things... +prefix = @prefix@ +datarootdir = @datarootdir@ +localstatedir = @localstatedir@ + +# User and group ids the installed files should be "owned" by +install_uid = 0 +install_gid = 0 + +#### End of system configuration section. #### + +SHELL = @SHELL@ + +all: + +Makefile: $(srcdir)/Makefile.in + (cd $(top_builddir) && ./config.status --file include/Makefile) + +.SUFFIXES: .h + +pre-install: + +install: install-dirs install-includes + +install-dirs: + $(SHELL) $(top_srcdir)/mkinstalldirs $(DESTDIR)$(includedir) + +install-binaries: + +install-doc: + +install-includes: install-dirs + $(INSTALL) -O $(install_uid) -G $(install_gid) -M 0444 $(srcdir)/sudo_plugin.h $(DESTDIR)$(includedir) + +install-plugin: + +uninstall: + -rm -f $(DESTDIR)$(includedir)/sudo_plugin.h + +check: + +clean: + +mostlyclean: clean + +distclean: clean + -rm -rf Makefile + +clobber: distclean + +realclean: distclean + +cleandir: distclean diff --git a/alloc.h b/include/alloc.h similarity index 83% rename from alloc.h rename to include/alloc.h index d3e1b07..912654e 100644 --- a/alloc.h +++ b/include/alloc.h @@ -17,8 +17,8 @@ #ifndef _SUDO_ALLOC_H #define _SUDO_ALLOC_H -#ifdef __STDC__ -# include +#include + int easprintf(char **, const char *, ...) __printflike(2, 3); int evasprintf(char **, const char *, va_list) __printflike(2, 0); void efree(void *); @@ -27,16 +27,6 @@ void *emalloc2(size_t, size_t); void *erealloc(void *, size_t); void *erealloc3(void *, size_t, size_t); char *estrdup(const char *); -#else -# include -int easprintf(); -int evasprintf(); -void efree(); -void *emalloc(); -void *emalloc2(); -void *erealloc(); -void *erealloc3(); -char *estrdup(); -#endif /* __STDC__ */ +char *estrndup(const char *, size_t); #endif /* _SUDO_ALLOC_H */ diff --git a/error.h b/include/error.h similarity index 78% rename from error.h rename to include/error.h index 5ac3076..190bd26 100644 --- a/error.h +++ b/include/error.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004 Todd C. Miller + * Copyright (c) 2004, 2010 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -17,18 +17,11 @@ #ifndef _SUDO_ERROR_H_ #define _SUDO_ERROR_H_ -#ifdef __STDC__ -# include +#include + void error(int, const char *, ...) __attribute__((__noreturn__)); void errorx(int, const char *, ...) __attribute__((__noreturn__)); void warning(const char *, ...); void warningx(const char *, ...); -#else -# include -void error() __attribute__((__noreturn__)); -void errorx() __attribute__((__noreturn__)); -void warning(); -void warningx(); -#endif /* __STDC__ */ #endif /* _SUDO_ERROR_H_ */ diff --git a/include/fileops.h b/include/fileops.h new file mode 100644 index 0000000..e1c93a6 --- /dev/null +++ b/include/fileops.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2010 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SUDO_FILEOPS_H +#define _SUDO_FILEOPS_H + +/* + * Flags for lock_file() + */ +#define SUDO_LOCK 1 /* lock a file */ +#define SUDO_TLOCK 2 /* test & lock a file (non-blocking) */ +#define SUDO_UNLOCK 4 /* unlock a file */ + +struct timeval; + +int lock_file(int, int); +int touch(int, char *, struct timeval *); +char *sudo_parseln(FILE *); + +#endif /* _SUDO_FILEOPS_H */ diff --git a/lbuf.h b/include/lbuf.h similarity index 77% rename from lbuf.h rename to include/lbuf.h index db6f964..501eeaf 100644 --- a/lbuf.h +++ b/include/lbuf.h @@ -23,7 +23,7 @@ * Line buffer struct. */ struct lbuf { - int (*output)__P((const char *)); + int (*output)(const char *); char *buf; const char *continuation; int indent; @@ -32,11 +32,10 @@ struct lbuf { int cols; }; -int get_ttycols __P((void)); -void lbuf_append __P((struct lbuf *, ...)); -void lbuf_append_quoted __P((struct lbuf *, const char *, ...)); -void lbuf_destroy __P((struct lbuf *)); -void lbuf_init __P((struct lbuf *, int (*)(const char *), int, const char *)); -void lbuf_print __P((struct lbuf *)); +void lbuf_init(struct lbuf *, int (*)(const char *), int, const char *, int); +void lbuf_destroy(struct lbuf *); +void lbuf_append(struct lbuf *, ...); +void lbuf_append_quoted(struct lbuf *, const char *, ...); +void lbuf_print(struct lbuf *); #endif /* _SUDO_LBUF_H */ diff --git a/list.h b/include/list.h similarity index 81% rename from list.h rename to include/list.h index 719afa2..1055e22 100644 --- a/list.h +++ b/include/list.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007 Todd C. Miller + * Copyright (c) 2007, 2010 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -20,19 +20,11 @@ /* * Convenience macro for declaring a list head. */ -#ifdef __STDC__ #define TQ_DECLARE(n) \ struct n##_list { \ struct n *first; \ struct n *last; \ }; -#else -#define TQ_DECLARE(n) \ -struct n/**/_list { \ - struct n *first; \ - struct n *last; \ -}; -#endif /* * Foreach loops: forward and reverse @@ -75,10 +67,10 @@ struct n/**/_list { \ /* * Prototypes for list.c */ -void *tq_pop __P((void *)); -void tq_append __P((void *, void *)); -void tq_remove __P((void *, void *)); -void list_append __P((void *, void *)); -void list2tq __P((void *, void *)); +void *tq_pop(void *); +void tq_append(void *, void *); +void tq_remove(void *, void *); +void list_append(void *, void *); +void list2tq(void *, void *); #endif /* _SUDO_LIST_H */ diff --git a/missing.h b/include/missing.h similarity index 67% rename from missing.h rename to include/missing.h index 7b2d29d..68d5879 100644 --- a/missing.h +++ b/include/missing.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 1998-2005, 2008-2010 + * Copyright (c) 1996, 1998-2005, 2008, 2009-2010 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -23,25 +23,12 @@ #define _SUDO_MISSING_H #include -#ifdef __STDC__ -# include -#else -# include -#endif +#include /* - * Macros that may be missing on some Operating Systems + * Macros and functions that may be missing on some operating systems. */ -/* Deal with ANSI stuff reasonably. */ -#ifndef __P -# if defined (__cplusplus) || defined (__STDC__) -# define __P(args) args -# else -# define __P(args) () -# endif -#endif /* __P */ - /* Define away __attribute__ for non-gcc or old gcc */ #if !defined(__GNUC__) || __GNUC__ < 2 || __GNUC__ == 2 && __GNUC_MINOR__ < 5 # define __attribute__(x) @@ -134,19 +121,6 @@ # define STDERR_FILENO 2 #endif -/* - * These should be defined in but not everyone has them. - */ -#ifndef SEEK_SET -# define SEEK_SET 0 -#endif -#ifndef SEEK_CUR -# define SEEK_CUR 1 -#endif -#ifndef SEEK_END -# define SEEK_END 2 -#endif - /* * BSD defines these in but others may not. */ @@ -161,26 +135,10 @@ * Simple isblank() macro and function for systems without it. */ #ifndef HAVE_ISBLANK -int isblank __P((int)); +int isblank(int); # define isblank(_x) ((_x) == ' ' || (_x) == '\t') #endif -/* - * Old BSD systems lack strchr(), strrchr(), memset() and memcpy() - */ -#if !defined(HAVE_STRCHR) && !defined(strchr) -# define strchr(_s, _c) index(_s, _c) -#endif -#if !defined(HAVE_STRRCHR) && !defined(strrchr) -# define strrchr(_s, _c) rindex(_s, _c) -#endif -#if !defined(HAVE_MEMCPY) && !defined(memcpy) -# define memcpy(_d, _s, _n) (bcopy(_s, _d, _n)) -#endif -#if !defined(HAVE_MEMSET) && !defined(memset) -# define memset(_s, _x, _n) (bzero(_s, _n)) -#endif - /* * NCR's SVr4 has _innetgr(3) instead of innetgr(3) for some reason. */ @@ -197,40 +155,17 @@ int isblank __P((int)); #endif /* O_NOCTTY */ /* - * Emulate POSIX signals via sigvec(2) - */ -#ifndef HAVE_SIGACTION -# define SA_ONSTACK SV_ONSTACK -# define SA_RESTART SV_INTERRUPT /* opposite effect */ -# define SA_RESETHAND SV_RESETHAND -# define sa_handler sv_handler -# define sa_mask sv_mask -# define sa_flags sv_flags -typedef struct sigvec sigaction_t; -typedef int sigset_t; -int sigaction __P((int sig, const sigaction_t *act, sigaction_t *oact)); -int sigemptyset __P((sigset_t *)); -int sigfillset __P((sigset_t *)); -int sigaddset __P((sigset_t *, int)); -int sigdelset __P((sigset_t *, int)); -int sigismember __P((sigset_t *, int)); -int sigprocmask __P((int, const sigset_t *, sigset_t *)); -#endif - -/* - * Extra sugar for POSIX signals to deal with the above emulation - * as well as the fact that SunOS has a SA_INTERRUPT flag. + * Add IRIX-like sigaction_t for those without it. + * SA_RESTART is not required by POSIX; SunOS has SA_INTERRUPT instead. */ -#ifdef HAVE_SIGACTION -# ifndef HAVE_SIGACTION_T +#ifndef HAVE_SIGACTION_T typedef struct sigaction sigaction_t; -# endif -# ifndef SA_INTERRUPT -# define SA_INTERRUPT 0 -# endif -# ifndef SA_RESTART -# define SA_RESTART 0 -# endif +#endif +#ifndef SA_INTERRUPT +# define SA_INTERRUPT 0 +#endif +#ifndef SA_RESTART +# define SA_RESTART 0 #endif /* @@ -262,7 +197,8 @@ typedef struct sigaction sigaction_t; extern const char *__progname; # define getprogname() (__progname) # else -const char *getprogname __P((void)); +const char *getprogname(void); +void setprogname(const char *); #endif /* HAVE___PROGNAME */ #endif /* !HAVE_GETPROGNAME */ @@ -316,15 +252,27 @@ const char *getprogname __P((void)); # define WCOREDUMP(x) ((x) & 0x80) #endif +#ifndef HAVE_SETEUID +# if defined(HAVE_SETRESUID) +# define seteuid(u) setresuid(-1, (u), -1) +# define setegid(g) setresgid(-1, (g), -1) +# define HAVE_SETEUID 1 +# elif defined(HAVE_SETREUID) +# define seteuid(u) setreuid(-1, (u)) +# define setegid(g) setregid(-1, (g)) +# define HAVE_SETEUID 1 +# endif +#endif /* HAVE_SETEUID */ + /* * HP-UX does not declare innetgr() or getdomainname(). * Solaris does not declare getdomainname(). */ #if defined(__hpux) -int innetgr __P((const char *, const char *, const char *, const char *)); +int innetgr(const char *, const char *, const char *, const char *); #endif #if defined(__hpux) || defined(__sun) -int getdomainname __P((char *, size_t)); +int getdomainname(char *, size_t); #endif /* Functions "missing" from libc. */ @@ -333,65 +281,58 @@ struct timeval; struct timespec; #ifndef HAVE_CLOSEFROM -void closefrom __P((int)); +void closefrom(int); #endif #ifndef HAVE_GETCWD -char *getcwd __P((char *, size_t size)); +char *getcwd(char *, size_t size); #endif #ifndef HAVE_GETLINE -ssize_t getline __P((char **, size_t *, FILE *)); +ssize_t getline(char **, size_t *, FILE *); #endif #ifndef HAVE_UTIMES -int utimes __P((const char *, const struct timeval *)); +int utimes(const char *, const struct timeval *); #endif #ifdef HAVE_FUTIME -int futimes __P((int, const struct timeval *)); +int futimes(int, const struct timeval *); #endif #ifndef HAVE_SNPRINTF -int snprintf __P((char *, size_t, const char *, ...)) - __printflike(3, 4); +int snprintf(char *, size_t, const char *, ...) __printflike(3, 4); #endif #ifndef HAVE_VSNPRINTF -int vsnprintf __P((char *, size_t, const char *, va_list)) - __printflike(3, 0); +int vsnprintf(char *, size_t, const char *, va_list) __printflike(3, 0); #endif #ifndef HAVE_ASPRINTF -int asprintf __P((char **, const char *, ...)) - __printflike(2, 3); +int asprintf(char **, const char *, ...) __printflike(2, 3); #endif #ifndef HAVE_VASPRINTF -int vasprintf __P((char **, const char *, va_list)) - __printflike(2, 0); -#endif -#ifndef HAVE_STRCASECMP -int strcasecmp __P((const char *, const char *)); +int vasprintf(char **, const char *, va_list) __printflike(2, 0); #endif #ifndef HAVE_STRLCAT -size_t strlcat __P((char *, const char *, size_t)); +size_t strlcat(char *, const char *, size_t); #endif #ifndef HAVE_STRLCPY -size_t strlcpy __P((char *, const char *, size_t)); +size_t strlcpy(char *, const char *, size_t); #endif #ifndef HAVE_MEMRCHR -void *memrchr __P((const void *, int, size_t)); +void *memrchr(const void *, int, size_t); +#endif +#ifndef HAVE_MKDTEMP +char *mkdtemp(char *); #endif #ifndef HAVE_MKSTEMPS -int mkstemps __P((char *, int)); +int mkstemps(char *, int); #endif #ifndef HAVE_NANOSLEEP -int nanosleep __P((const struct timespec *, struct timespec *)); +int nanosleep(const struct timespec *, struct timespec *); #endif #ifndef HAVE_SETENV -int setenv __P((const char *, const char *, int)); +int setenv(const char *, const char *, int); #endif #ifndef HAVE_UNSETENV -int unsetenv __P((const char *)); +int unsetenv(const char *); #endif #ifndef HAVE_STRSIGNAL -char *strsignal __P((int)); -#endif -#ifndef HAVE_SETSID -pid_t setsid __P((void)); +char *strsignal(int); #endif #endif /* _SUDO_MISSING_H */ diff --git a/include/sudo_plugin.h b/include/sudo_plugin.h new file mode 100644 index 0000000..2306503 --- /dev/null +++ b/include/sudo_plugin.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2009-2011 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SUDO_PLUGIN_H +#define _SUDO_PLUGIN_H + +/* API version major/minor */ +#define SUDO_API_VERSION_MAJOR 1 +#define SUDO_API_VERSION_MINOR 1 +#define SUDO_API_MKVERSION(x, y) ((x << 16) | y) +#define SUDO_API_VERSION SUDO_API_MKVERSION(SUDO_API_VERSION_MAJOR, SUDO_API_VERSION_MINOR) + +/* Getters and setters for API version */ +#define SUDO_API_VERSION_GET_MAJOR(v) ((v) >> 16) +#define SUDO_API_VERSION_GET_MINOR(v) ((v) & 0xffff) +#define SUDO_API_VERSION_SET_MAJOR(vp, n) do { \ + *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \ +} while(0) +#define SUDO_VERSION_SET_MINOR(vp, n) do { \ + *(vp) = (*(vp) & 0xffff0000) | (n); \ +} while(0) + +/* Conversation function types and defines */ +struct sudo_conv_message { +#define SUDO_CONV_PROMPT_ECHO_OFF 0x0001 /* do not echo user input */ +#define SUDO_CONV_PROMPT_ECHO_ON 0x0002 /* echo user input */ +#define SUDO_CONV_ERROR_MSG 0x0003 /* error message */ +#define SUDO_CONV_INFO_MSG 0x0004 /* informational message */ +#define SUDO_CONV_PROMPT_MASK 0x0005 /* mask user input */ +#define SUDO_CONV_PROMPT_ECHO_OK 0x1000 /* flag: allow echo if no tty */ + int msg_type; + int timeout; + const char *msg; +}; + +struct sudo_conv_reply { + char *reply; +}; + +typedef int (*sudo_conv_t)(int num_msgs, const struct sudo_conv_message msgs[], + struct sudo_conv_reply replies[]); +typedef int (*sudo_printf_t)(int msg_type, const char *fmt, ...); + +/* Policy plugin type and defines */ +struct passwd; +struct policy_plugin { +#define SUDO_POLICY_PLUGIN 1 + unsigned int type; /* always SUDO_POLICY_PLUGIN */ + unsigned int version; /* always SUDO_API_VERSION */ + int (*open)(unsigned int version, sudo_conv_t conversation, + sudo_printf_t sudo_printf, char * const settings[], + char * const user_info[], char * const user_env[]); + void (*close)(int exit_status, int error); /* wait status or error */ + int (*show_version)(int verbose); + int (*check_policy)(int argc, char * const argv[], + char *env_add[], char **command_info[], + char **argv_out[], char **user_env_out[]); + int (*list)(int argc, char * const argv[], int verbose, + const char *list_user); + int (*validate)(void); + void (*invalidate)(int remove); + int (*init_session)(struct passwd *pwd); +}; + +/* I/O plugin type and defines */ +struct io_plugin { +#define SUDO_IO_PLUGIN 2 + unsigned int type; /* always SUDO_IO_PLUGIN */ + unsigned int version; /* always SUDO_API_VERSION */ + int (*open)(unsigned int version, sudo_conv_t conversation, + sudo_printf_t sudo_printf, char * const settings[], + char * const user_info[], char * const command_info[], + int argc, char * const argv[], char * const user_env[]); + void (*close)(int exit_status, int error); /* wait status or error */ + int (*show_version)(int verbose); + int (*log_ttyin)(const char *buf, unsigned int len); + int (*log_ttyout)(const char *buf, unsigned int len); + int (*log_stdin)(const char *buf, unsigned int len); + int (*log_stdout)(const char *buf, unsigned int len); + int (*log_stderr)(const char *buf, unsigned int len); +}; + +/* Sudoers group plugin version major/minor */ +#define GROUP_API_VERSION_MAJOR 1 +#define GROUP_API_VERSION_MINOR 0 +#define GROUP_API_VERSION ((GROUP_API_VERSION_MAJOR << 16) | GROUP_API_VERSION_MINOR) + +/* Getters and setters for group version */ +#define GROUP_API_VERSION_GET_MAJOR(v) ((v) >> 16) +#define GROUP_API_VERSION_GET_MINOR(v) ((v) & 0xffff) +#define GROUP_API_VERSION_SET_MAJOR(vp, n) do { \ + *(vp) = (*(vp) & 0x0000ffff) | ((n) << 16); \ +} while(0) +#define GROUP_API_VERSION_SET_MINOR(vp, n) do { \ + *(vp) = (*(vp) & 0xffff0000) | (n); \ +} while(0) + +/* + * version: for compatibility checking + * group_init: return 1 on success, 0 if unconfigured, -1 on error. + * group_cleanup: called to clean up resources used by provider + * user_in_group: returns 1 if user is in group, 0 if not. + * note that pwd may be NULL if the user is not in passwd. + */ +struct sudoers_group_plugin { + unsigned int version; + int (*init)(int version, sudo_printf_t sudo_printf, char *const argv[]); + void (*cleanup)(void); + int (*query)(const char *user, const char *group, const struct passwd *pwd); +}; + +#endif /* _SUDO_PLUGIN_H */ diff --git a/iolog.c b/iolog.c deleted file mode 100644 index 131770e..0000000 --- a/iolog.c +++ /dev/null @@ -1,404 +0,0 @@ -/* - * Copyright (c) 2009-2010 Todd C. Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include - -#include -#include -#include -#include -#include -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif /* STDC_HEADERS */ -#ifdef HAVE_STRING_H -# include -#endif /* HAVE_STRING_H */ -#ifdef HAVE_STRINGS_H -# include -#endif /* HAVE_STRINGS_H */ -#ifdef HAVE_UNISTD_H -# include -#endif /* HAVE_UNISTD_H */ -#if TIME_WITH_SYS_TIME -# include -#endif -#include -#include -#include -#include -#include -#ifdef HAVE_ZLIB_H -# include -#endif - -#include "sudo.h" - -union io_fd { - FILE *f; -#ifdef HAVE_ZLIB_H - gzFile g; -#endif - void *v; -}; - -struct script_buf { - int len; /* buffer length (how much read in) */ - int off; /* write position (how much already consumed) */ - char buf[16 * 1024]; -}; - -#define IOFD_STDIN 0 -#define IOFD_STDOUT 1 -#define IOFD_STDERR 2 -#define IOFD_TTYIN 3 -#define IOFD_TTYOUT 4 -#define IOFD_TIMING 5 -#define IOFD_MAX 6 - -#ifdef __STDC__ -# define SESSID_MAX 2176782336U -#else -# define SESSID_MAX (unsigned long)2176782336 -#endif - -static sigset_t ttyblock; -static struct timeval last_time; -static union io_fd io_fds[IOFD_MAX]; - -void -io_nextid() -{ - struct stat sb; - char buf[32], *ep; - int fd, i; - unsigned long id = 0; - int len; - ssize_t nread; - char pathbuf[PATH_MAX]; - static const char b36char[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; - - /* - * Create I/O log directory if it doesn't already exist. - */ - if (stat(def_iolog_dir, &sb) != 0) { - if (mkdir(def_iolog_dir, S_IRWXU) != 0) - log_error(USE_ERRNO, "Can't mkdir %s", def_iolog_dir); - } else if (!S_ISDIR(sb.st_mode)) { - log_error(0, "%s exists but is not a directory (0%o)", - def_iolog_dir, (unsigned int) sb.st_mode); - } - - /* - * Open sequence file - */ - len = snprintf(pathbuf, sizeof(pathbuf), "%s/seq", def_iolog_dir); - if (len <= 0 || len >= sizeof(pathbuf)) { - errno = ENAMETOOLONG; - log_error(USE_ERRNO, "%s/seq", pathbuf); - } - fd = open(pathbuf, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR); - if (fd == -1) - log_error(USE_ERRNO, "cannot open %s", pathbuf); - lock_file(fd, SUDO_LOCK); - - /* Read seq number (base 36). */ - nread = read(fd, buf, sizeof(buf)); - if (nread != 0) { - if (nread == -1) - log_error(USE_ERRNO, "cannot read %s", pathbuf); - id = strtoul(buf, &ep, 36); - if (buf == ep || id >= SESSID_MAX) - log_error(0, "invalid sequence number %s", pathbuf); - } - id++; - - /* - * Convert id to a string and stash in sudo_user.sessid. - * Note that that least significant digits go at the end of the string. - */ - for (i = 5; i >= 0; i--) { - buf[i] = b36char[id % 36]; - id /= 36; - } - buf[6] = '\n'; - - /* Stash id logging purposes */ - memcpy(sudo_user.sessid, buf, 6); - sudo_user.sessid[6] = '\0'; - - /* Rewind and overwrite old seq file. */ - if (lseek(fd, 0, SEEK_SET) == (off_t)-1 || write(fd, buf, 7) != 7) - log_error(USE_ERRNO, "Can't write to %s", pathbuf); - close(fd); -} - -static int -build_idpath(pathbuf, pathsize) - char *pathbuf; - size_t pathsize; -{ - struct stat sb; - int i, len; - - if (sudo_user.sessid[0] == '\0') - log_error(0, "tried to build a session id path without a session id"); - - /* - * Path is of the form /var/log/sudo-io/00/00/01. - */ - len = snprintf(pathbuf, pathsize, "%s/%c%c/%c%c/%c%c", def_iolog_dir, - sudo_user.sessid[0], sudo_user.sessid[1], sudo_user.sessid[2], - sudo_user.sessid[3], sudo_user.sessid[4], sudo_user.sessid[5]); - if (len <= 0 && len >= pathsize) { - errno = ENAMETOOLONG; - log_error(USE_ERRNO, "%s/%s", def_iolog_dir, sudo_user.sessid); - } - - /* - * Create the intermediate subdirs as needed. - */ - for (i = 6; i > 0; i -= 3) { - pathbuf[len - i] = '\0'; - if (stat(pathbuf, &sb) != 0) { - if (mkdir(pathbuf, S_IRWXU) != 0) - log_error(USE_ERRNO, "Can't mkdir %s", pathbuf); - } else if (!S_ISDIR(sb.st_mode)) { - log_error(0, "%s: %s", pathbuf, strerror(ENOTDIR)); - } - pathbuf[len - i] = '/'; - } - - return len; -} - -static void * -open_io_fd(pathbuf, len, suffix, docompress) - char *pathbuf; - int len; - const char *suffix; - int docompress; -{ - void *vfd = NULL; - int fd; - - pathbuf[len] = '\0'; - strlcat(pathbuf, suffix, PATH_MAX); - fd = open(pathbuf, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR); - if (fd != -1) { - fcntl(fd, F_SETFD, FD_CLOEXEC); -#ifdef HAVE_ZLIB_H - if (docompress) - vfd = gzdopen(fd, "w"); - else -#endif - vfd = fdopen(fd, "w"); - } - return vfd; -} - -int -io_log_open() -{ - char pathbuf[PATH_MAX]; - FILE *io_logfile; - int len; - - if (!def_log_input && !def_log_output) - return FALSE; - - /* - * Build a path containing the session id split into two-digit subdirs, - * so ID 000001 becomes /var/log/sudo-io/00/00/01. - */ - len = build_idpath(pathbuf, sizeof(pathbuf)); - if (len == -1) - return -1; - - if (mkdir(pathbuf, S_IRUSR|S_IWUSR|S_IXUSR) != 0) - log_error(USE_ERRNO, "Can't mkdir %s", pathbuf); - - /* - * We create 7 files: a log file, a timing file and 5 for input/output. - */ - io_logfile = open_io_fd(pathbuf, len, "/log", FALSE); - if (io_logfile == NULL) - log_error(USE_ERRNO, "Can't create %s", pathbuf); - - io_fds[IOFD_TIMING].v = open_io_fd(pathbuf, len, "/timing", def_compress_io); - if (io_fds[IOFD_TIMING].v == NULL) - log_error(USE_ERRNO, "Can't create %s", pathbuf); - - if (def_log_input) { - io_fds[IOFD_TTYIN].v = open_io_fd(pathbuf, len, "/ttyin", def_compress_io); - if (io_fds[IOFD_TTYIN].v == NULL) - log_error(USE_ERRNO, "Can't create %s", pathbuf); - } - - if (def_log_output) { - io_fds[IOFD_TTYOUT].v = open_io_fd(pathbuf, len, "/ttyout", def_compress_io); - if (io_fds[IOFD_TTYOUT].v == NULL) - log_error(USE_ERRNO, "Can't create %s", pathbuf); - } - - if (def_log_input) { - io_fds[IOFD_STDIN].v = open_io_fd(pathbuf, len, "/stdin", def_compress_io); - if (io_fds[IOFD_STDIN].v == NULL) - log_error(USE_ERRNO, "Can't create %s", pathbuf); - } - - if (def_log_output) { - io_fds[IOFD_STDOUT].v = open_io_fd(pathbuf, len, "/stdout", def_compress_io); - if (io_fds[IOFD_STDOUT].v == NULL) - log_error(USE_ERRNO, "Can't create %s", pathbuf); - } - - if (def_log_output) { - io_fds[IOFD_STDERR].v = open_io_fd(pathbuf, len, "/stderr", def_compress_io); - if (io_fds[IOFD_STDERR].v == NULL) - log_error(USE_ERRNO, "Can't create %s", pathbuf); - } - - /* So we can block tty-generated signals */ - sigemptyset(&ttyblock); - sigaddset(&ttyblock, SIGINT); - sigaddset(&ttyblock, SIGQUIT); - sigaddset(&ttyblock, SIGTSTP); - sigaddset(&ttyblock, SIGTTIN); - sigaddset(&ttyblock, SIGTTOU); - - gettimeofday(&last_time, NULL); - - /* XXX - log more stuff? window size? environment? */ - fprintf(io_logfile, "%ld:%s:%s:%s:%s\n", (long)last_time.tv_sec, user_name, - runas_pw->pw_name, runas_gr ? runas_gr->gr_name : "", user_tty); - fprintf(io_logfile, "%s\n", user_cwd); - fprintf(io_logfile, "%s%s%s\n", user_cmnd, user_args ? " " : "", - user_args ? user_args : ""); - fclose(io_logfile); - - return TRUE; -} - -void -io_log_close() -{ - int i; - - for (i = 0; i < IOFD_MAX; i++) { - if (io_fds[i].v == NULL) - continue; -#ifdef HAVE_ZLIB_H - if (def_compress_io) - gzclose(io_fds[i].g); - else -#endif - fclose(io_fds[i].f); - } -} - -static int -log_io(buf, len, idx) - const char *buf; - unsigned int len; - int idx; -{ - struct timeval now, delay; - sigset_t omask; - - gettimeofday(&now, NULL); - - sigprocmask(SIG_BLOCK, &ttyblock, &omask); - -#ifdef HAVE_ZLIB_H - if (def_compress_io) - gzwrite(io_fds[idx].g, buf, len); - else -#endif - fwrite(buf, 1, len, io_fds[idx].f); - delay.tv_sec = now.tv_sec; - delay.tv_usec = now.tv_usec; - timevalsub(&delay, &last_time); -#ifdef HAVE_ZLIB_H - if (def_compress_io) - gzprintf(io_fds[IOFD_TIMING].g, "%d %f %d\n", idx, - delay.tv_sec + ((double)delay.tv_usec / 1000000), len); - else -#endif - fprintf(io_fds[IOFD_TIMING].f, "%d %f %d\n", idx, - delay.tv_sec + ((double)delay.tv_usec / 1000000), len); - last_time.tv_sec = now.tv_sec; - last_time.tv_usec = now.tv_usec; - - sigprocmask(SIG_SETMASK, &omask, NULL); - - return TRUE; -} - -int -log_ttyin(buf, len) - const char *buf; - unsigned int len; -{ - if (!io_fds[IOFD_TTYIN].v) - return TRUE; - return log_io(buf, len, IOFD_TTYIN); -} - -int -log_ttyout(buf, len) - const char *buf; - unsigned int len; -{ - if (!io_fds[IOFD_TTYOUT].v) - return TRUE; - return log_io(buf, len, IOFD_TTYOUT); -} - -int -log_stdin(buf, len) - const char *buf; - unsigned int len; -{ - if (!io_fds[IOFD_STDIN].v) - return TRUE; - return log_io(buf, len, IOFD_STDIN); -} - -int -log_stdout(buf, len) - const char *buf; - unsigned int len; -{ - if (!io_fds[IOFD_STDOUT].v) - return TRUE; - return log_io(buf, len, IOFD_STDOUT); -} - -int -log_stderr(buf, len) - const char *buf; - unsigned int len; -{ - if (!io_fds[IOFD_STDOUT].v) - return TRUE; - return log_io(buf, len, IOFD_STDERR); -} diff --git a/ltmain.sh b/ltmain.sh old mode 100644 new mode 100755 index a72f2fd..04eaea4 --- a/ltmain.sh +++ b/ltmain.sh @@ -1,9 +1,10 @@ # Generated from ltmain.m4sh. -# ltmain.sh (GNU libtool) 2.2.6b +# libtool (GNU libtool) 2.2.10 # Written by Gordon Matzigkeit , 1996 -# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, 2007 2008 Free Software Foundation, Inc. +# Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, 2006, +# 2007, 2008, 2009, 2010 Free Software Foundation, Inc. # This is free software; see the source for copying conditions. There is NO # warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. @@ -32,50 +33,54 @@ # # Provide generalized library-building support services. # -# --config show all configuration variables -# --debug enable verbose shell tracing -# -n, --dry-run display commands without modifying any files -# --features display basic configuration information and exit -# --mode=MODE use operation mode MODE -# --preserve-dup-deps don't remove duplicate dependency libraries -# --quiet, --silent don't print informational messages -# --tag=TAG use configuration variables from tag TAG -# -v, --verbose print informational messages (default) -# --version print version information -# -h, --help print short or long help message +# --config show all configuration variables +# --debug enable verbose shell tracing +# -n, --dry-run display commands without modifying any files +# --features display basic configuration information and exit +# --mode=MODE use operation mode MODE +# --preserve-dup-deps don't remove duplicate dependency libraries +# --quiet, --silent don't print informational messages +# --no-quiet, --no-silent +# print informational messages (default) +# --tag=TAG use configuration variables from tag TAG +# -v, --verbose print more informational messages than default +# --no-verbose don't print the extra informational messages +# --version print version information +# -h, --help, --help-all print short, long, or detailed help message # # MODE must be one of the following: # -# clean remove files from the build directory -# compile compile a source file into a libtool object -# execute automatically set library path, then run a program -# finish complete the installation of libtool libraries -# install install libraries or executables -# link create a library or an executable -# uninstall remove libraries from an installed directory +# clean remove files from the build directory +# compile compile a source file into a libtool object +# execute automatically set library path, then run a program +# finish complete the installation of libtool libraries +# install install libraries or executables +# link create a library or an executable +# uninstall remove libraries from an installed directory # -# MODE-ARGS vary depending on the MODE. +# MODE-ARGS vary depending on the MODE. When passed as first option, +# `--mode=MODE' may be abbreviated as `MODE' or a unique abbreviation of that. # Try `$progname --help --mode=MODE' for a more detailed description of MODE. # # When reporting a bug, please describe a test case to reproduce it and # include the following information: # -# host-triplet: $host -# shell: $SHELL -# compiler: $LTCC -# compiler flags: $LTCFLAGS -# linker: $LD (gnu? $with_gnu_ld) -# $progname: (GNU libtool) 2.2.6b -# automake: $automake_version -# autoconf: $autoconf_version +# host-triplet: $host +# shell: $SHELL +# compiler: $LTCC +# compiler flags: $LTCFLAGS +# linker: $LD (gnu? $with_gnu_ld) +# $progname: (GNU libtool) 2.2.10 +# automake: $automake_version +# autoconf: $autoconf_version # # Report bugs to . -PROGRAM=ltmain.sh +PROGRAM=libtool PACKAGE=libtool -VERSION=2.2.6b +VERSION=2.2.10 TIMESTAMP="" -package_revision=1.3017 +package_revision=1.3175 # Be Bourne compatible if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then @@ -91,10 +96,15 @@ fi BIN_SH=xpg4; export BIN_SH # for Tru64 DUALCASE=1; export DUALCASE # for MKS sh +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +$1 +_LTECHO_EOF' +} + # NLS nuisances: We save the old values to restore during execute mode. -# Only set LANG and LC_ALL to C if already set. -# These must not be set unconditionally because not all systems understand -# e.g. LANG=C (notably SCO). lt_user_locale= lt_safe_locale= for lt_var in LANG LANGUAGE LC_ALL LC_CTYPE LC_COLLATE LC_MESSAGES @@ -107,24 +117,33 @@ do lt_safe_locale=\"$lt_var=C; \$lt_safe_locale\" fi" done +LC_ALL=C +LANGUAGE=C +export LANGUAGE LC_ALL $lt_unset CDPATH +# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh +# is ksh but when the shell is invoked as "sh" and the current value of +# the _XPG environment variable is not equal to 1 (one), the special +# positional parameter $0, within a function call, is the name of the +# function. +progpath="$0" : ${CP="cp -f"} -: ${ECHO="echo"} -: ${EGREP="/bin/grep -E"} -: ${FGREP="/bin/grep -F"} -: ${GREP="/bin/grep"} +test "${ECHO+set}" = set || ECHO=${as_echo-'printf %s\n'} +: ${EGREP="grep -E"} +: ${FGREP="grep -F"} +: ${GREP="grep"} : ${LN_S="ln -s"} : ${MAKE="make"} : ${MKDIR="mkdir"} : ${MV="mv -f"} : ${RM="rm -f"} -: ${SED="/bin/sed"} +: ${SED="sed"} : ${SHELL="${CONFIG_SHELL-/bin/sh}"} : ${Xsed="$SED -e 1s/^X//"} @@ -159,32 +178,168 @@ basename="s,^.*/,," func_dirname_and_basename () { # Extract subdirectory from the argument. - func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` + func_dirname_result=`$ECHO "${1}" | $SED -e "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else func_dirname_result="$func_dirname_result${2}" fi - func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` + func_basename_result=`$ECHO "${1}" | $SED -e "$basename"` } # Generated shell functions inserted here. -# Work around backward compatibility issue on IRIX 6.5. On IRIX 6.4+, sh -# is ksh but when the shell is invoked as "sh" and the current value of -# the _XPG environment variable is not equal to 1 (one), the special -# positional parameter $0, within a function call, is the name of the -# function. -progpath="$0" +# These SED scripts presuppose an absolute path with a trailing slash. +pathcar='s,^/\([^/]*\).*$,\1,' +pathcdr='s,^/[^/]*,,' +removedotparts=':dotsl + s@/\./@/@g + t dotsl + s,/\.$,/,' +collapseslashes='s@/\{1,\}@/@g' +finalslash='s,/*$,/,' + +# func_normal_abspath PATH +# Remove doubled-up and trailing slashes, "." path components, +# and cancel out any ".." path components in PATH after making +# it an absolute path. +# value returned in "$func_normal_abspath_result" +func_normal_abspath () +{ + # Start from root dir and reassemble the path. + func_normal_abspath_result= + func_normal_abspath_tpath=$1 + func_normal_abspath_altnamespace= + case $func_normal_abspath_tpath in + "") + # Empty path, that just means $cwd. + func_stripname '' '/' "`pwd`" + func_normal_abspath_result=$func_stripname_result + return + ;; + # The next three entries are used to spot a run of precisely + # two leading slashes without using negated character classes; + # we take advantage of case's first-match behaviour. + ///*) + # Unusual form of absolute path, do nothing. + ;; + //*) + # Not necessarily an ordinary path; POSIX reserves leading '//' + # and for example Cygwin uses it to access remote file shares + # over CIFS/SMB, so we conserve a leading double slash if found. + func_normal_abspath_altnamespace=/ + ;; + /*) + # Absolute path, do nothing. + ;; + *) + # Relative path, prepend $cwd. + func_normal_abspath_tpath=`pwd`/$func_normal_abspath_tpath + ;; + esac + # Cancel out all the simple stuff to save iterations. We also want + # the path to end with a slash for ease of parsing, so make sure + # there is one (and only one) here. + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$removedotparts" -e "$collapseslashes" -e "$finalslash"` + while :; do + # Processed it all yet? + if test "$func_normal_abspath_tpath" = / ; then + # If we ascended to the root using ".." the result may be empty now. + if test -z "$func_normal_abspath_result" ; then + func_normal_abspath_result=/ + fi + break + fi + func_normal_abspath_tcomponent=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$pathcar"` + func_normal_abspath_tpath=`$ECHO "$func_normal_abspath_tpath" | $SED \ + -e "$pathcdr"` + # Figure out what to do with it + case $func_normal_abspath_tcomponent in + "") + # Trailing empty path component, ignore it. + ;; + ..) + # Parent dir; strip last assembled component from result. + func_dirname "$func_normal_abspath_result" + func_normal_abspath_result=$func_dirname_result + ;; + *) + # Actual path component, append it. + func_normal_abspath_result=$func_normal_abspath_result/$func_normal_abspath_tcomponent + ;; + esac + done + # Restore leading double-slash if one was found on entry. + func_normal_abspath_result=$func_normal_abspath_altnamespace$func_normal_abspath_result +} + +# func_relative_path SRCDIR DSTDIR +# generates a relative path from SRCDIR to DSTDIR, with a trailing +# slash if non-empty, suitable for immediately appending a filename +# without needing to append a separator. +# value returned in "$func_relative_path_result" +func_relative_path () +{ + func_relative_path_result= + func_normal_abspath "$1" + func_relative_path_tlibdir=$func_normal_abspath_result + func_normal_abspath "$2" + func_relative_path_tbindir=$func_normal_abspath_result + + # Ascend the tree starting from libdir + while :; do + # check if we have found a prefix of bindir + case $func_relative_path_tbindir in + $func_relative_path_tlibdir) + # found an exact match + func_relative_path_tcancelled= + break + ;; + $func_relative_path_tlibdir*) + # found a matching prefix + func_stripname "$func_relative_path_tlibdir" '' "$func_relative_path_tbindir" + func_relative_path_tcancelled=$func_stripname_result + if test -z "$func_relative_path_result"; then + func_relative_path_result=. + fi + break + ;; + *) + func_dirname $func_relative_path_tlibdir + func_relative_path_tlibdir=${func_dirname_result} + if test "x$func_relative_path_tlibdir" = x ; then + # Have to descend all the way to the root! + func_relative_path_result=../$func_relative_path_result + func_relative_path_tcancelled=$func_relative_path_tbindir + break + fi + func_relative_path_result=../$func_relative_path_result + ;; + esac + done + + # Now calculate path; take care to avoid doubling-up slashes. + func_stripname '' '/' "$func_relative_path_result" + func_relative_path_result=$func_stripname_result + func_stripname '/' '/' "$func_relative_path_tcancelled" + if test "x$func_stripname_result" != x ; then + func_relative_path_result=${func_relative_path_result}/${func_stripname_result} + fi + + # Normalisation. If bindir is libdir, return empty string, + # else relative path ending with a slash; either way, target + # file name can be directly appended. + if test ! -z "$func_relative_path_result"; then + func_stripname './' '' "$func_relative_path_result/" + func_relative_path_result=$func_stripname_result + fi +} # The name of this program: -# In the unlikely event $progname began with a '-', it would play havoc with -# func_echo (imagine progname=-n), so we prepend ./ in that case: func_dirname_and_basename "$progpath" progname=$func_basename_result -case $progname in - -*) progname=./$progname ;; -esac # Make sure we have an absolute path for reexecution: case $progpath in @@ -258,6 +413,13 @@ func_verbose () : } +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} + # func_error arg... # Echo program name prefixed message to standard error. func_error () @@ -326,9 +488,9 @@ func_mkdir_p () case $my_directory_path in */*) ;; *) break ;; esac # ...otherwise throw away the child directory and loop - my_directory_path=`$ECHO "X$my_directory_path" | $Xsed -e "$dirname"` + my_directory_path=`$ECHO "$my_directory_path" | $SED -e "$dirname"` done - my_dir_list=`$ECHO "X$my_dir_list" | $Xsed -e 's,:*$,,'` + my_dir_list=`$ECHO "$my_dir_list" | $SED 's,:*$,,'` save_mkdir_p_IFS="$IFS"; IFS=':' for my_dir in $my_dir_list; do @@ -378,7 +540,7 @@ func_mktempdir () func_fatal_error "cannot create temporary directory \`$my_tmpdir'" fi - $ECHO "X$my_tmpdir" | $Xsed + $ECHO "$my_tmpdir" } @@ -392,7 +554,7 @@ func_quote_for_eval () { case $1 in *[\\\`\"\$]*) - func_quote_for_eval_unquoted_result=`$ECHO "X$1" | $Xsed -e "$sed_quote_subst"` ;; + func_quote_for_eval_unquoted_result=`$ECHO "$1" | $SED "$sed_quote_subst"` ;; *) func_quote_for_eval_unquoted_result="$1" ;; esac @@ -419,7 +581,7 @@ func_quote_for_expand () { case $1 in *[\\\`\"]*) - my_arg=`$ECHO "X$1" | $Xsed \ + my_arg=`$ECHO "$1" | $SED \ -e "$double_quote_subst" -e "$sed_double_backslash"` ;; *) my_arg="$1" ;; @@ -489,14 +651,19 @@ func_show_eval_locale () } - - - # func_version # Echo version message to standard output and exit. func_version () { - $SED -n '/^# '$PROGRAM' (GNU /,/# warranty; / { + $SED -n '/(C)/!b go + :more + /\./!{ + N + s/\n# / / + b more + } + :go + /^# '$PROGRAM' (GNU /,/# warranty; / { s/^# // s/^# *$// s/\((C)\)[ 0-9,-]*\( [1-9][0-9]*\)/\1\2/ @@ -509,19 +676,20 @@ func_version () # Echo short help message to standard output and exit. func_usage () { - $SED -n '/^# Usage:/,/# -h/ { + $SED -n '/^# Usage:/,/^# *.*--help/ { s/^# // s/^# *$// s/\$progname/'$progname'/ p }' < "$progpath" - $ECHO + echo $ECHO "run \`$progname --help | more' for full usage" exit $? } -# func_help -# Echo long help message to standard output and exit. +# func_help [NOEXIT] +# Echo long help message to standard output and exit, +# unless 'noexit' is passed as argument. func_help () { $SED -n '/^# Usage:/,/# Report bugs to/ { @@ -538,7 +706,10 @@ func_help () s/\$autoconf_version/'"`(autoconf --version) 2>/dev/null |$SED 1q`"'/ p }' < "$progpath" - exit $? + ret=$? + if test -z "$1"; then + exit $ret + fi } # func_missing_arg argname @@ -546,7 +717,7 @@ func_help () # exit_cmd. func_missing_arg () { - func_error "missing argument for $1" + func_error "missing argument for $1." exit_cmd=exit } @@ -556,29 +727,6 @@ exit_cmd=: -# Check that we have a working $ECHO. -if test "X$1" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift -elif test "X$1" = X--fallback-echo; then - # Avoid inline document here, it may be left over - : -elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t'; then - # Yippee, $ECHO works! - : -else - # Restart under the correct shell, and then maybe $ECHO will work. - exec $SHELL "$progpath" --no-reexec ${1+"$@"} -fi - -if test "X$1" = X--fallback-echo; then - # used as fallback echo - shift - cat </dev/null; then + case $nonopt in *shtool*) :;; *) false;; esac; then # Aesthetically quote it. func_quote_for_eval "$nonopt" install_prog="$func_quote_for_eval_result " @@ -1867,6 +2067,11 @@ func_mode_install () # Aesthetically quote it. func_quote_for_eval "$arg" install_prog="$install_prog$func_quote_for_eval_result" + install_shared_prog=$install_prog + case " $install_prog " in + *[\\\ /]cp\ *) install_cp=: ;; + *) install_cp=false ;; + esac # We need to accept at least all the BSD install flags. dest= @@ -1876,8 +2081,10 @@ func_mode_install () install_type= isdir=no stripme= + no_mode=: for arg do + arg2= if test -n "$dest"; then files="$files $dest" dest=$arg @@ -1887,10 +2094,9 @@ func_mode_install () case $arg in -d) isdir=yes ;; -f) - case " $install_prog " in - *[\\\ /]cp\ *) ;; - *) prev=$arg ;; - esac + if $install_cp; then :; else + prev=$arg + fi ;; -g | -m | -o) prev=$arg @@ -1904,6 +2110,10 @@ func_mode_install () *) # If the previous option needed an argument, then skip it. if test -n "$prev"; then + if test "x$prev" = x-m && test -n "$install_override_mode"; then + arg2=$install_override_mode + no_mode=false + fi prev= else dest=$arg @@ -1915,6 +2125,10 @@ func_mode_install () # Aesthetically quote the argument. func_quote_for_eval "$arg" install_prog="$install_prog $func_quote_for_eval_result" + if test -n "$arg2"; then + func_quote_for_eval "$arg2" + fi + install_shared_prog="$install_shared_prog $func_quote_for_eval_result" done test -z "$install_prog" && \ @@ -1923,6 +2137,13 @@ func_mode_install () test -n "$prev" && \ func_fatal_help "the \`$prev' option requires an argument" + if test -n "$install_override_mode" && $no_mode; then + if $install_cp; then :; else + func_quote_for_eval "$install_override_mode" + install_shared_prog="$install_shared_prog -m $func_quote_for_eval_result" + fi + fi + if test -z "$files"; then if test -z "$dest"; then func_fatal_help "no file or destination specified" @@ -2010,7 +2231,7 @@ func_mode_install () if test -n "$relink_command"; then # Determine the prefix the user has applied to our future dir. - inst_prefix_dir=`$ECHO "X$destdir" | $Xsed -e "s%$libdir\$%%"` + inst_prefix_dir=`$ECHO "$destdir" | $SED -e "s%$libdir\$%%"` # Don't allow the user to place us outside of our expected # location b/c this prevents finding dependent libraries that @@ -2023,9 +2244,9 @@ func_mode_install () if test -n "$inst_prefix_dir"; then # Stick the inst_prefix_dir data into the link command. - relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%-inst-prefix-dir $inst_prefix_dir%"` else - relink_command=`$ECHO "X$relink_command" | $Xsed -e "s%@inst_prefix_dir@%%"` + relink_command=`$ECHO "$relink_command" | $SED "s%@inst_prefix_dir@%%"` fi func_warning "relinking \`$file'" @@ -2043,7 +2264,7 @@ func_mode_install () test -n "$relink_command" && srcname="$realname"T # Install the shared library and build the symlinks. - func_show_eval "$install_prog $dir/$srcname $destdir/$realname" \ + func_show_eval "$install_shared_prog $dir/$srcname $destdir/$realname" \ 'exit $?' tstripme="$stripme" case $host_os in @@ -2183,7 +2404,7 @@ func_mode_install () if test -f "$lib"; then func_source "$lib" fi - libfile="$libdir/"`$ECHO "X$lib" | $Xsed -e 's%^.*/%%g'` ### testsuite: skip nested quoting test + libfile="$libdir/"`$ECHO "$lib" | $SED 's%^.*/%%g'` ### testsuite: skip nested quoting test if test -n "$libdir" && test ! -f "$libfile"; then func_warning "\`$lib' has not been installed in \`$libdir'" finalize=no @@ -2202,7 +2423,7 @@ func_mode_install () file="$func_basename_result" outputname="$tmpdir/$file" # Replace the output file specification. - relink_command=`$ECHO "X$relink_command" | $Xsed -e 's%@OUTPUT@%'"$outputname"'%g'` + relink_command=`$ECHO "$relink_command" | $SED 's%@OUTPUT@%'"$outputname"'%g'` $opt_silent || { func_quote_for_expand "$relink_command" @@ -2221,7 +2442,7 @@ func_mode_install () } else # Install the binary that we compiled earlier. - file=`$ECHO "X$file$stripped_ext" | $Xsed -e "s%\([^/]*\)$%$objdir/\1%"` + file=`$ECHO "$file$stripped_ext" | $SED "s%\([^/]*\)$%$objdir/\1%"` fi fi @@ -2323,6 +2544,10 @@ func_generate_dlsyms () extern \"C\" { #endif +#if defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 4)) +#pragma GCC diagnostic ignored \"-Wstrict-prototypes\" +#endif + /* External symbol declarations for the compiler. */\ " @@ -2332,7 +2557,7 @@ extern \"C\" { $opt_dry_run || echo ': @PROGRAM@ ' > "$nlist" # Add our own program objects to the symbol list. - progfiles=`$ECHO "X$objs$old_deplibs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + progfiles=`$ECHO "$objs$old_deplibs" | $SP2NL | $SED "$lo2o" | $NL2SP` for progfile in $progfiles; do func_verbose "extracting global C symbols from \`$progfile'" $opt_dry_run || eval "$NM $progfile | $global_symbol_pipe >> '$nlist'" @@ -2371,7 +2596,7 @@ extern \"C\" { eval '$GREP -f "$output_objdir/$outputname.exp" < "$nlist" > "$nlist"T' eval '$MV "$nlist"T "$nlist"' case $host in - *cygwin | *mingw* | *cegcc* ) + *cygwin* | *mingw* | *cegcc* ) eval "echo EXPORTS "'> "$output_objdir/$outputname.def"' eval 'cat "$nlist" >> "$output_objdir/$outputname.def"' ;; @@ -2415,10 +2640,10 @@ extern \"C\" { if test -f "$nlist"S; then eval "$global_symbol_to_cdecl"' < "$nlist"S >> "$output_objdir/$my_dlsyms"' else - $ECHO '/* NONE */' >> "$output_objdir/$my_dlsyms" + echo '/* NONE */' >> "$output_objdir/$my_dlsyms" fi - $ECHO >> "$output_objdir/$my_dlsyms" "\ + echo >> "$output_objdir/$my_dlsyms" "\ /* The mapping between symbol names and symbols. */ typedef struct { @@ -2428,7 +2653,7 @@ typedef struct { " case $host in *cygwin* | *mingw* | *cegcc* ) - $ECHO >> "$output_objdir/$my_dlsyms" "\ + echo >> "$output_objdir/$my_dlsyms" "\ /* DATA imports from DLLs on WIN32 con't be const, because runtime relocations are performed -- see ld's documentation on pseudo-relocs. */" @@ -2441,7 +2666,7 @@ typedef struct { lt_dlsym_const=const ;; esac - $ECHO >> "$output_objdir/$my_dlsyms" "\ + echo >> "$output_objdir/$my_dlsyms" "\ extern $lt_dlsym_const lt_dlsymlist lt_${my_prefix}_LTX_preloaded_symbols[]; $lt_dlsym_const lt_dlsymlist @@ -2457,7 +2682,7 @@ lt_${my_prefix}_LTX_preloaded_symbols[] = eval "$global_symbol_to_c_name_address_lib_prefix" < "$nlist" >> "$output_objdir/$my_dlsyms" ;; esac - $ECHO >> "$output_objdir/$my_dlsyms" "\ + echo >> "$output_objdir/$my_dlsyms" "\ {0, (void *) 0} }; @@ -2515,16 +2740,16 @@ static const void *lt_preloaded_setup() { case $host in *cygwin* | *mingw* | *cegcc* ) if test -f "$output_objdir/$my_outputname.def"; then - compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` - finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$output_objdir/$my_outputname.def $symfileobj%"` else - compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` - finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` fi ;; *) - compile_command=`$ECHO "X$compile_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` - finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s%@SYMFILE@%$symfileobj%"` + compile_command=`$ECHO "$compile_command" | $SED "s%@SYMFILE@%$symfileobj%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s%@SYMFILE@%$symfileobj%"` ;; esac ;; @@ -2538,8 +2763,8 @@ static const void *lt_preloaded_setup() { # really was required. # Nullify the symbol file. - compile_command=`$ECHO "X$compile_command" | $Xsed -e "s% @SYMFILE@%%"` - finalize_command=`$ECHO "X$finalize_command" | $Xsed -e "s% @SYMFILE@%%"` + compile_command=`$ECHO "$compile_command" | $SED "s% @SYMFILE@%%"` + finalize_command=`$ECHO "$finalize_command" | $SED "s% @SYMFILE@%%"` fi } @@ -2549,6 +2774,7 @@ static const void *lt_preloaded_setup() { # Need a lot of goo to handle *both* DLLs and import libs # Has to be a shell function in order to 'eat' the argument # that is supplied when $file_magic_command is called. +# Despite the name, also deal with 64 bit binaries. func_win32_libid () { $opt_debug @@ -2559,8 +2785,9 @@ func_win32_libid () win32_libid_type="x86 archive import" ;; *ar\ archive*) # could be an import, or static + # Keep the egrep pattern in sync with the one in _LT_CHECK_MAGIC_METHOD. if eval $OBJDUMP -f $1 | $SED -e '10q' 2>/dev/null | - $EGREP 'file format pe-i386(.*architecture: i386)?' >/dev/null ; then + $EGREP 'file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' >/dev/null; then win32_nmres=`eval $NM -f posix -A $1 | $SED -n -e ' 1,100{ @@ -2598,7 +2825,18 @@ func_extract_an_archive () $opt_debug f_ex_an_ar_dir="$1"; shift f_ex_an_ar_oldlib="$1" - func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" 'exit $?' + if test "$lock_old_archive_extraction" = yes; then + lockfile=$f_ex_an_ar_oldlib.lock + until $opt_dry_run || ln "$progpath" "$lockfile" 2>/dev/null; do + func_echo "Waiting for $lockfile to be removed" + sleep 2 + done + fi + func_show_eval "(cd \$f_ex_an_ar_dir && $AR x \"\$f_ex_an_ar_oldlib\")" \ + 'stat=$?; rm -f "$lockfile"; exit $stat' + if test "$lock_old_archive_extraction" = yes; then + $opt_dry_run || rm -f "$lockfile" + fi if ($AR t "$f_ex_an_ar_oldlib" | sort | sort -uc >/dev/null 2>&1); then : else @@ -2669,7 +2907,7 @@ func_extract_archives () darwin_file= darwin_files= for darwin_file in $darwin_filelist; do - darwin_files=`find unfat-$$ -name $darwin_file -print | $NL2SP` + darwin_files=`find unfat-$$ -name $darwin_file -print | sort | $NL2SP` $LIPO -create -output "$darwin_file" $darwin_files done # $darwin_filelist $RM -rf unfat-$$ @@ -2684,25 +2922,30 @@ func_extract_archives () func_extract_an_archive "$my_xdir" "$my_xabs" ;; esac - my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | $NL2SP` + my_oldobjs="$my_oldobjs "`find $my_xdir -name \*.$objext -print -o -name \*.lo -print | sort | $NL2SP` done func_extract_archives_result="$my_oldobjs" } - -# func_emit_wrapper_part1 [arg=no] +# func_emit_wrapper [arg=no] +# +# Emit a libtool wrapper script on stdout. +# Don't directly open a file because we may want to +# incorporate the script contents within a cygwin/mingw +# wrapper executable. Must ONLY be called from within +# func_mode_link because it depends on a number of variables +# set therein. # -# Emit the first part of a libtool wrapper script on stdout. -# For more information, see the description associated with -# func_emit_wrapper(), below. -func_emit_wrapper_part1 () +# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR +# variable will take. If 'yes', then the emitted script +# will assume that the directory in which it is stored is +# the $objdir directory. This is a cygwin/mingw-specific +# behavior. +func_emit_wrapper () { - func_emit_wrapper_part1_arg1=no - if test -n "$1" ; then - func_emit_wrapper_part1_arg1=$1 - fi + func_emit_wrapper_arg1=${1-no} $ECHO "\ #! $SHELL @@ -2718,7 +2961,6 @@ func_emit_wrapper_part1 () # Sed substitution that helps us do robust quoting. It backslashifies # metacharacters that are still active within double-quoted strings. -Xsed='${SED} -e 1s/^X//' sed_quote_subst='$sed_quote_subst' # Be Bourne compatible @@ -2749,31 +2991,132 @@ if test \"\$libtool_install_magic\" = \"$magic\"; then else # When we are sourced in execute mode, \$file and \$ECHO are already set. if test \"\$libtool_execute_magic\" != \"$magic\"; then - ECHO=\"$qecho\" - file=\"\$0\" - # Make sure echo works. - if test \"X\$1\" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift - elif test \"X\`{ \$ECHO '\t'; } 2>/dev/null\`\" = 'X\t'; then - # Yippee, \$ECHO works! - : - else - # Restart under the correct shell, and then maybe \$ECHO will work. - exec $SHELL \"\$0\" --no-reexec \${1+\"\$@\"} - fi - fi\ + file=\"\$0\"" + + qECHO=`$ECHO "$ECHO" | $SED "$sed_quote_subst"` + $ECHO "\ + +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$1 +_LTECHO_EOF' +} + ECHO=\"$qECHO\" + fi + +# Very basic option parsing. These options are (a) specific to +# the libtool wrapper, (b) are identical between the wrapper +# /script/ and the wrapper /executable/ which is used only on +# windows platforms, and (c) all begin with the string "--lt-" +# (application programs are unlikely to have options which match +# this pattern). +# +# There are only two supported options: --lt-debug and +# --lt-dump-script. There is, deliberately, no --lt-help. +# +# The first argument to this parsing function should be the +# script's $0 value, followed by "$@". +lt_option_debug= +func_parse_lt_options () +{ + lt_script_arg0=\$0 + shift + for lt_opt + do + case \"\$lt_opt\" in + --lt-debug) lt_option_debug=1 ;; + --lt-dump-script) + lt_dump_D=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%/[^/]*$%%'\` + test \"X\$lt_dump_D\" = \"X\$lt_script_arg0\" && lt_dump_D=. + lt_dump_F=\`\$ECHO \"X\$lt_script_arg0\" | $SED -e 's/^X//' -e 's%^.*/%%'\` + cat \"\$lt_dump_D/\$lt_dump_F\" + exit 0 + ;; + --lt-*) + \$ECHO \"Unrecognized --lt- option: '\$lt_opt'\" 1>&2 + exit 1 + ;; + esac + done + + # Print the debug banner immediately: + if test -n \"\$lt_option_debug\"; then + echo \"${outputname}:${output}:\${LINENO}: libtool wrapper (GNU $PACKAGE$TIMESTAMP) $VERSION\" 1>&2 + fi +} + +# Used when --lt-debug. Prints its arguments to stdout +# (redirection is the responsibility of the caller) +func_lt_dump_args () +{ + lt_dump_args_N=1; + for lt_arg + do + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[\$lt_dump_args_N]: \$lt_arg\" + lt_dump_args_N=\`expr \$lt_dump_args_N + 1\` + done +} + +# Core function for launching the target application +func_exec_program_core () +{ " - $ECHO "\ + case $host in + # Backslashes separate directories on plain windows + *-*-mingw | *-*-os2* | *-cegcc*) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir\\\\\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} +" + ;; + + *) + $ECHO "\ + if test -n \"\$lt_option_debug\"; then + \$ECHO \"${outputname}:${output}:\${LINENO}: newargv[0]: \$progdir/\$program\" 1>&2 + func_lt_dump_args \${1+\"\$@\"} 1>&2 + fi + exec \"\$progdir/\$program\" \${1+\"\$@\"} +" + ;; + esac + $ECHO "\ + \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 + exit 1 +} + +# A function to encapsulate launching the target application +# Strips options in the --lt-* namespace from \$@ and +# launches target application with the remaining arguments. +func_exec_program () +{ + for lt_wr_arg + do + case \$lt_wr_arg in + --lt-*) ;; + *) set x \"\$@\" \"\$lt_wr_arg\"; shift;; + esac + shift + done + func_exec_program_core \${1+\"\$@\"} +} + + # Parse options + func_parse_lt_options \"\$0\" \${1+\"\$@\"} # Find the directory that this script lives in. - thisdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*$%%'\` + thisdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*$%%'\` test \"x\$thisdir\" = \"x\$file\" && thisdir=. # Follow symbolic links until we get to the real thisdir. - file=\`ls -ld \"\$file\" | ${SED} -n 's/.*-> //p'\` + file=\`ls -ld \"\$file\" | $SED -n 's/.*-> //p'\` while test -n \"\$file\"; do - destdir=\`\$ECHO \"X\$file\" | \$Xsed -e 's%/[^/]*\$%%'\` + destdir=\`\$ECHO \"\$file\" | $SED 's%/[^/]*\$%%'\` # If there was a directory component, then change thisdir. if test \"x\$destdir\" != \"x\$file\"; then @@ -2783,30 +3126,13 @@ else esac fi - file=\`\$ECHO \"X\$file\" | \$Xsed -e 's%^.*/%%'\` - file=\`ls -ld \"\$thisdir/\$file\" | ${SED} -n 's/.*-> //p'\` + file=\`\$ECHO \"\$file\" | $SED 's%^.*/%%'\` + file=\`ls -ld \"\$thisdir/\$file\" | $SED -n 's/.*-> //p'\` done -" -} -# end: func_emit_wrapper_part1 - -# func_emit_wrapper_part2 [arg=no] -# -# Emit the second part of a libtool wrapper script on stdout. -# For more information, see the description associated with -# func_emit_wrapper(), below. -func_emit_wrapper_part2 () -{ - func_emit_wrapper_part2_arg1=no - if test -n "$1" ; then - func_emit_wrapper_part2_arg1=$1 - fi - - $ECHO "\ # Usually 'no', except on cygwin/mingw when embedded into # the cwrapper. - WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_part2_arg1 + WRAPPER_SCRIPT_BELONGS_IN_OBJDIR=$func_emit_wrapper_arg1 if test \"\$WRAPPER_SCRIPT_BELONGS_IN_OBJDIR\" = \"yes\"; then # special case for '.' if test \"\$thisdir\" = \".\"; then @@ -2814,7 +3140,7 @@ func_emit_wrapper_part2 () fi # remove .libs from thisdir case \"\$thisdir\" in - *[\\\\/]$objdir ) thisdir=\`\$ECHO \"X\$thisdir\" | \$Xsed -e 's%[\\\\/][^\\\\/]*$%%'\` ;; + *[\\\\/]$objdir ) thisdir=\`\$ECHO \"\$thisdir\" | $SED 's%[\\\\/][^\\\\/]*$%%'\` ;; $objdir ) thisdir=. ;; esac fi @@ -2877,7 +3203,7 @@ func_emit_wrapper_part2 () # Some systems cannot cope with colon-terminated $shlibpath_var # The second colon is a workaround for a bug in BeOS R4 sed - $shlibpath_var=\`\$ECHO \"X\$$shlibpath_var\" | \$Xsed -e 's/::*\$//'\` + $shlibpath_var=\`\$ECHO \"\$$shlibpath_var\" | $SED 's/::*\$//'\` export $shlibpath_var " @@ -2894,64 +3220,18 @@ func_emit_wrapper_part2 () $ECHO "\ if test \"\$libtool_execute_magic\" != \"$magic\"; then # Run the actual program with our arguments. -" - case $host in - # Backslashes separate directories on plain windows - *-*-mingw | *-*-os2* | *-cegcc*) - $ECHO "\ - exec \"\$progdir\\\\\$program\" \${1+\"\$@\"} -" - ;; - - *) - $ECHO "\ - exec \"\$progdir/\$program\" \${1+\"\$@\"} -" - ;; - esac - $ECHO "\ - \$ECHO \"\$0: cannot exec \$program \$*\" 1>&2 - exit 1 + func_exec_program \${1+\"\$@\"} fi else # The program doesn't exist. \$ECHO \"\$0: error: \\\`\$progdir/\$program' does not exist\" 1>&2 \$ECHO \"This script is just a wrapper for \$program.\" 1>&2 - $ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 + \$ECHO \"See the $PACKAGE documentation for more information.\" 1>&2 exit 1 fi fi\ " } -# end: func_emit_wrapper_part2 - - -# func_emit_wrapper [arg=no] -# -# Emit a libtool wrapper script on stdout. -# Don't directly open a file because we may want to -# incorporate the script contents within a cygwin/mingw -# wrapper executable. Must ONLY be called from within -# func_mode_link because it depends on a number of variables -# set therein. -# -# ARG is the value that the WRAPPER_SCRIPT_BELONGS_IN_OBJDIR -# variable will take. If 'yes', then the emitted script -# will assume that the directory in which it is stored is -# the $objdir directory. This is a cygwin/mingw-specific -# behavior. -func_emit_wrapper () -{ - func_emit_wrapper_arg1=no - if test -n "$1" ; then - func_emit_wrapper_arg1=$1 - fi - - # split this up so that func_emit_cwrapperexe_src - # can call each part independently. - func_emit_wrapper_part1 "${func_emit_wrapper_arg1}" - func_emit_wrapper_part2 "${func_emit_wrapper_arg1}" -} # func_to_host_path arg @@ -2978,23 +3258,19 @@ func_emit_wrapper () func_to_host_path () { func_to_host_path_result="$1" - if test -n "$1" ; then + if test -n "$1"; then case $host in *mingw* ) lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' case $build in *mingw* ) # actually, msys # awkward: cmd appends spaces to result - lt_sed_strip_trailing_spaces="s/[ ]*\$//" - func_to_host_path_tmp1=`( cmd //c echo "$1" |\ - $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` - func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ - $SED -e "$lt_sed_naive_backslashify"` + func_to_host_path_result=`( cmd //c echo "$1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` ;; *cygwin* ) - func_to_host_path_tmp1=`cygpath -w "$1"` - func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ - $SED -e "$lt_sed_naive_backslashify"` + func_to_host_path_result=`cygpath -w "$1" | + $SED -e "$lt_sed_naive_backslashify"` ;; * ) # Unfortunately, winepath does not exit with a non-zero @@ -3006,17 +3282,17 @@ func_to_host_path () # the odd construction: func_to_host_path_tmp1=`winepath -w "$1" 2>/dev/null` if test "$?" -eq 0 && test -n "${func_to_host_path_tmp1}"; then - func_to_host_path_result=`echo "$func_to_host_path_tmp1" |\ + func_to_host_path_result=`$ECHO "$func_to_host_path_tmp1" | $SED -e "$lt_sed_naive_backslashify"` else # Allow warning below. - func_to_host_path_result="" + func_to_host_path_result= fi ;; esac if test -z "$func_to_host_path_result" ; then func_error "Could not determine host path corresponding to" - func_error " '$1'" + func_error " \`$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback: func_to_host_path_result="$1" @@ -3049,30 +3325,24 @@ func_to_host_path () func_to_host_pathlist () { func_to_host_pathlist_result="$1" - if test -n "$1" ; then + if test -n "$1"; then case $host in *mingw* ) lt_sed_naive_backslashify='s|\\\\*|\\|g;s|/|\\|g;s|\\|\\\\|g' # Remove leading and trailing path separator characters from # ARG. msys behavior is inconsistent here, cygpath turns them # into '.;' and ';.', and winepath ignores them completely. - func_to_host_pathlist_tmp2="$1" - # Once set for this call, this variable should not be - # reassigned. It is used in tha fallback case. - func_to_host_pathlist_tmp1=`echo "$func_to_host_pathlist_tmp2" |\ - $SED -e 's|^:*||' -e 's|:*$||'` + func_stripname : : "$1" + func_to_host_pathlist_tmp1=$func_stripname_result case $build in *mingw* ) # Actually, msys. # Awkward: cmd appends spaces to result. - lt_sed_strip_trailing_spaces="s/[ ]*\$//" - func_to_host_pathlist_tmp2=`( cmd //c echo "$func_to_host_pathlist_tmp1" |\ - $SED -e "$lt_sed_strip_trailing_spaces" ) 2>/dev/null || echo ""` - func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ - $SED -e "$lt_sed_naive_backslashify"` + func_to_host_pathlist_result=` + ( cmd //c echo "$func_to_host_pathlist_tmp1" ) 2>/dev/null | + $SED -e 's/[ ]*$//' -e "$lt_sed_naive_backslashify"` ;; *cygwin* ) - func_to_host_pathlist_tmp2=`cygpath -w -p "$func_to_host_pathlist_tmp1"` - func_to_host_pathlist_result=`echo "$func_to_host_pathlist_tmp2" |\ + func_to_host_pathlist_result=`cygpath -w -p "$func_to_host_pathlist_tmp1" | $SED -e "$lt_sed_naive_backslashify"` ;; * ) @@ -3088,18 +3358,17 @@ func_to_host_pathlist () if test -z "$func_to_host_pathlist_result" ; then func_to_host_pathlist_result="$func_to_host_path_result" else - func_to_host_pathlist_result="$func_to_host_pathlist_result;$func_to_host_path_result" + func_append func_to_host_pathlist_result ";$func_to_host_path_result" fi fi fi - IFS=: done IFS=$func_to_host_pathlist_oldIFS ;; esac - if test -z "$func_to_host_pathlist_result" ; then + if test -z "$func_to_host_pathlist_result"; then func_error "Could not determine the host path(s) corresponding to" - func_error " '$1'" + func_error " \`$1'" func_error "Continuing, but uninstalled executables may not work." # Fallback. This may break if $1 contains DOS-style drive # specifications. The fix is not to complicate the expression @@ -3116,7 +3385,7 @@ func_to_host_pathlist () ;; esac case "$1" in - *: ) func_to_host_pathlist_result="$func_to_host_pathlist_result;" + *: ) func_append func_to_host_pathlist_result ";" ;; esac ;; @@ -3141,31 +3410,23 @@ func_emit_cwrapperexe_src () This wrapper executable should never be moved out of the build directory. If it is, it will not operate correctly. - - Currently, it simply execs the wrapper *script* "$SHELL $output", - but could eventually absorb all of the scripts functionality and - exec $objdir/$outputname directly. */ EOF cat <<"EOF" +#ifdef _MSC_VER +# define _CRT_SECURE_NO_DEPRECATE 1 +#endif #include #include #ifdef _MSC_VER # include # include # include -# define setmode _setmode #else # include # include # ifdef __CYGWIN__ # include -# define HAVE_SETENV -# ifdef __STRICT_ANSI__ -char *realpath (const char *, char *); -int putenv (char *); -int setenv (const char *, const char *, int); -# endif # endif #endif #include @@ -3177,6 +3438,44 @@ int setenv (const char *, const char *, int); #include #include +/* declarations of non-ANSI functions */ +#if defined(__MINGW32__) +# ifdef __STRICT_ANSI__ +int _putenv (const char *); +# endif +#elif defined(__CYGWIN__) +# ifdef __STRICT_ANSI__ +char *realpath (const char *, char *); +int putenv (char *); +int setenv (const char *, const char *, int); +# endif +/* #elif defined (other platforms) ... */ +#endif + +/* portability defines, excluding path handling macros */ +#if defined(_MSC_VER) +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +# define S_IXUSR _S_IEXEC +# ifndef _INTPTR_T_DEFINED +# define _INTPTR_T_DEFINED +# define intptr_t int +# endif +#elif defined(__MINGW32__) +# define setmode _setmode +# define stat _stat +# define chmod _chmod +# define getcwd _getcwd +# define putenv _putenv +#elif defined(__CYGWIN__) +# define HAVE_SETENV +# define FOPEN_WB "wb" +/* #elif defined (other platforms) ... */ +#endif + #if defined(PATH_MAX) # define LT_PATHMAX PATH_MAX #elif defined(MAXPATHLEN) @@ -3192,14 +3491,7 @@ int setenv (const char *, const char *, int); # define S_IXGRP 0 #endif -#ifdef _MSC_VER -# define S_IXUSR _S_IEXEC -# define stat _stat -# ifndef _INTPTR_T_DEFINED -# define intptr_t int -# endif -#endif - +/* path handling portability macros */ #ifndef DIR_SEPARATOR # define DIR_SEPARATOR '/' # define PATH_SEPARATOR ':' @@ -3230,10 +3522,6 @@ int setenv (const char *, const char *, int); # define IS_PATH_SEPARATOR(ch) ((ch) == PATH_SEPARATOR_2) #endif /* PATH_SEPARATOR_2 */ -#ifdef __CYGWIN__ -# define FOPEN_WB "wb" -#endif - #ifndef FOPEN_WB # define FOPEN_WB "w" #endif @@ -3246,22 +3534,13 @@ int setenv (const char *, const char *, int); if (stale) { free ((void *) stale); stale = 0; } \ } while (0) -#undef LTWRAPPER_DEBUGPRINTF -#if defined DEBUGWRAPPER -# define LTWRAPPER_DEBUGPRINTF(args) ltwrapper_debugprintf args -static void -ltwrapper_debugprintf (const char *fmt, ...) -{ - va_list args; - va_start (args, fmt); - (void) vfprintf (stderr, fmt, args); - va_end (args); -} +#if defined(LT_DEBUGWRAPPER) +static int lt_debug = 1; #else -# define LTWRAPPER_DEBUGPRINTF(args) +static int lt_debug = 0; #endif -const char *program_name = NULL; +const char *program_name = "libtool-wrapper"; /* in case xstrdup fails */ void *xmalloc (size_t num); char *xstrdup (const char *string); @@ -3271,31 +3550,17 @@ char *chase_symlinks (const char *pathspec); int make_executable (const char *path); int check_executable (const char *path); char *strendzap (char *str, const char *pat); -void lt_fatal (const char *message, ...); +void lt_debugprintf (const char *file, int line, const char *fmt, ...); +void lt_fatal (const char *file, int line, const char *message, ...); +static const char *nonnull (const char *s); +static const char *nonempty (const char *s); void lt_setenv (const char *name, const char *value); char *lt_extend_str (const char *orig_value, const char *add, int to_end); -void lt_opt_process_env_set (const char *arg); -void lt_opt_process_env_prepend (const char *arg); -void lt_opt_process_env_append (const char *arg); -int lt_split_name_value (const char *arg, char** name, char** value); void lt_update_exe_path (const char *name, const char *value); void lt_update_lib_path (const char *name, const char *value); - -static const char *script_text_part1 = -EOF - - func_emit_wrapper_part1 yes | - $SED -e 's/\([\\"]\)/\\\1/g' \ - -e 's/^/ "/' -e 's/$/\\n"/' - echo ";" - cat <"))); + lt_debugprintf (__FILE__, __LINE__, "(main) lt_argv_zero: %s\n", + nonnull (lt_argv_zero)); for (i = 0; i < newargc; i++) { - LTWRAPPER_DEBUGPRINTF (("(main) newargz[%d] : %s\n", i, (newargz[i] ? newargz[i] : ""))); + lt_debugprintf (__FILE__, __LINE__, "(main) newargz[%d]: %s\n", + i, nonnull (newargz[i])); } EOF @@ -3560,11 +3782,14 @@ EOF mingw*) cat <<"EOF" /* execv doesn't actually work on mingw as expected on unix */ + newargz = prepare_spawn (newargz); rval = _spawnv (_P_WAIT, lt_argv_zero, (const char * const *) newargz); if (rval == -1) { /* failed to start process */ - LTWRAPPER_DEBUGPRINTF (("(main) failed to launch target \"%s\": errno = %d\n", lt_argv_zero, errno)); + lt_debugprintf (__FILE__, __LINE__, + "(main) failed to launch target \"%s\": %s\n", + lt_argv_zero, nonnull (strerror (errno))); return 127; } return rval; @@ -3586,7 +3811,7 @@ xmalloc (size_t num) { void *p = (void *) malloc (num); if (!p) - lt_fatal ("Memory exhausted"); + lt_fatal (__FILE__, __LINE__, "memory exhausted"); return p; } @@ -3620,8 +3845,8 @@ check_executable (const char *path) { struct stat st; - LTWRAPPER_DEBUGPRINTF (("(check_executable) : %s\n", - path ? (*path ? path : "EMPTY!") : "NULL!")); + lt_debugprintf (__FILE__, __LINE__, "(check_executable): %s\n", + nonempty (path)); if ((!path) || (!*path)) return 0; @@ -3638,8 +3863,8 @@ make_executable (const char *path) int rval = 0; struct stat st; - LTWRAPPER_DEBUGPRINTF (("(make_executable) : %s\n", - path ? (*path ? path : "EMPTY!") : "NULL!")); + lt_debugprintf (__FILE__, __LINE__, "(make_executable): %s\n", + nonempty (path)); if ((!path) || (!*path)) return 0; @@ -3665,8 +3890,8 @@ find_executable (const char *wrapper) int tmp_len; char *concat_name; - LTWRAPPER_DEBUGPRINTF (("(find_executable) : %s\n", - wrapper ? (*wrapper ? wrapper : "EMPTY!") : "NULL!")); + lt_debugprintf (__FILE__, __LINE__, "(find_executable): %s\n", + nonempty (wrapper)); if ((wrapper == NULL) || (*wrapper == '\0')) return NULL; @@ -3719,7 +3944,8 @@ find_executable (const char *wrapper) { /* empty path: current directory */ if (getcwd (tmp, LT_PATHMAX) == NULL) - lt_fatal ("getcwd failed"); + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); @@ -3744,7 +3970,8 @@ find_executable (const char *wrapper) } /* Relative path | not found in path: prepend cwd */ if (getcwd (tmp, LT_PATHMAX) == NULL) - lt_fatal ("getcwd failed"); + lt_fatal (__FILE__, __LINE__, "getcwd failed: %s", + nonnull (strerror (errno))); tmp_len = strlen (tmp); concat_name = XMALLOC (char, tmp_len + 1 + strlen (wrapper) + 1); memcpy (concat_name, tmp, tmp_len); @@ -3770,8 +3997,9 @@ chase_symlinks (const char *pathspec) int has_symlinks = 0; while (strlen (tmp_pathspec) && !has_symlinks) { - LTWRAPPER_DEBUGPRINTF (("checking path component for symlinks: %s\n", - tmp_pathspec)); + lt_debugprintf (__FILE__, __LINE__, + "checking path component for symlinks: %s\n", + tmp_pathspec); if (lstat (tmp_pathspec, &s) == 0) { if (S_ISLNK (s.st_mode) != 0) @@ -3793,8 +4021,9 @@ chase_symlinks (const char *pathspec) } else { - char *errstr = strerror (errno); - lt_fatal ("Error accessing file %s (%s)", tmp_pathspec, errstr); + lt_fatal (__FILE__, __LINE__, + "error accessing file \"%s\": %s", + tmp_pathspec, nonnull (strerror (errno))); } } XFREE (tmp_pathspec); @@ -3807,7 +4036,8 @@ chase_symlinks (const char *pathspec) tmp_pathspec = realpath (pathspec, buf); if (tmp_pathspec == 0) { - lt_fatal ("Could not follow symlinks for %s", pathspec); + lt_fatal (__FILE__, __LINE__, + "could not follow symlinks for %s", pathspec); } return xstrdup (tmp_pathspec); #endif @@ -3833,11 +4063,25 @@ strendzap (char *str, const char *pat) return str; } +void +lt_debugprintf (const char *file, int line, const char *fmt, ...) +{ + va_list args; + if (lt_debug) + { + (void) fprintf (stderr, "%s:%s:%d: ", program_name, file, line); + va_start (args, fmt); + (void) vfprintf (stderr, fmt, args); + va_end (args); + } +} + static void -lt_error_core (int exit_status, const char *mode, +lt_error_core (int exit_status, const char *file, + int line, const char *mode, const char *message, va_list ap) { - fprintf (stderr, "%s: %s: ", program_name, mode); + fprintf (stderr, "%s:%s:%d: %s: ", program_name, file, line, mode); vfprintf (stderr, message, ap); fprintf (stderr, ".\n"); @@ -3846,20 +4090,32 @@ lt_error_core (int exit_status, const char *mode, } void -lt_fatal (const char *message, ...) +lt_fatal (const char *file, int line, const char *message, ...) { va_list ap; va_start (ap, message); - lt_error_core (EXIT_FAILURE, "FATAL", message, ap); + lt_error_core (EXIT_FAILURE, file, line, "FATAL", message, ap); va_end (ap); } +static const char * +nonnull (const char *s) +{ + return s ? s : "(null)"; +} + +static const char * +nonempty (const char *s) +{ + return (s && !*s) ? "(empty)" : nonnull (s); +} + void lt_setenv (const char *name, const char *value) { - LTWRAPPER_DEBUGPRINTF (("(lt_setenv) setting '%s' to '%s'\n", - (name ? name : ""), - (value ? value : ""))); + lt_debugprintf (__FILE__, __LINE__, + "(lt_setenv) setting '%s' to '%s'\n", + nonnull (name), nonnull (value)); { #ifdef HAVE_SETENV /* always make a copy, for consistency with !HAVE_SETENV */ @@ -3904,95 +4160,12 @@ lt_extend_str (const char *orig_value, const char *add, int to_end) return new_value; } -int -lt_split_name_value (const char *arg, char** name, char** value) -{ - const char *p; - int len; - if (!arg || !*arg) - return 1; - - p = strchr (arg, (int)'='); - - if (!p) - return 1; - - *value = xstrdup (++p); - - len = strlen (arg) - strlen (*value); - *name = XMALLOC (char, len); - strncpy (*name, arg, len-1); - (*name)[len - 1] = '\0'; - - return 0; -} - -void -lt_opt_process_env_set (const char *arg) -{ - char *name = NULL; - char *value = NULL; - - if (lt_split_name_value (arg, &name, &value) != 0) - { - XFREE (name); - XFREE (value); - lt_fatal ("bad argument for %s: '%s'", env_set_opt, arg); - } - - lt_setenv (name, value); - XFREE (name); - XFREE (value); -} - -void -lt_opt_process_env_prepend (const char *arg) -{ - char *name = NULL; - char *value = NULL; - char *new_value = NULL; - - if (lt_split_name_value (arg, &name, &value) != 0) - { - XFREE (name); - XFREE (value); - lt_fatal ("bad argument for %s: '%s'", env_prepend_opt, arg); - } - - new_value = lt_extend_str (getenv (name), value, 0); - lt_setenv (name, new_value); - XFREE (new_value); - XFREE (name); - XFREE (value); -} - -void -lt_opt_process_env_append (const char *arg) -{ - char *name = NULL; - char *value = NULL; - char *new_value = NULL; - - if (lt_split_name_value (arg, &name, &value) != 0) - { - XFREE (name); - XFREE (value); - lt_fatal ("bad argument for %s: '%s'", env_append_opt, arg); - } - - new_value = lt_extend_str (getenv (name), value, 1); - lt_setenv (name, new_value); - XFREE (new_value); - XFREE (name); - XFREE (value); -} - void lt_update_exe_path (const char *name, const char *value) { - LTWRAPPER_DEBUGPRINTF (("(lt_update_exe_path) modifying '%s' by prepending '%s'\n", - (name ? name : ""), - (value ? value : ""))); + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_exe_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); if (name && *name && value && *value) { @@ -4011,9 +4184,9 @@ lt_update_exe_path (const char *name, const char *value) void lt_update_lib_path (const char *name, const char *value) { - LTWRAPPER_DEBUGPRINTF (("(lt_update_lib_path) modifying '%s' by prepending '%s'\n", - (name ? name : ""), - (value ? value : ""))); + lt_debugprintf (__FILE__, __LINE__, + "(lt_update_lib_path) modifying '%s' by prepending '%s'\n", + nonnull (name), nonnull (value)); if (name && *name && value && *value) { @@ -4023,11 +4196,152 @@ lt_update_lib_path (const char *name, const char *value) } } +EOF + case $host_os in + mingw*) + cat <<"EOF" + +/* Prepares an argument vector before calling spawn(). + Note that spawn() does not by itself call the command interpreter + (getenv ("COMSPEC") != NULL ? getenv ("COMSPEC") : + ({ OSVERSIONINFO v; v.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); + GetVersionEx(&v); + v.dwPlatformId == VER_PLATFORM_WIN32_NT; + }) ? "cmd.exe" : "command.com"). + Instead it simply concatenates the arguments, separated by ' ', and calls + CreateProcess(). We must quote the arguments since Win32 CreateProcess() + interprets characters like ' ', '\t', '\\', '"' (but not '<' and '>') in a + special way: + - Space and tab are interpreted as delimiters. They are not treated as + delimiters if they are surrounded by double quotes: "...". + - Unescaped double quotes are removed from the input. Their only effect is + that within double quotes, space and tab are treated like normal + characters. + - Backslashes not followed by double quotes are not special. + - But 2*n+1 backslashes followed by a double quote become + n backslashes followed by a double quote (n >= 0): + \" -> " + \\\" -> \" + \\\\\" -> \\" + */ +#define SHELL_SPECIAL_CHARS "\"\\ \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +#define SHELL_SPACE_CHARS " \001\002\003\004\005\006\007\010\011\012\013\014\015\016\017\020\021\022\023\024\025\026\027\030\031\032\033\034\035\036\037" +char ** +prepare_spawn (char **argv) +{ + size_t argc; + char **new_argv; + size_t i; + + /* Count number of arguments. */ + for (argc = 0; argv[argc] != NULL; argc++) + ; + + /* Allocate new argument vector. */ + new_argv = XMALLOC (char *, argc + 1); + + /* Put quoted arguments into the new argument vector. */ + for (i = 0; i < argc; i++) + { + const char *string = argv[i]; + + if (string[0] == '\0') + new_argv[i] = xstrdup ("\"\""); + else if (strpbrk (string, SHELL_SPECIAL_CHARS) != NULL) + { + int quote_around = (strpbrk (string, SHELL_SPACE_CHARS) != NULL); + size_t length; + unsigned int backslashes; + const char *s; + char *quoted_string; + char *p; + + length = 0; + backslashes = 0; + if (quote_around) + length++; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + length += backslashes + 1; + length++; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + length += backslashes + 1; + + quoted_string = XMALLOC (char, length + 1); + + p = quoted_string; + backslashes = 0; + if (quote_around) + *p++ = '"'; + for (s = string; *s != '\0'; s++) + { + char c = *s; + if (c == '"') + { + unsigned int j; + for (j = backslashes + 1; j > 0; j--) + *p++ = '\\'; + } + *p++ = c; + if (c == '\\') + backslashes++; + else + backslashes = 0; + } + if (quote_around) + { + unsigned int j; + for (j = backslashes; j > 0; j--) + *p++ = '\\'; + *p++ = '"'; + } + *p = '\0'; + + new_argv[i] = quoted_string; + } + else + new_argv[i] = (char *) string; + } + new_argv[argc] = NULL; + + return new_argv; +} +EOF + ;; + esac + + cat <<"EOF" +void lt_dump_script (FILE* f) +{ +EOF + func_emit_wrapper yes | + $SED -e 's/\([\\"]\)/\\\1/g' \ + -e 's/^/ fputs ("/' -e 's/$/\\n", f);/' + cat <<"EOF" +} EOF } # end: func_emit_cwrapperexe_src +# func_win32_import_lib_p ARG +# True if ARG is an import lib, as indicated by $file_magic_cmd +func_win32_import_lib_p () +{ + $opt_debug + case `eval $file_magic_cmd \"\$1\" 2>/dev/null | $SED -e 10q` in + *import*) : ;; + *) false ;; + esac +} + # func_mode_link arg... func_mode_link () { @@ -4072,6 +4386,7 @@ func_mode_link () new_inherited_linker_flags= avoid_version=no + bindir= dlfiles= dlprefiles= dlself=no @@ -4164,6 +4479,11 @@ func_mode_link () esac case $prev in + bindir) + bindir="$arg" + prev= + continue + ;; dlfiles|dlprefiles) if test "$preload" = no; then # Add the symbol object into the linking commands. @@ -4425,6 +4745,11 @@ func_mode_link () continue ;; + -bindir) + prev=bindir + continue + ;; + -dlopen) prev=dlfiles continue @@ -4503,7 +4828,7 @@ func_mode_link () esac case $host in *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-cegcc*) - testbindir=`$ECHO "X$dir" | $Xsed -e 's*/lib$*/bin*'` + testbindir=`$ECHO "$dir" | $SED 's*/lib$*/bin*'` case :$dllsearchpath: in *":$dir:"*) ;; ::) dllsearchpath=$dir;; @@ -4522,7 +4847,7 @@ func_mode_link () -l*) if test "X$arg" = "X-lc" || test "X$arg" = "X-lm"; then case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc*) + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-beos* | *-cegcc* | *-*-haiku*) # These systems don't actually have a C or math library (as such) continue ;; @@ -4708,7 +5033,7 @@ func_mode_link () for flag in $args; do IFS="$save_ifs" func_quote_for_eval "$flag" - arg="$arg $wl$func_quote_for_eval_result" + arg="$arg $func_quote_for_eval_result" compiler_flags="$compiler_flags $func_quote_for_eval_result" done IFS="$save_ifs" @@ -4754,18 +5079,19 @@ func_mode_link () arg="$func_quote_for_eval_result" ;; - # -64, -mips[0-9] enable 64-bit mode on the SGI compiler - # -r[0-9][0-9]* specifies the processor on the SGI compiler - # -xarch=*, -xtarget=* enable 64-bit mode on the Sun compiler - # +DA*, +DD* enable 64-bit mode on the HP compiler - # -q* pass through compiler args for the IBM compiler - # -m*, -t[45]*, -txscale* pass through architecture-specific - # compiler args for GCC - # -F/path gives path to uninstalled frameworks, gcc on darwin - # -p, -pg, --coverage, -fprofile-* pass through profiling flag for GCC - # @file GCC response files + # Flags to be passed through unchanged, with rationale: + # -64, -mips[0-9] enable 64-bit mode for the SGI compiler + # -r[0-9][0-9]* specify processor for the SGI compiler + # -xarch=*, -xtarget=* enable 64-bit mode for the Sun compiler + # +DA*, +DD* enable 64-bit mode for the HP compiler + # -q* compiler args for the IBM compiler + # -m*, -t[45]*, -txscale* architecture-specific flags for GCC + # -F/path path to uninstalled frameworks, gcc on darwin + # -p, -pg, --coverage, -fprofile-* profiling flags for GCC + # @file GCC response files + # -tp=* Portland pgcc target processor selection -64|-mips[0-9]|-r[0-9][0-9]*|-xarch=*|-xtarget=*|+DA*|+DD*|-q*|-m*| \ - -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*) + -t[45]*|-txscale*|-p|-pg|--coverage|-fprofile-*|-F*|@*|-tp=*) func_quote_for_eval "$arg" arg="$func_quote_for_eval_result" func_append compile_command " $arg" @@ -4925,7 +5251,7 @@ func_mode_link () if test -n "$shlibpath_var"; then # get the directories listed in $shlibpath_var - eval shlib_search_path=\`\$ECHO \"X\${$shlibpath_var}\" \| \$Xsed -e \'s/:/ /g\'\` + eval shlib_search_path=\`\$ECHO \"\${$shlibpath_var}\" \| \$SED \'s/:/ /g\'\` else shlib_search_path= fi @@ -5048,7 +5374,8 @@ func_mode_link () # Collect preopened libtool deplibs, except any this library # has declared as weak libs for deplib in $dependency_libs; do - deplib_base=`$ECHO "X$deplib" | $Xsed -e "$basename"` + func_basename "$deplib" + deplib_base=$func_basename_result case " $weak_libs " in *" $deplib_base "*) ;; *) deplibs="$deplibs $deplib" ;; @@ -5227,7 +5554,7 @@ func_mode_link () match_pattern*) set dummy $deplibs_check_method; shift match_pattern_regex=`expr "$deplibs_check_method" : "$1 \(.*\)"` - if eval "\$ECHO \"X$deplib\"" 2>/dev/null | $Xsed -e 10q \ + if eval "\$ECHO \"$deplib\"" 2>/dev/null | $SED 10q \ | $EGREP "$match_pattern_regex" > /dev/null; then valid_a_lib=yes fi @@ -5237,15 +5564,15 @@ func_mode_link () ;; esac if test "$valid_a_lib" != yes; then - $ECHO + echo $ECHO "*** Warning: Trying to link with static lib archive $deplib." - $ECHO "*** I have the capability to make that library automatically link in when" - $ECHO "*** you link to this library. But I can only do this if you have a" - $ECHO "*** shared version of the library, which you do not appear to have" - $ECHO "*** because the file extensions .$libext of this argument makes me believe" - $ECHO "*** that it is just a static archive that I should not use here." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because the file extensions .$libext of this argument makes me believe" + echo "*** that it is just a static archive that I should not use here." else - $ECHO + echo $ECHO "*** Warning: Linking the shared library $output against the" $ECHO "*** static library $deplib is not portable!" deplibs="$deplib $deplibs" @@ -5318,7 +5645,7 @@ func_mode_link () # Convert "-framework foo" to "foo.ltframework" if test -n "$inherited_linker_flags"; then - tmp_inherited_linker_flags=`$ECHO "X$inherited_linker_flags" | $Xsed -e 's/-framework \([^ $]*\)/\1.ltframework/g'` + tmp_inherited_linker_flags=`$ECHO "$inherited_linker_flags" | $SED 's/-framework \([^ $]*\)/\1.ltframework/g'` for tmp_inherited_linker_flag in $tmp_inherited_linker_flags; do case " $new_inherited_linker_flags " in *" $tmp_inherited_linker_flag "*) ;; @@ -5326,7 +5653,7 @@ func_mode_link () esac done fi - dependency_libs=`$ECHO "X $dependency_libs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + dependency_libs=`$ECHO " $dependency_libs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` if test "$linkmode,$pass" = "lib,link" || test "$linkmode,$pass" = "prog,scan" || { test "$linkmode" != prog && test "$linkmode" != lib; }; then @@ -5580,7 +5907,7 @@ func_mode_link () fi done if test -z "$dlopenmodule" && test "$shouldnotlink" = yes && test "$pass" = link; then - $ECHO + echo if test "$linkmode" = prog; then $ECHO "*** Warning: Linking the executable $output against the loadable module" else @@ -5683,9 +6010,9 @@ func_mode_link () if test "X$dlopenmodule" != "X$lib"; then $ECHO "*** Warning: lib $linklib is a module, not a shared library" if test -z "$old_library" ; then - $ECHO - $ECHO "*** And there doesn't seem to be a static archive available" - $ECHO "*** The link will probably fail, sorry" + echo + echo "*** And there doesn't seem to be a static archive available" + echo "*** The link will probably fail, sorry" else add="$dir/$old_library" fi @@ -5825,21 +6152,21 @@ func_mode_link () # Just print a warning and add the library to dependency_libs so # that the program can be linked against the static library. - $ECHO + echo $ECHO "*** Warning: This system can not link to static lib archive $lib." - $ECHO "*** I have the capability to make that library automatically link in when" - $ECHO "*** you link to this library. But I can only do this if you have a" - $ECHO "*** shared version of the library, which you do not appear to have." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have." if test "$module" = yes; then - $ECHO "*** But as you try to build a module library, libtool will still create " - $ECHO "*** a static module, that should work as long as the dlopening application" - $ECHO "*** is linked with the -dlopen flag to resolve symbols at runtime." + echo "*** But as you try to build a module library, libtool will still create " + echo "*** a static module, that should work as long as the dlopening application" + echo "*** is linked with the -dlopen flag to resolve symbols at runtime." if test -z "$global_symbol_pipe"; then - $ECHO - $ECHO "*** However, this would only work if libtool was able to extract symbol" - $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could" - $ECHO "*** not find such a program. So, this module is probably useless." - $ECHO "*** \`nm' from GNU binutils and a full rebuild may help." + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then build_libtool_libs=module @@ -5893,6 +6220,7 @@ func_mode_link () if test "$link_all_deplibs" != no; then # Add the search paths of all dependency libraries for deplib in $dependency_libs; do + path= case $deplib in -L*) path="$deplib" ;; *.la) @@ -5958,7 +6286,7 @@ func_mode_link () compile_deplibs="$new_inherited_linker_flags $compile_deplibs" finalize_deplibs="$new_inherited_linker_flags $finalize_deplibs" else - compiler_flags="$compiler_flags "`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + compiler_flags="$compiler_flags "`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` fi fi dependency_libs="$newdependency_libs" @@ -6126,7 +6454,7 @@ func_mode_link () if test "$deplibs_check_method" != pass_all; then func_fatal_error "cannot build libtool library \`$output' from non-libtool objects on this host:$objs" else - $ECHO + echo $ECHO "*** Warning: Linking the shared library $output against the non-libtool" $ECHO "*** objects $objs is not portable!" libobjs="$libobjs $objs" @@ -6194,7 +6522,7 @@ func_mode_link () age="$number_minor" revision="$number_revision" ;; - freebsd-aout|freebsd-elf|sunos) + freebsd-aout|freebsd-elf|qnx|sunos) current="$number_major" revision="$number_minor" age="0" @@ -6428,14 +6756,14 @@ func_mode_link () oldlibs="$oldlibs $output_objdir/$libname.$libext" # Transform .lo files to .o files. - oldobjs="$objs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}'$/d' -e "$lo2o" | $NL2SP` + oldobjs="$objs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; $lo2o" | $NL2SP` fi # Eliminate all temporary directories. #for path in $notinst_path; do - # lib_search_path=`$ECHO "X$lib_search_path " | $Xsed -e "s% $path % %g"` - # deplibs=`$ECHO "X$deplibs " | $Xsed -e "s% -L$path % %g"` - # dependency_libs=`$ECHO "X$dependency_libs " | $Xsed -e "s% -L$path % %g"` + # lib_search_path=`$ECHO "$lib_search_path " | $SED "s% $path % %g"` + # deplibs=`$ECHO "$deplibs " | $SED "s% -L$path % %g"` + # dependency_libs=`$ECHO "$dependency_libs " | $SED "s% -L$path % %g"` #done if test -n "$xrpath"; then @@ -6476,7 +6804,7 @@ func_mode_link () if test "$build_libtool_libs" = yes; then if test -n "$rpath"; then case $host in - *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc*) + *-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-os2* | *-*-beos* | *-cegcc* | *-*-haiku*) # these systems don't actually have a c library (as such)! ;; *-*-rhapsody* | *-*-darwin1.[012]) @@ -6561,13 +6889,13 @@ EOF newdeplibs="$newdeplibs $i" else droppeddeps=yes - $ECHO + echo $ECHO "*** Warning: dynamic linker does not accept needed library $i." - $ECHO "*** I have the capability to make that library automatically link in when" - $ECHO "*** you link to this library. But I can only do this if you have a" - $ECHO "*** shared version of the library, which I believe you do not have" - $ECHO "*** because a test_compile did reveal that the linker did not use it for" - $ECHO "*** its dynamic dependency list that programs get resolved with at runtime." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which I believe you do not have" + echo "*** because a test_compile did reveal that the linker did not use it for" + echo "*** its dynamic dependency list that programs get resolved with at runtime." fi fi ;; @@ -6604,22 +6932,22 @@ EOF newdeplibs="$newdeplibs $i" else droppeddeps=yes - $ECHO + echo $ECHO "*** Warning: dynamic linker does not accept needed library $i." - $ECHO "*** I have the capability to make that library automatically link in when" - $ECHO "*** you link to this library. But I can only do this if you have a" - $ECHO "*** shared version of the library, which you do not appear to have" - $ECHO "*** because a test_compile did reveal that the linker did not use this one" - $ECHO "*** as a dynamic dependency that programs can get resolved with at runtime." + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because a test_compile did reveal that the linker did not use this one" + echo "*** as a dynamic dependency that programs can get resolved with at runtime." fi fi else droppeddeps=yes - $ECHO + echo $ECHO "*** Warning! Library $i is needed by this library but I was not able to" - $ECHO "*** make it link in! You will probably need to install it or some" - $ECHO "*** library that it depends on before this library will be fully" - $ECHO "*** functional. Installing it before continuing would be even better." + echo "*** make it link in! You will probably need to install it or some" + echo "*** library that it depends on before this library will be fully" + echo "*** functional. Installing it before continuing would be even better." fi ;; *) @@ -6665,7 +6993,7 @@ EOF potliblink=`ls -ld $potlib | ${SED} 's/.* -> //'` case $potliblink in [\\/]* | [A-Za-z]:[\\/]*) potlib="$potliblink";; - *) potlib=`$ECHO "X$potlib" | $Xsed -e 's,[^/]*$,,'`"$potliblink";; + *) potlib=`$ECHO "$potlib" | $SED 's,[^/]*$,,'`"$potliblink";; esac done if eval $file_magic_cmd \"\$potlib\" 2>/dev/null | @@ -6680,12 +7008,12 @@ EOF fi if test -n "$a_deplib" ; then droppeddeps=yes - $ECHO + echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." - $ECHO "*** I have the capability to make that library automatically link in when" - $ECHO "*** you link to this library. But I can only do this if you have a" - $ECHO "*** shared version of the library, which you do not appear to have" - $ECHO "*** because I did check the linker path looking for a file starting" + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for file magic test)" else @@ -6723,7 +7051,7 @@ EOF potential_libs=`ls $i/$libname[.-]* 2>/dev/null` for potent_lib in $potential_libs; do potlib="$potent_lib" # see symlink-check above in file_magic test - if eval "\$ECHO \"X$potent_lib\"" 2>/dev/null | $Xsed -e 10q | \ + if eval "\$ECHO \"$potent_lib\"" 2>/dev/null | $SED 10q | \ $EGREP "$match_pattern_regex" > /dev/null; then newdeplibs="$newdeplibs $a_deplib" a_deplib="" @@ -6734,12 +7062,12 @@ EOF fi if test -n "$a_deplib" ; then droppeddeps=yes - $ECHO + echo $ECHO "*** Warning: linker path does not have real file for library $a_deplib." - $ECHO "*** I have the capability to make that library automatically link in when" - $ECHO "*** you link to this library. But I can only do this if you have a" - $ECHO "*** shared version of the library, which you do not appear to have" - $ECHO "*** because I did check the linker path looking for a file starting" + echo "*** I have the capability to make that library automatically link in when" + echo "*** you link to this library. But I can only do this if you have a" + echo "*** shared version of the library, which you do not appear to have" + echo "*** because I did check the linker path looking for a file starting" if test -z "$potlib" ; then $ECHO "*** with $libname but no candidates were found. (...for regex pattern test)" else @@ -6757,25 +7085,25 @@ EOF ;; none | unknown | *) newdeplibs="" - tmp_deplibs=`$ECHO "X $deplibs" | $Xsed \ - -e 's/ -lc$//' -e 's/ -[LR][^ ]*//g'` + tmp_deplibs=`$ECHO " $deplibs" | $SED 's/ -lc$//; s/ -[LR][^ ]*//g'` if test "X$allow_libtool_libs_with_static_runtimes" = "Xyes" ; then for i in $predeps $postdeps ; do # can't use Xsed below, because $i might contain '/' - tmp_deplibs=`$ECHO "X $tmp_deplibs" | $Xsed -e "s,$i,,"` + tmp_deplibs=`$ECHO " $tmp_deplibs" | $SED "s,$i,,"` done fi - if $ECHO "X $tmp_deplibs" | $Xsed -e 's/[ ]//g' | - $GREP . >/dev/null; then - $ECHO + case $tmp_deplibs in + *[!\ \ ]*) + echo if test "X$deplibs_check_method" = "Xnone"; then - $ECHO "*** Warning: inter-library dependencies are not supported in this platform." + echo "*** Warning: inter-library dependencies are not supported in this platform." else - $ECHO "*** Warning: inter-library dependencies are not known to be supported." + echo "*** Warning: inter-library dependencies are not known to be supported." fi - $ECHO "*** All declared inter-library dependencies are being dropped." + echo "*** All declared inter-library dependencies are being dropped." droppeddeps=yes - fi + ;; + esac ;; esac versuffix=$versuffix_save @@ -6787,23 +7115,23 @@ EOF case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library with the System framework - newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's/ -lc / System.ltframework /'` + newdeplibs=`$ECHO " $newdeplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac if test "$droppeddeps" = yes; then if test "$module" = yes; then - $ECHO - $ECHO "*** Warning: libtool could not satisfy all declared inter-library" + echo + echo "*** Warning: libtool could not satisfy all declared inter-library" $ECHO "*** dependencies of module $libname. Therefore, libtool will create" - $ECHO "*** a static module, that should work as long as the dlopening" - $ECHO "*** application is linked with the -dlopen flag." + echo "*** a static module, that should work as long as the dlopening" + echo "*** application is linked with the -dlopen flag." if test -z "$global_symbol_pipe"; then - $ECHO - $ECHO "*** However, this would only work if libtool was able to extract symbol" - $ECHO "*** lists from a program, using \`nm' or equivalent, but libtool could" - $ECHO "*** not find such a program. So, this module is probably useless." - $ECHO "*** \`nm' from GNU binutils and a full rebuild may help." + echo + echo "*** However, this would only work if libtool was able to extract symbol" + echo "*** lists from a program, using \`nm' or equivalent, but libtool could" + echo "*** not find such a program. So, this module is probably useless." + echo "*** \`nm' from GNU binutils and a full rebuild may help." fi if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" @@ -6813,16 +7141,16 @@ EOF build_libtool_libs=no fi else - $ECHO "*** The inter-library dependencies that have been dropped here will be" - $ECHO "*** automatically added whenever a program is linked with this library" - $ECHO "*** or is declared to -dlopen it." + echo "*** The inter-library dependencies that have been dropped here will be" + echo "*** automatically added whenever a program is linked with this library" + echo "*** or is declared to -dlopen it." if test "$allow_undefined" = no; then - $ECHO - $ECHO "*** Since this library must not contain undefined symbols," - $ECHO "*** because either the platform does not support them or" - $ECHO "*** it was explicitly requested with -no-undefined," - $ECHO "*** libtool will only create a static version of it." + echo + echo "*** Since this library must not contain undefined symbols," + echo "*** because either the platform does not support them or" + echo "*** it was explicitly requested with -no-undefined," + echo "*** libtool will only create a static version of it." if test "$build_old_libs" = no; then oldlibs="$output_objdir/$libname.$libext" build_libtool_libs=module @@ -6839,9 +7167,9 @@ EOF # Time to change all our "foo.ltframework" stuff back to "-framework foo" case $host in *-*-darwin*) - newdeplibs=`$ECHO "X $newdeplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` - new_inherited_linker_flags=`$ECHO "X $new_inherited_linker_flags" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` - deplibs=`$ECHO "X $deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + newdeplibs=`$ECHO " $newdeplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + new_inherited_linker_flags=`$ECHO " $new_inherited_linker_flags" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + deplibs=`$ECHO " $deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac @@ -6963,7 +7291,7 @@ EOF done # Use standard objects if they are pic - test -z "$pic_flag" && libobjs=`$ECHO "X$libobjs" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + test -z "$pic_flag" && libobjs=`$ECHO "$libobjs" | $SP2NL | $SED "$lo2o" | $NL2SP` test "X$libobjs" = "X " && libobjs= delfiles= @@ -7029,7 +7357,7 @@ EOF if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" - $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"' + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test "X$skipped_export" != "X:" && test -n "$orig_export_symbols"; then @@ -7130,7 +7458,8 @@ EOF save_libobjs=$libobjs fi save_output=$output - output_la=`$ECHO "X$output" | $Xsed -e "$basename"` + func_basename "$output" + output_la=$func_basename_result # Clear the reloadable object creation command queue and # initialize k to one. @@ -7143,12 +7472,12 @@ EOF if test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "$with_gnu_ld" = yes; then output=${output_objdir}/${output_la}.lnkscript func_verbose "creating GNU ld script: $output" - $ECHO 'INPUT (' > $output + echo 'INPUT (' > $output for obj in $save_libobjs do $ECHO "$obj" >> $output done - $ECHO ')' >> $output + echo ')' >> $output delfiles="$delfiles $output" elif test -n "$save_libobjs" && test "X$skipped_export" != "X:" && test "X$file_list_spec" != X; then output=${output_objdir}/${output_la}.lnk @@ -7190,17 +7519,19 @@ EOF # command to the queue. if test "$k" -eq 1 ; then # The first file doesn't have a previous command to add. - eval concat_cmds=\"$reload_cmds $objlist $last_robj\" + reload_objs=$objlist + eval concat_cmds=\"$reload_cmds\" else # All subsequent reloadable object files will link in # the last one created. - eval concat_cmds=\"\$concat_cmds~$reload_cmds $objlist $last_robj~\$RM $last_robj\" + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\$concat_cmds~$reload_cmds~\$RM $last_robj\" fi last_robj=$output_objdir/$output_la-${k}.$objext func_arith $k + 1 k=$func_arith_result output=$output_objdir/$output_la-${k}.$objext - objlist=$obj + objlist=" $obj" func_len " $last_robj" func_arith $len0 + $func_len_result len=$func_arith_result @@ -7210,7 +7541,8 @@ EOF # reloadable object file. All subsequent reloadable object # files will link in the last one created. test -z "$concat_cmds" || concat_cmds=$concat_cmds~ - eval concat_cmds=\"\${concat_cmds}$reload_cmds $objlist $last_robj\" + reload_objs="$objlist $last_robj" + eval concat_cmds=\"\${concat_cmds}$reload_cmds\" if test -n "$last_robj"; then eval concat_cmds=\"\${concat_cmds}~\$RM $last_robj\" fi @@ -7269,7 +7601,7 @@ EOF if test -n "$export_symbols" && test -n "$include_expsyms"; then tmp_export_symbols="$export_symbols" test -n "$orig_export_symbols" && tmp_export_symbols="$orig_export_symbols" - $opt_dry_run || eval '$ECHO "X$include_expsyms" | $Xsed | $SP2NL >> "$tmp_export_symbols"' + $opt_dry_run || eval '$ECHO "$include_expsyms" | $SP2NL >> "$tmp_export_symbols"' fi if test -n "$orig_export_symbols"; then @@ -7434,7 +7766,7 @@ EOF if test -n "$convenience"; then if test -n "$whole_archive_flag_spec"; then eval tmp_whole_archive_flags=\"$whole_archive_flag_spec\" - reload_conv_objs=$reload_objs\ `$ECHO "X$tmp_whole_archive_flags" | $Xsed -e 's|,| |g'` + reload_conv_objs=$reload_objs\ `$ECHO "$tmp_whole_archive_flags" | $SED 's|,| |g'` else gentop="$output_objdir/${obj}x" generated="$generated $gentop" @@ -7445,7 +7777,7 @@ EOF fi # Create the old-style object. - reload_objs="$objs$old_deplibs "`$ECHO "X$libobjs" | $SP2NL | $Xsed -e '/\.'${libext}$'/d' -e '/\.lib$/d' -e "$lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test + reload_objs="$objs$old_deplibs "`$ECHO "$libobjs" | $SP2NL | $SED "/\.${libext}$/d; /\.lib$/d; $lo2o" | $NL2SP`" $reload_conv_objs" ### testsuite: skip nested quoting test output="$obj" func_execute_cmds "$reload_cmds" 'exit $?' @@ -7505,8 +7837,8 @@ EOF case $host in *-*-rhapsody* | *-*-darwin1.[012]) # On Rhapsody replace the C library is the System framework - compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'` - finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's/ -lc / System.ltframework /'` + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's/ -lc / System.ltframework /'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's/ -lc / System.ltframework /'` ;; esac @@ -7523,8 +7855,8 @@ EOF esac fi # Time to change all our "foo.ltframework" stuff back to "-framework foo" - compile_deplibs=`$ECHO "X $compile_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` - finalize_deplibs=`$ECHO "X $finalize_deplibs" | $Xsed -e 's% \([^ $]*\).ltframework% -framework \1%g'` + compile_deplibs=`$ECHO " $compile_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` + finalize_deplibs=`$ECHO " $finalize_deplibs" | $SED 's% \([^ $]*\).ltframework% -framework \1%g'` ;; esac @@ -7661,8 +7993,8 @@ EOF if test -n "$libobjs" && test "$build_old_libs" = yes; then # Transform all the library objects into standard objects. - compile_command=`$ECHO "X$compile_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` - finalize_command=`$ECHO "X$finalize_command" | $SP2NL | $Xsed -e "$lo2o" | $NL2SP` + compile_command=`$ECHO "$compile_command" | $SP2NL | $SED "$lo2o" | $NL2SP` + finalize_command=`$ECHO "$finalize_command" | $SP2NL | $SED "$lo2o" | $NL2SP` fi func_generate_dlsyms "$outputname" "@PROGRAM@" "no" @@ -7674,15 +8006,15 @@ EOF wrappers_required=yes case $host in + *cegcc* | *mingw32ce*) + # Disable wrappers for cegcc and mingw32ce hosts, we are cross compiling anyway. + wrappers_required=no + ;; *cygwin* | *mingw* ) if test "$build_libtool_libs" != yes; then wrappers_required=no fi ;; - *cegcc) - # Disable wrappers for cegcc, we are cross compiling anyway. - wrappers_required=no - ;; *) if test "$need_relink" = no || test "$build_libtool_libs" != yes; then wrappers_required=no @@ -7691,7 +8023,7 @@ EOF esac if test "$wrappers_required" = no; then # Replace the output file specification. - compile_command=`$ECHO "X$compile_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + compile_command=`$ECHO "$compile_command" | $SED 's%@OUTPUT@%'"$output"'%g'` link_command="$compile_command$compile_rpath" # We have no uninstalled library dependencies, so finalize right now. @@ -7738,7 +8070,7 @@ EOF # We don't need to create a wrapper script. link_command="$compile_var$compile_command$compile_rpath" # Replace the output file specification. - link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output"'%g'` + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output"'%g'` # Delete the old output file. $opt_dry_run || $RM $output # Link the executable and exit @@ -7757,7 +8089,7 @@ EOF if test "$fast_install" != no; then link_command="$finalize_var$compile_command$finalize_rpath" if test "$fast_install" = yes; then - relink_command=`$ECHO "X$compile_var$compile_command$compile_rpath" | $Xsed -e 's%@OUTPUT@%\$progdir/\$file%g'` + relink_command=`$ECHO "$compile_var$compile_command$compile_rpath" | $SED 's%@OUTPUT@%\$progdir/\$file%g'` else # fast_install is set to needless relink_command= @@ -7769,7 +8101,7 @@ EOF fi # Replace the output file specification. - link_command=`$ECHO "X$link_command" | $Xsed -e 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` + link_command=`$ECHO "$link_command" | $SED 's%@OUTPUT@%'"$output_objdir/$outputname"'%g'` # Delete the old output files. $opt_dry_run || $RM $output $output_objdir/$outputname $output_objdir/lt-$outputname @@ -7793,18 +8125,7 @@ EOF fi done relink_command="(cd `pwd`; $relink_command)" - relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"` - fi - - # Quote $ECHO for shipping. - if test "X$ECHO" = "X$SHELL $progpath --fallback-echo"; then - case $progpath in - [\\/]* | [A-Za-z]:[\\/]*) qecho="$SHELL $progpath --fallback-echo";; - *) qecho="$SHELL `pwd`/$progpath --fallback-echo";; - esac - qecho=`$ECHO "X$qecho" | $Xsed -e "$sed_quote_subst"` - else - qecho=`$ECHO "X$ECHO" | $Xsed -e "$sed_quote_subst"` + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` fi # Only actually do things if not in dry run mode. @@ -7925,7 +8246,7 @@ EOF done | sort | sort -uc >/dev/null 2>&1); then : else - $ECHO "copying selected object files to avoid basename conflicts..." + echo "copying selected object files to avoid basename conflicts..." gentop="$output_objdir/${outputname}x" generated="$generated $gentop" func_mkdir_p "$gentop" @@ -8036,7 +8357,7 @@ EOF done # Quote the link command for shipping. relink_command="(cd `pwd`; $SHELL $progpath $preserve_args --mode=relink $libtool_args @inst_prefix_dir@)" - relink_command=`$ECHO "X$relink_command" | $Xsed -e "$sed_quote_subst"` + relink_command=`$ECHO "$relink_command" | $SED "$sed_quote_subst"` if test "$hardcode_automatic" = yes ; then relink_command= fi @@ -8121,9 +8442,27 @@ EOF fi $RM $output # place dlname in correct position for cygwin + # In fact, it would be nice if we could use this code for all target + # systems that can't hard-code library paths into their executables + # and that have no shared library path variable independent of PATH, + # but it turns out we can't easily determine that from inspecting + # libtool variables, so we have to hard-code the OSs to which it + # applies here; at the moment, that means platforms that use the PE + # object format with DLL files. See the long comment at the top of + # tests/bindir.at for full details. tdlname=$dlname case $host,$output,$installed,$module,$dlname in - *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) tdlname=../bin/$dlname ;; + *cygwin*,*lai,yes,no,*.dll | *mingw*,*lai,yes,no,*.dll | *cegcc*,*lai,yes,no,*.dll) + # If a -bindir argument was supplied, place the dll there. + if test "x$bindir" != x ; + then + func_relative_path "$install_libdir" "$bindir" + tdlname=$func_relative_path_result$dlname + else + # Otherwise fall back on heuristic. + tdlname=../bin/$dlname + fi + ;; esac $ECHO > $output "\ # $outputname - a libtool library file diff --git a/m4/libtool.m4 b/m4/libtool.m4 index 39ba996..22924a8 100644 --- a/m4/libtool.m4 +++ b/m4/libtool.m4 @@ -1,7 +1,8 @@ # libtool.m4 - Configure libtool for the host system. -*-Autoconf-*- # # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, -# 2006, 2007, 2008 Free Software Foundation, Inc. +# 2006, 2007, 2008, 2009, 2010 Free Software Foundation, +# Inc. # Written by Gordon Matzigkeit, 1996 # # This file is free software; the Free Software Foundation gives @@ -10,7 +11,8 @@ m4_define([_LT_COPYING], [dnl # Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2003, 2004, 2005, -# 2006, 2007, 2008 Free Software Foundation, Inc. +# 2006, 2007, 2008, 2009, 2010 Free Software Foundation, +# Inc. # Written by Gordon Matzigkeit, 1996 # # This file is part of GNU Libtool. @@ -37,7 +39,7 @@ m4_define([_LT_COPYING], [dnl # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. ]) -# serial 56 LT_INIT +# serial 57 LT_INIT # LT_PREREQ(VERSION) @@ -66,6 +68,7 @@ esac # ------------------ AC_DEFUN([LT_INIT], [AC_PREREQ([2.58])dnl We use AC_INCLUDES_DEFAULT +AC_REQUIRE([AC_CONFIG_AUX_DIR_DEFAULT])dnl AC_BEFORE([$0], [LT_LANG])dnl AC_BEFORE([$0], [LT_OUTPUT])dnl AC_BEFORE([$0], [LTDL_INIT])dnl @@ -82,6 +85,8 @@ AC_REQUIRE([LTVERSION_VERSION])dnl AC_REQUIRE([LTOBSOLETE_VERSION])dnl m4_require([_LT_PROG_LTMAIN])dnl +_LT_SHELL_INIT([SHELL=${CONFIG_SHELL-/bin/sh}]) + dnl Parse OPTIONS _LT_SET_OPTIONS([$0], [$1]) @@ -118,7 +123,7 @@ m4_defun([_LT_CC_BASENAME], *) break;; esac done -cc_basename=`$ECHO "X$cc_temp" | $Xsed -e 's%.*/%%' -e "s%^$host_alias-%%"` +cc_basename=`$ECHO "$cc_temp" | $SED "s%.*/%%; s%^$host_alias-%%"` ]) @@ -138,6 +143,9 @@ m4_defun([_LT_FILEUTILS_DEFAULTS], m4_defun([_LT_SETUP], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl +AC_REQUIRE([_LT_PREPARE_SED_QUOTE_VARS])dnl +AC_REQUIRE([_LT_PROG_ECHO_BACKSLASH])dnl + _LT_DECL([], [host_alias], [0], [The host system])dnl _LT_DECL([], [host], [0])dnl _LT_DECL([], [host_os], [0])dnl @@ -179,7 +187,6 @@ fi _LT_CHECK_OBJDIR m4_require([_LT_TAG_COMPILER])dnl -_LT_PROG_ECHO_BACKSLASH case $host_os in aix3*) @@ -193,23 +200,6 @@ aix3*) ;; esac -# Sed substitution that helps us do robust quoting. It backslashifies -# metacharacters that are still active within double-quoted strings. -sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' - -# Same as above, but do not quote variable references. -double_quote_subst='s/\([["`\\]]\)/\\\1/g' - -# Sed substitution to delay expansion of an escaped shell variable in a -# double_quote_subst'ed string. -delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' - -# Sed substitution to delay expansion of an escaped single quote. -delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' - -# Sed substitution to avoid accidental globbing in evaled expressions -no_glob_subst='s/\*/\\\*/g' - # Global variables: ofile=libtool can_build_shared=yes @@ -250,6 +240,28 @@ _LT_CONFIG_COMMANDS ])# _LT_SETUP +# _LT_PREPARE_SED_QUOTE_VARS +# -------------------------- +# Define a few sed substitution that help us do robust quoting. +m4_defun([_LT_PREPARE_SED_QUOTE_VARS], +[# Backslashify metacharacters that are still active within +# double-quoted strings. +sed_quote_subst='s/\([["`$\\]]\)/\\\1/g' + +# Same as above, but do not quote variable references. +double_quote_subst='s/\([["`\\]]\)/\\\1/g' + +# Sed substitution to delay expansion of an escaped shell variable in a +# double_quote_subst'ed string. +delay_variable_subst='s/\\\\\\\\\\\$/\\\\\\$/g' + +# Sed substitution to delay expansion of an escaped single quote. +delay_single_quote_subst='s/'\''/'\'\\\\\\\'\''/g' + +# Sed substitution to avoid accidental globbing in evaled expressions +no_glob_subst='s/\*/\\\*/g' +]) + # _LT_PROG_LTMAIN # --------------- # Note that this code is called both from `configure', and `config.status' @@ -408,7 +420,7 @@ m4_define([_lt_decl_all_varnames], # declaration there will have the same value as in `configure'. VARNAME # must have a single quote delimited value for this to work. m4_define([_LT_CONFIG_STATUS_DECLARE], -[$1='`$ECHO "X$][$1" | $Xsed -e "$delay_single_quote_subst"`']) +[$1='`$ECHO "$][$1" | $SED "$delay_single_quote_subst"`']) # _LT_CONFIG_STATUS_DECLARATIONS @@ -418,7 +430,7 @@ m4_define([_LT_CONFIG_STATUS_DECLARE], # embedded single quotes properly. In configure, this macro expands # each variable declared with _LT_DECL (and _LT_TAGDECL) into: # -# ='`$ECHO "X$" | $Xsed -e "$delay_single_quote_subst"`' +# ='`$ECHO "$" | $SED "$delay_single_quote_subst"`' m4_defun([_LT_CONFIG_STATUS_DECLARATIONS], [m4_foreach([_lt_var], m4_quote(lt_decl_all_varnames), [m4_n([_LT_CONFIG_STATUS_DECLARE(_lt_var)])])]) @@ -517,12 +529,20 @@ LTCC='$LTCC' LTCFLAGS='$LTCFLAGS' compiler='$compiler_DEFAULT' +# A function that is used when there is no print builtin or printf. +func_fallback_echo () +{ + eval 'cat <<_LTECHO_EOF +\$[]1 +_LTECHO_EOF' +} + # Quote evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_quote_varnames); do - case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED \\"\\\$sed_quote_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -533,9 +553,9 @@ done # Double-quote double-evaled strings. for var in lt_decl_all_varnames([[ \ ]], lt_decl_dquote_varnames); do - case \`eval \\\\\$ECHO "X\\\\\$\$var"\` in + case \`eval \\\\\$ECHO \\\\""\\\\\$\$var"\\\\"\` in *[[\\\\\\\`\\"\\\$]]*) - eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"X\\\$\$var\\" | \\\$Xsed -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" + eval "lt_\$var=\\\\\\"\\\`\\\$ECHO \\"\\\$\$var\\" | \\\$SED -e \\"\\\$double_quote_subst\\" -e \\"\\\$sed_quote_subst\\" -e \\"\\\$delay_variable_subst\\"\\\`\\\\\\"" ;; *) eval "lt_\$var=\\\\\\"\\\$\$var\\\\\\"" @@ -543,16 +563,38 @@ for var in lt_decl_all_varnames([[ \ esac done -# Fix-up fallback echo if it was mangled by the above quoting rules. -case \$lt_ECHO in -*'\\\[$]0 --fallback-echo"')dnl " - lt_ECHO=\`\$ECHO "X\$lt_ECHO" | \$Xsed -e 's/\\\\\\\\\\\\\\\[$]0 --fallback-echo"\[$]/\[$]0 --fallback-echo"/'\` - ;; -esac - _LT_OUTPUT_LIBTOOL_INIT ]) +# _LT_GENERATED_FILE_INIT(FILE, [COMMENT]) +# ------------------------------------ +# Generate a child script FILE with all initialization necessary to +# reuse the environment learned by the parent script, and make the +# file executable. If COMMENT is supplied, it is inserted after the +# `#!' sequence but before initialization text begins. After this +# macro, additional text can be appended to FILE to form the body of +# the child script. The macro ends with non-zero status if the +# file could not be fully written (such as if the disk is full). +m4_ifdef([AS_INIT_GENERATED], +[m4_defun([_LT_GENERATED_FILE_INIT],[AS_INIT_GENERATED($@)])], +[m4_defun([_LT_GENERATED_FILE_INIT], +[m4_require([AS_PREPARE])]dnl +[m4_pushdef([AS_MESSAGE_LOG_FD])]dnl +[lt_write_fail=0 +cat >$1 <<_ASEOF || lt_write_fail=1 +#! $SHELL +# Generated by $as_me. +$2 +SHELL=\${CONFIG_SHELL-$SHELL} +export SHELL +_ASEOF +cat >>$1 <<\_ASEOF || lt_write_fail=1 +AS_SHELL_SANITIZE +_AS_PREPARE +exec AS_MESSAGE_FD>&1 +_ASEOF +test $lt_write_fail = 0 && chmod +x $1[]dnl +m4_popdef([AS_MESSAGE_LOG_FD])])])# _LT_GENERATED_FILE_INIT # LT_OUTPUT # --------- @@ -562,20 +604,11 @@ _LT_OUTPUT_LIBTOOL_INIT AC_DEFUN([LT_OUTPUT], [: ${CONFIG_LT=./config.lt} AC_MSG_NOTICE([creating $CONFIG_LT]) -cat >"$CONFIG_LT" <<_LTEOF -#! $SHELL -# Generated by $as_me. -# Run this file to recreate a libtool stub with the current configuration. - -lt_cl_silent=false -SHELL=\${CONFIG_SHELL-$SHELL} -_LTEOF +_LT_GENERATED_FILE_INIT(["$CONFIG_LT"], +[# Run this file to recreate a libtool stub with the current configuration.]) cat >>"$CONFIG_LT" <<\_LTEOF -AS_SHELL_SANITIZE -_AS_PREPARE - -exec AS_MESSAGE_FD>&1 +lt_cl_silent=false exec AS_MESSAGE_LOG_FD>>config.log { echo @@ -601,7 +634,7 @@ m4_ifset([AC_PACKAGE_NAME], [AC_PACKAGE_NAME ])config.lt[]dnl m4_ifset([AC_PACKAGE_VERSION], [ AC_PACKAGE_VERSION]) configured by $[0], generated by m4_PACKAGE_STRING. -Copyright (C) 2008 Free Software Foundation, Inc. +Copyright (C) 2010 Free Software Foundation, Inc. This config.lt script is free software; the Free Software Foundation gives unlimited permision to copy, distribute and modify it." @@ -646,15 +679,13 @@ chmod +x "$CONFIG_LT" # appending to config.log, which fails on DOS, as config.log is still kept # open by configure. Here we exec the FD to /dev/null, effectively closing # config.log, so it can be properly (re)opened and appended to by config.lt. -if test "$no_create" != yes; then - lt_cl_success=: - test "$silent" = yes && - lt_config_lt_args="$lt_config_lt_args --quiet" - exec AS_MESSAGE_LOG_FD>/dev/null - $SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false - exec AS_MESSAGE_LOG_FD>>config.log - $lt_cl_success || AS_EXIT(1) -fi +lt_cl_success=: +test "$silent" = yes && + lt_config_lt_args="$lt_config_lt_args --quiet" +exec AS_MESSAGE_LOG_FD>/dev/null +$SHELL "$CONFIG_LT" $lt_config_lt_args || lt_cl_success=false +exec AS_MESSAGE_LOG_FD>>config.log +$lt_cl_success || AS_EXIT(1) ])# LT_OUTPUT @@ -831,11 +862,13 @@ AU_DEFUN([AC_LIBTOOL_CXX], [LT_LANG(C++)]) AU_DEFUN([AC_LIBTOOL_F77], [LT_LANG(Fortran 77)]) AU_DEFUN([AC_LIBTOOL_FC], [LT_LANG(Fortran)]) AU_DEFUN([AC_LIBTOOL_GCJ], [LT_LANG(Java)]) +AU_DEFUN([AC_LIBTOOL_RC], [LT_LANG(Windows Resource)]) dnl aclocal-1.4 backwards compatibility: dnl AC_DEFUN([AC_LIBTOOL_CXX], []) dnl AC_DEFUN([AC_LIBTOOL_F77], []) dnl AC_DEFUN([AC_LIBTOOL_FC], []) dnl AC_DEFUN([AC_LIBTOOL_GCJ], []) +dnl AC_DEFUN([AC_LIBTOOL_RC], []) # _LT_TAG_COMPILER @@ -940,6 +973,31 @@ m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ [lt_cv_ld_exported_symbols_list=no]) LDFLAGS="$save_LDFLAGS" ]) + AC_CACHE_CHECK([for -force_load linker flag],[lt_cv_ld_force_load], + [lt_cv_ld_force_load=no + cat > conftest.c << _LT_EOF +int forced_loaded() { return 2;} +_LT_EOF + echo "$LTCC $LTCFLAGS -c -o conftest.o conftest.c" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS -c -o conftest.o conftest.c 2>&AS_MESSAGE_LOG_FD + echo "$AR cru libconftest.a conftest.o" >&AS_MESSAGE_LOG_FD + $AR cru libconftest.a conftest.o 2>&AS_MESSAGE_LOG_FD + echo "$RANLIB libconftest.a" >&AS_MESSAGE_LOG_FD + $RANLIB libconftest.a 2>&AS_MESSAGE_LOG_FD + cat > conftest.c << _LT_EOF +int main() { return 0;} +_LT_EOF + echo "$LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a" >&AS_MESSAGE_LOG_FD + $LTCC $LTCFLAGS $LDFLAGS -o conftest conftest.c -Wl,-force_load,./libconftest.a 2>conftest.err + _lt_result=$? + if test -f conftest && test ! -s conftest.err && test $_lt_result = 0 && $GREP forced_load conftest 2>&1 >/dev/null; then + lt_cv_ld_force_load=yes + else + cat conftest.err >&AS_MESSAGE_LOG_FD + fi + rm -f conftest.err libconftest.a conftest conftest.c + rm -rf conftest.dSYM + ]) case $host_os in rhapsody* | darwin1.[[012]]) _lt_dar_allow_undefined='${wl}-undefined ${wl}suppress' ;; @@ -967,7 +1025,7 @@ m4_defun_once([_LT_REQUIRED_DARWIN_CHECKS],[ else _lt_dar_export_syms='~$NMEDIT -s $output_objdir/${libname}-symbols.expsym ${lib}' fi - if test "$DSYMUTIL" != ":"; then + if test "$DSYMUTIL" != ":" && test "$lt_cv_ld_force_load" = "no"; then _lt_dsymutil='~$DSYMUTIL $lib || :' else _lt_dsymutil= @@ -987,7 +1045,11 @@ m4_defun([_LT_DARWIN_LINKER_FEATURES], _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_automatic, $1)=yes _LT_TAGVAR(hardcode_shlibpath_var, $1)=unsupported - _LT_TAGVAR(whole_archive_flag_spec, $1)='' + if test "$lt_cv_ld_force_load" = "yes"; then + _LT_TAGVAR(whole_archive_flag_spec, $1)='`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience ${wl}-force_load,$conv\"; done; func_echo_all \"$new_convenience\"`' + else + _LT_TAGVAR(whole_archive_flag_spec, $1)='' + fi _LT_TAGVAR(link_all_deplibs, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)="$_lt_dar_allow_undefined" case $cc_basename in @@ -995,7 +1057,7 @@ m4_defun([_LT_DARWIN_LINKER_FEATURES], *) _lt_dar_can_shared=$GCC ;; esac if test "$_lt_dar_can_shared" = "yes"; then - output_verbose_link_cmd=echo + output_verbose_link_cmd=func_echo_all _LT_TAGVAR(archive_cmds, $1)="\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring $_lt_dar_single_mod${_lt_dsymutil}" _LT_TAGVAR(module_cmds, $1)="\$CC \$allow_undefined_flag -o \$lib -bundle \$libobjs \$deplibs \$compiler_flags${_lt_dsymutil}" _LT_TAGVAR(archive_expsym_cmds, $1)="sed 's,^,_,' < \$export_symbols > \$output_objdir/\${libname}-symbols.expsym~\$CC -dynamiclib \$allow_undefined_flag -o \$lib \$libobjs \$deplibs \$compiler_flags -install_name \$rpath/\$soname \$verstring ${_lt_dar_single_mod}${_lt_dar_export_syms}${_lt_dsymutil}" @@ -1041,170 +1103,65 @@ if test -z "$aix_libpath"; then aix_libpath="/usr/lib:/lib"; fi # _LT_SHELL_INIT(ARG) # ------------------- m4_define([_LT_SHELL_INIT], -[ifdef([AC_DIVERSION_NOTICE], - [AC_DIVERT_PUSH(AC_DIVERSION_NOTICE)], - [AC_DIVERT_PUSH(NOTICE)]) -$1 -AC_DIVERT_POP -])# _LT_SHELL_INIT +[m4_divert_text([M4SH-INIT], [$1 +])])# _LT_SHELL_INIT + # _LT_PROG_ECHO_BACKSLASH # ----------------------- -# Add some code to the start of the generated configure script which -# will find an echo command which doesn't interpret backslashes. +# Find how we can fake an echo command that does not interpret backslash. +# In particular, with Autoconf 2.60 or later we add some code to the start +# of the generated configure script which will find a shell with a builtin +# printf (which we can use as an echo command). m4_defun([_LT_PROG_ECHO_BACKSLASH], -[_LT_SHELL_INIT([ -# Check that we are running under the correct shell. -SHELL=${CONFIG_SHELL-/bin/sh} - -case X$lt_ECHO in -X*--fallback-echo) - # Remove one level of quotation (which was required for Make). - ECHO=`echo "$lt_ECHO" | sed 's,\\\\\[$]\\[$]0,'[$]0','` - ;; -esac - -ECHO=${lt_ECHO-echo} -if test "X[$]1" = X--no-reexec; then - # Discard the --no-reexec flag, and continue. - shift -elif test "X[$]1" = X--fallback-echo; then - # Avoid inline document here, it may be left over - : -elif test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' ; then - # Yippee, $ECHO works! - : +[ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO +ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + +AC_MSG_CHECKING([how to print strings]) +# Test print first, because it will be a builtin if present. +if test "X`print -r -- -n 2>/dev/null`" = X-n && \ + test "X`print -r -- $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='print -r --' +elif test "X`printf %s $ECHO 2>/dev/null`" = "X$ECHO"; then + ECHO='printf %s\n' else - # Restart under the correct shell. - exec $SHELL "[$]0" --no-reexec ${1+"[$]@"} -fi - -if test "X[$]1" = X--fallback-echo; then - # used as fallback echo - shift - cat <<_LT_EOF -[$]* -_LT_EOF - exit 0 + # Use this function as a fallback that always works. + func_fallback_echo () + { + eval 'cat <<_LTECHO_EOF +$[]1 +_LTECHO_EOF' + } + ECHO='func_fallback_echo' fi -# The HP-UX ksh and POSIX shell print the target directory to stdout -# if CDPATH is set. -(unset CDPATH) >/dev/null 2>&1 && unset CDPATH - -if test -z "$lt_ECHO"; then - if test "X${echo_test_string+set}" != Xset; then - # find a string as large as possible, as long as the shell can cope with it - for cmd in 'sed 50q "[$]0"' 'sed 20q "[$]0"' 'sed 10q "[$]0"' 'sed 2q "[$]0"' 'echo test'; do - # expected sizes: less than 2Kb, 1Kb, 512 bytes, 16 bytes, ... - if { echo_test_string=`eval $cmd`; } 2>/dev/null && - { test "X$echo_test_string" = "X$echo_test_string"; } 2>/dev/null - then - break - fi - done - fi - - if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && - echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - : - else - # The Solaris, AIX, and Digital Unix default echo programs unquote - # backslashes. This makes it impossible to quote backslashes using - # echo "$something" | sed 's/\\/\\\\/g' - # - # So, first we look for a working echo in the user's PATH. - - lt_save_ifs="$IFS"; IFS=$PATH_SEPARATOR - for dir in $PATH /usr/ucb; do - IFS="$lt_save_ifs" - if (test -f $dir/echo || test -f $dir/echo$ac_exeext) && - test "X`($dir/echo '\t') 2>/dev/null`" = 'X\t' && - echo_testing_string=`($dir/echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - ECHO="$dir/echo" - break - fi - done - IFS="$lt_save_ifs" - - if test "X$ECHO" = Xecho; then - # We didn't find a better echo, so look for alternatives. - if test "X`{ print -r '\t'; } 2>/dev/null`" = 'X\t' && - echo_testing_string=`{ print -r "$echo_test_string"; } 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # This shell has a builtin print -r that does the trick. - ECHO='print -r' - elif { test -f /bin/ksh || test -f /bin/ksh$ac_exeext; } && - test "X$CONFIG_SHELL" != X/bin/ksh; then - # If we have ksh, try running configure again with it. - ORIGINAL_CONFIG_SHELL=${CONFIG_SHELL-/bin/sh} - export ORIGINAL_CONFIG_SHELL - CONFIG_SHELL=/bin/ksh - export CONFIG_SHELL - exec $CONFIG_SHELL "[$]0" --no-reexec ${1+"[$]@"} - else - # Try using printf. - ECHO='printf %s\n' - if test "X`{ $ECHO '\t'; } 2>/dev/null`" = 'X\t' && - echo_testing_string=`{ $ECHO "$echo_test_string"; } 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - # Cool, printf works - : - elif echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($ORIGINAL_CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - CONFIG_SHELL=$ORIGINAL_CONFIG_SHELL - export CONFIG_SHELL - SHELL="$CONFIG_SHELL" - export SHELL - ECHO="$CONFIG_SHELL [$]0 --fallback-echo" - elif echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo '\t') 2>/dev/null` && - test "X$echo_testing_string" = 'X\t' && - echo_testing_string=`($CONFIG_SHELL "[$]0" --fallback-echo "$echo_test_string") 2>/dev/null` && - test "X$echo_testing_string" = "X$echo_test_string"; then - ECHO="$CONFIG_SHELL [$]0 --fallback-echo" - else - # maybe with a smaller string... - prev=: - - for cmd in 'echo test' 'sed 2q "[$]0"' 'sed 10q "[$]0"' 'sed 20q "[$]0"' 'sed 50q "[$]0"'; do - if { test "X$echo_test_string" = "X`eval $cmd`"; } 2>/dev/null - then - break - fi - prev="$cmd" - done +# func_echo_all arg... +# Invoke $ECHO with all args, space-separated. +func_echo_all () +{ + $ECHO "$*" +} - if test "$prev" != 'sed 50q "[$]0"'; then - echo_test_string=`eval $prev` - export echo_test_string - exec ${ORIGINAL_CONFIG_SHELL-${CONFIG_SHELL-/bin/sh}} "[$]0" ${1+"[$]@"} - else - # Oops. We lost completely, so just stick with echo. - ECHO=echo - fi - fi - fi - fi - fi -fi +case "$ECHO" in + printf*) AC_MSG_RESULT([printf]) ;; + print*) AC_MSG_RESULT([print -r]) ;; + *) AC_MSG_RESULT([cat]) ;; +esac -# Copy echo and quote the copy suitably for passing to libtool from -# the Makefile, instead of quoting the original, which is used later. -lt_ECHO=$ECHO -if test "X$lt_ECHO" = "X$CONFIG_SHELL [$]0 --fallback-echo"; then - lt_ECHO="$CONFIG_SHELL \\\$\[$]0 --fallback-echo" -fi +m4_ifdef([_AS_DETECT_SUGGESTED], +[_AS_DETECT_SUGGESTED([ + test -n "${ZSH_VERSION+set}${BASH_VERSION+set}" || ( + ECHO='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\' + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO + ECHO=$ECHO$ECHO$ECHO$ECHO$ECHO$ECHO + PATH=/empty FPATH=/empty; export PATH FPATH + test "X`printf %s $ECHO`" = "X$ECHO" \ + || test "X`print -r -- $ECHO`" = "X$ECHO" )])]) -AC_SUBST(lt_ECHO) -]) _LT_DECL([], [SHELL], [1], [Shell to use when invoking shell scripts]) -_LT_DECL([], [ECHO], [1], - [An echo program that does not interpret backslashes]) +_LT_DECL([], [ECHO], [1], [An echo program that protects backslashes]) ])# _LT_PROG_ECHO_BACKSLASH @@ -1236,7 +1193,7 @@ ia64-*-hpux*) ;; *-*-irix6*) # Find out which ABI we are using. - echo '[#]line __oline__ "configure"' > conftest.$ac_ext + echo '[#]line '$LINENO' "configure"' > conftest.$ac_ext if AC_TRY_EVAL(ac_compile); then if test "$lt_cv_prog_gnu_ld" = yes; then case `/usr/bin/file conftest.$ac_objext` in @@ -1388,10 +1345,19 @@ if test -n "$RANLIB"; then esac old_archive_cmds="$old_archive_cmds~\$RANLIB \$oldlib" fi + +case $host_os in + darwin*) + lock_old_archive_extraction=yes ;; + *) + lock_old_archive_extraction=no ;; +esac _LT_DECL([], [old_postinstall_cmds], [2]) _LT_DECL([], [old_postuninstall_cmds], [2]) _LT_TAGDECL([], [old_archive_cmds], [2], [Commands used to build an old-style archive]) +_LT_DECL([], [lock_old_archive_extraction], [0], + [Whether to use a lock for old archive extraction]) ])# _LT_CMD_OLD_ARCHIVE @@ -1416,15 +1382,15 @@ AC_CACHE_CHECK([$1], [$2], -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>conftest.err) ac_status=$? cat conftest.err >&AS_MESSAGE_LOG_FD - echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s "$ac_outfile"; then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings other than the usual output. - $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' >conftest.exp + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' >conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if test ! -s conftest.er2 || diff conftest.exp conftest.er2 >/dev/null; then $2=yes @@ -1464,7 +1430,7 @@ AC_CACHE_CHECK([$1], [$2], if test -s conftest.err; then # Append any errors to the config.log. cat conftest.err 1>&AS_MESSAGE_LOG_FD - $ECHO "X$_lt_linker_boilerplate" | $Xsed -e '/^$/d' > conftest.exp + $ECHO "$_lt_linker_boilerplate" | $SED '/^$/d' > conftest.exp $SED '/^$/d; /^ *+/d' conftest.err >conftest.er2 if diff conftest.exp conftest.er2 >/dev/null; then $2=yes @@ -1527,6 +1493,11 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl lt_cv_sys_max_cmd_len=8192; ;; + mint*) + # On MiNT this can take a long time and run out of memory. + lt_cv_sys_max_cmd_len=8192; + ;; + amigaos*) # On AmigaOS with pdksh, this test takes hours, literally. # So we just punt and use a minimum line length of 8192. @@ -1591,8 +1562,8 @@ AC_CACHE_VAL([lt_cv_sys_max_cmd_len], [dnl # If test is not a shell built-in, we'll probably end up computing a # maximum length that is only half of the actual maximum length, but # we can't tell. - while { test "X"`$SHELL [$]0 --fallback-echo "X$teststring$teststring" 2>/dev/null` \ - = "XX$teststring$teststring"; } >/dev/null 2>&1 && + while { test "X"`func_fallback_echo "$teststring$teststring" 2>/dev/null` \ + = "X$teststring$teststring"; } >/dev/null 2>&1 && test $i != 17 # 1/2 MB should be enough do i=`expr $i + 1` @@ -1643,7 +1614,7 @@ else lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2 lt_status=$lt_dlunknown cat > conftest.$ac_ext <<_LT_EOF -[#line __oline__ "configure" +[#line $LINENO "configure" #include "confdefs.h" #if HAVE_DLFCN_H @@ -1684,7 +1655,13 @@ else # endif #endif -void fnord() { int i=42;} +/* When -fvisbility=hidden is used, assume the code has been annotated + correspondingly for the symbols needed. */ +#if defined(__GNUC__) && (((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)) +void fnord () __attribute__((visibility("default"))); +#endif + +void fnord () { int i=42; } int main () { void *self = dlopen (0, LT_DLGLOBAL|LT_DLLAZY_OR_NOW); @@ -1693,7 +1670,11 @@ int main () if (self) { if (dlsym (self,"fnord")) status = $lt_dlno_uscore; - else if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else + { + if (dlsym( self,"_fnord")) status = $lt_dlneed_uscore; + else puts (dlerror ()); + } /* dlclose (self); */ } else @@ -1869,16 +1850,16 @@ AC_CACHE_CHECK([if $compiler supports -c -o file.$ac_objext], -e 's:.*FLAGS}\{0,1\} :&$lt_compiler_flag :; t' \ -e 's: [[^ ]]*conftest\.: $lt_compiler_flag&:; t' \ -e 's:$: $lt_compiler_flag:'` - (eval echo "\"\$as_me:__oline__: $lt_compile\"" >&AS_MESSAGE_LOG_FD) + (eval echo "\"\$as_me:$LINENO: $lt_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$lt_compile" 2>out/conftest.err) ac_status=$? cat out/conftest.err >&AS_MESSAGE_LOG_FD - echo "$as_me:__oline__: \$? = $ac_status" >&AS_MESSAGE_LOG_FD + echo "$as_me:$LINENO: \$? = $ac_status" >&AS_MESSAGE_LOG_FD if (exit $ac_status) && test -s out/conftest2.$ac_objext then # The compiler can only warn and ignore the option if not recognized # So say no if there are warnings - $ECHO "X$_lt_compiler_boilerplate" | $Xsed -e '/^$/d' > out/conftest.exp + $ECHO "$_lt_compiler_boilerplate" | $SED '/^$/d' > out/conftest.exp $SED '/^$/d; /^ *+/d' out/conftest.err >out/conftest.er2 if test ! -s out/conftest.er2 || diff out/conftest.exp out/conftest.er2 >/dev/null; then _LT_TAGVAR(lt_cv_prog_compiler_c_o, $1)=yes @@ -2037,6 +2018,7 @@ m4_require([_LT_DECL_EGREP])dnl m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_OBJDUMP])dnl m4_require([_LT_DECL_SED])dnl +m4_require([_LT_CHECK_SHELL_FEATURES])dnl AC_MSG_CHECKING([dynamic linker characteristics]) m4_if([$1], [], [ @@ -2045,16 +2027,23 @@ if test "$GCC" = yes; then darwin*) lt_awk_arg="/^libraries:/,/LR/" ;; *) lt_awk_arg="/^libraries:/" ;; esac - lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if $ECHO "$lt_search_path_spec" | $GREP ';' >/dev/null ; then + case $host_os in + mingw* | cegcc*) lt_sed_strip_eq="s,=\([[A-Za-z]]:\),\1,g" ;; + *) lt_sed_strip_eq="s,=/,/,g" ;; + esac + lt_search_path_spec=`$CC -print-search-dirs | awk $lt_awk_arg | $SED -e "s/^libraries://" -e $lt_sed_strip_eq` + case $lt_search_path_spec in + *\;*) # if the path contains ";" then we assume it to be the separator # otherwise default to the standard path separator (i.e. ":") - it is # assumed that no part of a normal pathname contains ";" but that should # okay in the real world where ";" in dirpaths is itself problematic. - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e 's/;/ /g'` - else - lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED 's/;/ /g'` + ;; + *) + lt_search_path_spec=`$ECHO "$lt_search_path_spec" | $SED "s/$PATH_SEPARATOR/ /g"` + ;; + esac # Ok, now we have the path, separated by spaces, we can step through it # and add multilib dir if necessary. lt_tmp_lt_search_path_spec= @@ -2067,7 +2056,7 @@ if test "$GCC" = yes; then lt_tmp_lt_search_path_spec="$lt_tmp_lt_search_path_spec $lt_sys_path" fi done - lt_search_path_spec=`$ECHO $lt_tmp_lt_search_path_spec | awk ' + lt_search_path_spec=`$ECHO "$lt_tmp_lt_search_path_spec" | awk ' BEGIN {RS=" "; FS="/|\n";} { lt_foo=""; lt_count=0; @@ -2087,7 +2076,13 @@ BEGIN {RS=" "; FS="/|\n";} { if (lt_foo != "") { lt_freq[[lt_foo]]++; } if (lt_freq[[lt_foo]] == 1) { print lt_foo; } }'` - sys_lib_search_path_spec=`$ECHO $lt_search_path_spec` + # AWK program above erroneously prepends '/' to C:/dos/paths + # for these hosts. + case $host_os in + mingw* | cegcc*) lt_search_path_spec=`$ECHO "$lt_search_path_spec" |\ + $SED 's,/\([[A-Za-z]]:\),\1,g'` ;; + esac + sys_lib_search_path_spec=`$ECHO "$lt_search_path_spec" | $lt_NL2SP` else sys_lib_search_path_spec="/lib /usr/lib /usr/local/lib" fi]) @@ -2175,7 +2170,7 @@ amigaos*) m68k) library_names_spec='$libname.ixlibrary $libname.a' # Create ${libname}_ixlibrary.a entries in /sys/libs. - finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`$ECHO "X$lib" | $Xsed -e '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' + finish_eval='for lib in `ls $libdir/*.ixlibrary 2>/dev/null`; do libname=`func_echo_all "$lib" | $SED '\''s%^.*/\([[^/]]*\)\.ixlibrary$%\1%'\''`; test $RM /sys/libs/${libname}_ixlibrary.a; $show "cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a"; cd /sys/libs && $LN_S $lib ${libname}_ixlibrary.a || exit 1; done' ;; esac ;; @@ -2228,23 +2223,12 @@ cygwin* | mingw* | pw32* | cegcc*) cygwin*) # Cygwin DLLs use 'cyg' prefix rather than 'lib' soname_spec='`echo ${libname} | sed -e 's/^lib/cyg/'``echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec="/usr/lib /lib/w32api /lib /usr/local/lib" +m4_if([$1], [],[ + sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/lib/w32api"]) ;; mingw* | cegcc*) # MinGW DLLs use traditional 'lib' prefix soname_spec='${libname}`echo ${release} | $SED -e 's/[[.]]/-/g'`${versuffix}${shared_ext}' - sys_lib_search_path_spec=`$CC -print-search-dirs | $GREP "^libraries:" | $SED -e "s/^libraries://" -e "s,=/,/,g"` - if $ECHO "$sys_lib_search_path_spec" | [$GREP ';[c-zC-Z]:/' >/dev/null]; then - # It is most probably a Windows format PATH printed by - # mingw gcc, but we are running on Cygwin. Gcc prints its search - # path with ; separators, and with drive letters. We can handle the - # drive letters (cygwin fileutils understands them), so leave them, - # especially as we might pass files found there to a mingw objdump, - # which wouldn't understand a cygwinified path. Ahh. - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e 's/;/ /g'` - else - sys_lib_search_path_spec=`$ECHO "$sys_lib_search_path_spec" | $SED -e "s/$PATH_SEPARATOR/ /g"` - fi ;; pw32*) # pw32 DLLs use 'pw' prefix rather than 'lib' @@ -2344,6 +2328,19 @@ gnu*) hardcode_into_libs=yes ;; +haiku*) + version_type=linux + need_lib_prefix=no + need_version=no + dynamic_linker="$host_os runtime_loader" + library_names_spec='${libname}${release}${shared_ext}$versuffix ${libname}${release}${shared_ext}${major} ${libname}${shared_ext}' + soname_spec='${libname}${release}${shared_ext}$major' + shlibpath_var=LIBRARY_PATH + shlibpath_overrides_runpath=yes + sys_lib_dlsearch_path_spec='/boot/home/config/lib /boot/common/lib /boot/system/lib' + hardcode_into_libs=yes + ;; + hpux9* | hpux10* | hpux11*) # Give a soname corresponding to the major version so that dld.sl refuses to # link against other versions. @@ -2386,8 +2383,10 @@ hpux9* | hpux10* | hpux11*) soname_spec='${libname}${release}${shared_ext}$major' ;; esac - # HP-UX runs *really* slowly unless shared libraries are mode 555. + # HP-UX runs *really* slowly unless shared libraries are mode 555, ... postinstall_cmds='chmod 555 $lib' + # or fails outright, so override atomically: + install_override_mode=555 ;; interix[[3-9]]*) @@ -2445,7 +2444,7 @@ linux*oldld* | linux*aout* | linux*coff*) ;; # This must be Linux ELF. -linux* | k*bsd*-gnu) +linux* | k*bsd*-gnu | kopensolaris*-gnu) version_type=linux need_lib_prefix=no need_version=no @@ -2454,16 +2453,21 @@ linux* | k*bsd*-gnu) finish_cmds='PATH="\$PATH:/sbin" ldconfig -n $libdir' shlibpath_var=LD_LIBRARY_PATH shlibpath_overrides_runpath=no + # Some binutils ld are patched to set DT_RUNPATH - save_LDFLAGS=$LDFLAGS - save_libdir=$libdir - eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ - LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" - AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], - [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], - [shlibpath_overrides_runpath=yes])]) - LDFLAGS=$save_LDFLAGS - libdir=$save_libdir + AC_CACHE_VAL([lt_cv_shlibpath_overrides_runpath], + [lt_cv_shlibpath_overrides_runpath=no + save_LDFLAGS=$LDFLAGS + save_libdir=$libdir + eval "libdir=/foo; wl=\"$_LT_TAGVAR(lt_prog_compiler_wl, $1)\"; \ + LDFLAGS=\"\$LDFLAGS $_LT_TAGVAR(hardcode_libdir_flag_spec, $1)\"" + AC_LINK_IFELSE([AC_LANG_PROGRAM([],[])], + [AS_IF([ ($OBJDUMP -p conftest$ac_exeext) 2>/dev/null | grep "RUNPATH.*$libdir" >/dev/null], + [lt_cv_shlibpath_overrides_runpath=yes])]) + LDFLAGS=$save_LDFLAGS + libdir=$save_libdir + ]) + shlibpath_overrides_runpath=$lt_cv_shlibpath_overrides_runpath # This implies no fast_install, which is unacceptable. # Some rework will be needed to allow for fast_install @@ -2472,7 +2476,7 @@ linux* | k*bsd*-gnu) # Append ld.so.conf contents to the search path if test -f /etc/ld.so.conf; then - lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;/^$/d' | tr '\n' ' '` + lt_ld_extra=`awk '/^include / { system(sprintf("cd /etc; cat %s 2>/dev/null", \[$]2)); skip = 1; } { if (!skip) print \[$]0; skip = 0; }' < /etc/ld.so.conf | $SED -e 's/#.*//;/^[ ]*hwcap[ ]/d;s/[:, ]/ /g;s/=[^=]*$//;s/=[^= ]* / /g;s/"//g;/^$/d' | tr '\n' ' '` sys_lib_dlsearch_path_spec="/lib /usr/lib $lt_ld_extra" fi @@ -2705,6 +2709,8 @@ _LT_DECL([], [library_names_spec], [1], The last name is the one that the linker finds with -lNAME]]) _LT_DECL([], [soname_spec], [1], [[The coded name of the library, if different from the real name]]) +_LT_DECL([], [install_override_mode], [1], + [Permission mode override for installation of shared libraries]) _LT_DECL([], [postinstall_cmds], [2], [Command to use after installation of a shared archive]) _LT_DECL([], [postuninstall_cmds], [2], @@ -2817,6 +2823,7 @@ AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_CANONICAL_BUILD])dnl m4_require([_LT_DECL_SED])dnl m4_require([_LT_DECL_EGREP])dnl +m4_require([_LT_PROG_ECHO_BACKSLASH])dnl AC_ARG_WITH([gnu-ld], [AS_HELP_STRING([--with-gnu-ld], @@ -2946,8 +2953,8 @@ case $host_os in fi ;; esac -_LT_DECL([], [reload_flag], [1], [How to create reloadable object files])dnl -_LT_DECL([], [reload_cmds], [2])dnl +_LT_TAGDECL([], [reload_flag], [1], [How to create reloadable object files])dnl +_LT_TAGDECL([], [reload_cmds], [2])dnl ])# _LT_CMD_RELOAD @@ -2999,16 +3006,18 @@ mingw* | pw32*) # Base MSYS/MinGW do not provide the 'file' command needed by # func_win32_libid shell function, so use a weaker test based on 'objdump', # unless we find 'file', for example because we are cross-compiling. - if ( file / ) >/dev/null 2>&1; then + # func_win32_libid assumes BSD nm, so disallow it if using MS dumpbin. + if ( test "$lt_cv_nm_interface" = "BSD nm" && file / ) >/dev/null 2>&1; then lt_cv_deplibs_check_method='file_magic ^x86 archive import|^x86 DLL' lt_cv_file_magic_cmd='func_win32_libid' else - lt_cv_deplibs_check_method='file_magic file format pei*-i386(.*architecture: i386)?' + # Keep this pattern in sync with the one in func_win32_libid. + lt_cv_deplibs_check_method='file_magic file format (pei*-i386(.*architecture: i386)?|pe-arm-wince|pe-x86-64)' lt_cv_file_magic_cmd='$OBJDUMP -f' fi ;; -cegcc) +cegcc*) # use the weaker test based on 'objdump'. See mingw*. lt_cv_deplibs_check_method='file_magic file format pe-arm-.*little(.*architecture: arm)?' lt_cv_file_magic_cmd='$OBJDUMP -f' @@ -3038,6 +3047,10 @@ gnu*) lt_cv_deplibs_check_method=pass_all ;; +haiku*) + lt_cv_deplibs_check_method=pass_all + ;; + hpux10.20* | hpux11*) lt_cv_file_magic_cmd=/usr/bin/file case $host_cpu in @@ -3046,11 +3059,11 @@ hpux10.20* | hpux11*) lt_cv_file_magic_test_file=/usr/lib/hpux32/libc.so ;; hppa*64*) - [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF-[0-9][0-9]) shared object file - PA-RISC [0-9].[0-9]'] + [lt_cv_deplibs_check_method='file_magic (s[0-9][0-9][0-9]|ELF[ -][0-9][0-9])(-bit)?( [LM]SB)? shared object( file)?[, -]* PA-RISC [0-9]\.[0-9]'] lt_cv_file_magic_test_file=/usr/lib/pa20_64/libc.sl ;; *) - lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]].[[0-9]]) shared library' + lt_cv_deplibs_check_method='file_magic (s[[0-9]][[0-9]][[0-9]]|PA-RISC[[0-9]]\.[[0-9]]) shared library' lt_cv_file_magic_test_file=/usr/lib/libc.sl ;; esac @@ -3072,7 +3085,7 @@ irix5* | irix6* | nonstopux*) ;; # This must be Linux ELF. -linux* | k*bsd*-gnu) +linux* | k*bsd*-gnu | kopensolaris*-gnu) lt_cv_deplibs_check_method=pass_all ;; @@ -3214,7 +3227,19 @@ if test "$lt_cv_path_NM" != "no"; then NM="$lt_cv_path_NM" else # Didn't find any BSD compatible name lister, look for dumpbin. - AC_CHECK_TOOLS(DUMPBIN, ["dumpbin -symbols" "link -dump -symbols"], :) + if test -n "$DUMPBIN"; then : + # Let the user override the test. + else + AC_CHECK_TOOLS(DUMPBIN, [dumpbin "link -dump"], :) + case `$DUMPBIN -symbols /dev/null 2>&1 | sed '1q'` in + *COFF*) + DUMPBIN="$DUMPBIN -symbols" + ;; + *) + DUMPBIN=: + ;; + esac + fi AC_SUBST([DUMPBIN]) if test "$DUMPBIN" != ":"; then NM="$DUMPBIN" @@ -3227,13 +3252,13 @@ _LT_DECL([], [NM], [1], [A BSD- or MS-compatible name lister])dnl AC_CACHE_CHECK([the name lister ($NM) interface], [lt_cv_nm_interface], [lt_cv_nm_interface="BSD nm" echo "int some_variable = 0;" > conftest.$ac_ext - (eval echo "\"\$as_me:__oline__: $ac_compile\"" >&AS_MESSAGE_LOG_FD) + (eval echo "\"\$as_me:$LINENO: $ac_compile\"" >&AS_MESSAGE_LOG_FD) (eval "$ac_compile" 2>conftest.err) cat conftest.err >&AS_MESSAGE_LOG_FD - (eval echo "\"\$as_me:__oline__: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) + (eval echo "\"\$as_me:$LINENO: $NM \\\"conftest.$ac_objext\\\"\"" >&AS_MESSAGE_LOG_FD) (eval "$NM \"conftest.$ac_objext\"" 2>conftest.err > conftest.out) cat conftest.err >&AS_MESSAGE_LOG_FD - (eval echo "\"\$as_me:__oline__: output\"" >&AS_MESSAGE_LOG_FD) + (eval echo "\"\$as_me:$LINENO: output\"" >&AS_MESSAGE_LOG_FD) cat conftest.out >&AS_MESSAGE_LOG_FD if $GREP 'External.*some_variable' conftest.out > /dev/null; then lt_cv_nm_interface="MS dumpbin" @@ -3256,7 +3281,7 @@ AC_DEFUN([LT_LIB_M], [AC_REQUIRE([AC_CANONICAL_HOST])dnl LIBM= case $host in -*-*-beos* | *-*-cygwin* | *-*-pw32* | *-*-darwin*) +*-*-beos* | *-*-cegcc* | *-*-cygwin* | *-*-haiku* | *-*-pw32* | *-*-darwin*) # These system don't have libm, or don't need it ;; *-ncr-sysv4.3*) @@ -3284,7 +3309,12 @@ m4_defun([_LT_COMPILER_NO_RTTI], _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)= if test "$GCC" = yes; then - _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' + case $cc_basename in + nvcc*) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -Xcompiler -fno-builtin' ;; + *) + _LT_TAGVAR(lt_prog_compiler_no_builtin_flag, $1)=' -fno-builtin' ;; + esac _LT_COMPILER_OPTION([if $compiler supports -fno-rtti -fno-exceptions], lt_cv_prog_compiler_rtti_exceptions, @@ -3301,6 +3331,7 @@ _LT_TAGDECL([no_builtin_flag], [lt_prog_compiler_no_builtin_flag], [1], m4_defun([_LT_CMD_GLOBAL_SYMBOLS], [AC_REQUIRE([AC_CANONICAL_HOST])dnl AC_REQUIRE([AC_PROG_CC])dnl +AC_REQUIRE([AC_PROG_AWK])dnl AC_REQUIRE([LT_PATH_NM])dnl AC_REQUIRE([LT_PATH_LD])dnl m4_require([_LT_DECL_SED])dnl @@ -3426,7 +3457,7 @@ _LT_EOF if AC_TRY_EVAL(ac_compile); then # Now try to grab the symbols. nlist=conftest.nm - if AC_TRY_EVAL(NM conftest.$ac_objext \| $lt_cv_sys_global_symbol_pipe \> $nlist) && test -s "$nlist"; then + if AC_TRY_EVAL(NM conftest.$ac_objext \| "$lt_cv_sys_global_symbol_pipe" \> $nlist) && test -s "$nlist"; then # Try sorting and uniquifying the output. if sort "$nlist" | uniq > "$nlist"T; then mv -f "$nlist"T "$nlist" @@ -3588,6 +3619,11 @@ m4_if([$1], [CXX], [ # DJGPP does not support shared libraries at all _LT_TAGVAR(lt_prog_compiler_pic, $1)= ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; interix[[3-9]]*) # Interix 3.x gcc -fpic/-fPIC options generate broken code. # Instead, we relocate shared libraries at runtime. @@ -3693,7 +3729,7 @@ m4_if([$1], [CXX], [ ;; esac ;; - linux* | k*bsd*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in KCC*) # KAI C++ Compiler @@ -3726,8 +3762,8 @@ m4_if([$1], [CXX], [ _LT_TAGVAR(lt_prog_compiler_pic, $1)= _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; - xlc* | xlC*) - # IBM XL 8.0 on PPC + xlc* | xlC* | bgxl[[cC]]* | mpixl[[cC]]*) + # IBM XL 8.0, 9.0 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' @@ -3789,7 +3825,7 @@ m4_if([$1], [CXX], [ ;; solaris*) case $cc_basename in - CC*) + CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' @@ -3893,6 +3929,12 @@ m4_if([$1], [CXX], [ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fno-common' ;; + haiku*) + # PIC is the default for Haiku. + # The "-static" flag exists, but is broken. + _LT_TAGVAR(lt_prog_compiler_static, $1)= + ;; + hpux*) # PIC is the default for 64-bit PA HP-UX, but not for 32-bit # PA HP-UX. On IA64 HP-UX, PIC is the default but the pic flag @@ -3935,6 +3977,13 @@ m4_if([$1], [CXX], [ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-fPIC' ;; esac + + case $cc_basename in + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Xlinker ' + _LT_TAGVAR(lt_prog_compiler_pic, $1)='-Xcompiler -fPIC' + ;; + esac else # PORTME Check for flag to pass linker flags through the system compiler. case $host_os in @@ -3977,7 +4026,7 @@ m4_if([$1], [CXX], [ _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; - linux* | k*bsd*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in # old Intel for x86_64 which still supported -KPIC. ecc*) @@ -3998,7 +4047,7 @@ m4_if([$1], [CXX], [ _LT_TAGVAR(lt_prog_compiler_pic, $1)='--shared' _LT_TAGVAR(lt_prog_compiler_static, $1)='--static' ;; - pgcc* | pgf77* | pgf90* | pgf95*) + pgcc* | pgf77* | pgf90* | pgf95* | pgfortran*) # Portland Group compilers (*not* the Pentium gcc compiler, # which looks to be a dead project) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' @@ -4010,25 +4059,25 @@ m4_if([$1], [CXX], [ # All Alpha code is PIC. _LT_TAGVAR(lt_prog_compiler_static, $1)='-non_shared' ;; - xl*) - # IBM XL C 8.0/Fortran 10.1 on PPC + xl* | bgxl* | bgf* | mpixl*) + # IBM XL C 8.0/Fortran 10.1, 11.1 on PPC and BlueGene _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' _LT_TAGVAR(lt_prog_compiler_pic, $1)='-qpic' _LT_TAGVAR(lt_prog_compiler_static, $1)='-qstaticlink' ;; *) case `$CC -V 2>&1 | sed 5q` in - *Sun\ C*) - # Sun C 5.9 + *Sun\ F* | *Sun*Fortran*) + # Sun Fortran 8.3 passes all unrecognized flags to the linker _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='' ;; - *Sun\ F*) - # Sun Fortran 8.3 passes all unrecognized flags to the linker + *Sun\ C*) + # Sun C 5.9 _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' - _LT_TAGVAR(lt_prog_compiler_wl, $1)='' + _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,' ;; esac ;; @@ -4060,7 +4109,7 @@ m4_if([$1], [CXX], [ _LT_TAGVAR(lt_prog_compiler_pic, $1)='-KPIC' _LT_TAGVAR(lt_prog_compiler_static, $1)='-Bstatic' case $cc_basename in - f77* | f90* | f95*) + f77* | f90* | f95* | sunf77* | sunf90* | sunf95*) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Qoption ld ';; *) _LT_TAGVAR(lt_prog_compiler_wl, $1)='-Wl,';; @@ -4170,8 +4219,10 @@ m4_if([$1], [CXX], [ aix[[4-9]]*) # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global defined + # symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi @@ -4249,7 +4300,33 @@ dnl Note also adjust exclude_expsyms for C++ above. esac _LT_TAGVAR(ld_shlibs, $1)=yes + + # On some targets, GNU ld is compatible enough with the native linker + # that we're better off using the native interface for both. + lt_use_gnu_ld_interface=no if test "$with_gnu_ld" = yes; then + case $host_os in + aix*) + # The AIX port of GNU ld has always aspired to compatibility + # with the native linker. However, as the warning in the GNU ld + # block says, versions before 2.19.5* couldn't really create working + # shared libraries, regardless of the interface used. + case `$LD -v 2>&1` in + *\ \(GNU\ Binutils\)\ 2.19.5*) ;; + *\ \(GNU\ Binutils\)\ 2.[[2-9]]*) ;; + *\ \(GNU\ Binutils\)\ [[3-9]]*) ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + ;; + *) + lt_use_gnu_ld_interface=yes + ;; + esac + fi + + if test "$lt_use_gnu_ld_interface" = yes; then # If archive_cmds runs LD, not CC, wlarc should be empty wlarc='${wl}' @@ -4267,6 +4344,7 @@ dnl Note also adjust exclude_expsyms for C++ above. fi supports_anon_versioning=no case `$LD -v 2>&1` in + *GNU\ gold*) supports_anon_versioning=yes ;; *\ [[01]].* | *\ 2.[[0-9]].* | *\ 2.10.*) ;; # catch versions < 2.11 *\ 2.11.93.0.2\ *) supports_anon_versioning=yes ;; # RH7.3 ... *\ 2.11.92.0.12\ *) supports_anon_versioning=yes ;; # Mandrake 8.2 ... @@ -4282,11 +4360,12 @@ dnl Note also adjust exclude_expsyms for C++ above. _LT_TAGVAR(ld_shlibs, $1)=no cat <<_LT_EOF 1>&2 -*** Warning: the GNU linker, at least up to release 2.9.1, is reported +*** Warning: the GNU linker, at least up to release 2.19, is reported *** to be unable to reliably create shared libraries on AIX. *** Therefore, libtool is disabling shared libraries support. If you -*** really care for shared libraries, you may want to modify your PATH -*** so that a non-GNU linker is found, and then restart. +*** really care for shared libraries, you may want to install binutils +*** 2.20 or above, or modify your PATH so that a non-GNU linker is found. +*** You will then need to restart the configuration process. _LT_EOF fi @@ -4322,6 +4401,7 @@ _LT_EOF # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes @@ -4343,6 +4423,11 @@ _LT_EOF fi ;; + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + interix[[3-9]]*) _LT_TAGVAR(hardcode_direct, $1)=no _LT_TAGVAR(hardcode_shlibpath_var, $1)=no @@ -4358,7 +4443,7 @@ _LT_EOF _LT_TAGVAR(archive_expsym_cmds, $1)='sed "s,^,_," $export_symbols >$output_objdir/$soname.expsym~$CC -shared $pic_flag $libobjs $deplibs $compiler_flags ${wl}-h,$soname ${wl}--retain-symbols-file,$output_objdir/$soname.expsym ${wl}--image-base,`expr ${RANDOM-$$} % 4096 / 2 \* 262144 + 1342177280` -o $lib' ;; - gnu* | linux* | tpf* | k*bsd*-gnu) + gnu* | linux* | tpf* | k*bsd*-gnu | kopensolaris*-gnu) tmp_diet=no if test "$host_os" = linux-dietlibc; then case $cc_basename in @@ -4372,11 +4457,12 @@ _LT_EOF tmp_sharedflag='-shared' case $cc_basename,$host_cpu in pgcc*) # Portland Group C compiler - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag' ;; - pgf77* | pgf90* | pgf95*) # Portland Group f77 and f90 compilers - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + pgf77* | pgf90* | pgf95* | pgfortran*) + # Portland Group f77 and f90 compilers + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' tmp_addflag=' $pic_flag -Mnomain' ;; ecc*,ia64* | icc*,ia64*) # Intel C compiler on ia64 tmp_addflag=' -i_dynamic' ;; @@ -4387,13 +4473,17 @@ _LT_EOF lf95*) # Lahey Fortran 8.1 _LT_TAGVAR(whole_archive_flag_spec, $1)= tmp_sharedflag='--shared' ;; - xl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) + xl[[cC]]* | bgxl[[cC]]* | mpixl[[cC]]*) # IBM XL C 8.0 on PPC (deal with xlf below) tmp_sharedflag='-qmkshrobj' tmp_addflag= ;; + nvcc*) # Cuda Compiler Driver 2.2 + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(compiler_needs_object, $1)=yes + ;; esac case `$CC -V 2>&1 | sed 5q` in *Sun\ C*) # Sun C 5.9 - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes tmp_sharedflag='-G' ;; *Sun\ F*) # Sun Fortran 8.3 @@ -4409,17 +4499,17 @@ _LT_EOF fi case $cc_basename in - xlf*) + xlf* | bgf* | bgxlf* | mpixlf*) # IBM XL Fortran 10.1 on PPC cannot create shared libs itself _LT_TAGVAR(whole_archive_flag_spec, $1)='--whole-archive$convenience --no-whole-archive' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)= _LT_TAGVAR(hardcode_libdir_flag_spec_ld, $1)='-rpath $libdir' - _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $compiler_flags -soname $soname -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$LD -shared $libobjs $deplibs $linker_flags -soname $soname -o $lib' if test "x$supports_anon_versioning" = xyes; then _LT_TAGVAR(archive_expsym_cmds, $1)='echo "{ global:" > $output_objdir/$libname.ver~ cat $export_symbols | sed -e "s/\(.*\)/\1;/" >> $output_objdir/$libname.ver~ echo "local: *; };" >> $output_objdir/$libname.ver~ - $LD -shared $libobjs $deplibs $compiler_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' + $LD -shared $libobjs $deplibs $linker_flags -soname $soname -version-script $output_objdir/$libname.ver -o $lib' fi ;; esac @@ -4540,8 +4630,10 @@ _LT_EOF else # If we're using GNU nm, then we don't want the "-C" option. # -C means demangle to AIX nm, but means don't demangle with GNU nm + # Also, AIX nm treats weak defined symbols like other global + # defined symbols, whereas GNU nm marks them as "W". if $NM -V 2>&1 | $GREP 'GNU' > /dev/null; then - _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' + _LT_TAGVAR(export_symbols_cmds, $1)='$NM -Bpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B") || (\$ 2 == "W")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' else _LT_TAGVAR(export_symbols_cmds, $1)='$NM -BCpg $libobjs $convenience | awk '\''{ if (((\$ 2 == "T") || (\$ 2 == "D") || (\$ 2 == "B")) && ([substr](\$ 3,1,1) != ".")) { print \$ 3 } }'\'' | sort -u > $export_symbols' fi @@ -4630,7 +4722,7 @@ _LT_EOF # empty executable. _LT_SYS_MODULE_PATH_AIX _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' @@ -4645,8 +4737,13 @@ _LT_EOF # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' - # Exported symbols can be pulled into shared objects from archives - _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared libraries. _LT_TAGVAR(archive_expsym_cmds, $1)="\$CC $shared_flag"' -o $output_objdir/$soname $libobjs $deplibs ${wl}-bnoentry $compiler_flags ${wl}-bE:$export_symbols${allow_undefined_flag}~$AR $AR_FLAGS $output_objdir/$libname$release.a $output_objdir/$soname' @@ -4685,7 +4782,7 @@ _LT_EOF # Tell ltmain to make .dll files, not .so files. shrext_cmds=".dll" # FIXME: Setting linknames here is a bad hack. - _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `$ECHO "X$deplibs" | $Xsed -e '\''s/ -lc$//'\''` -link -dll~linknames=' + _LT_TAGVAR(archive_cmds, $1)='$CC -o $lib $libobjs $compiler_flags `func_echo_all "$deplibs" | $SED '\''s/ -lc$//'\''` -link -dll~linknames=' # The linker will automatically build a .lib file if we build a DLL. _LT_TAGVAR(old_archive_from_new_cmds, $1)='true' # FIXME: Should let the user specify the lib program. @@ -4752,7 +4849,7 @@ _LT_EOF ;; hpux10*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then + if test "$GCC" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(archive_cmds, $1)='$CC -shared -fPIC ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' else _LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags' @@ -4771,7 +4868,7 @@ _LT_EOF ;; hpux11*) - if test "$GCC" = yes -a "$with_gnu_ld" = no; then + if test "$GCC" = yes && test "$with_gnu_ld" = no; then case $host_cpu in hppa*64*) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}+h ${wl}$soname -o $lib $libobjs $deplibs $compiler_flags' @@ -4792,7 +4889,14 @@ _LT_EOF _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+nodefaultrpath -o $lib $libobjs $deplibs $compiler_flags' ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags' + m4_if($1, [], [ + # Older versions of the 11.00 compiler do not understand -b yet + # (HP92453-01 A.11.01.20 doesn't, HP92453-01 B.11.X.35175-35176.GP does) + _LT_LINKER_OPTION([if $CC understands -b], + _LT_TAGVAR(lt_cv_prog_compiler__b, $1), [-b], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags'], + [_LT_TAGVAR(archive_cmds, $1)='$LD -b +h $soname +b $install_libdir -o $lib $libobjs $deplibs $linker_flags'])], + [_LT_TAGVAR(archive_cmds, $1)='$CC -b ${wl}+h ${wl}$soname ${wl}+b ${wl}$install_libdir -o $lib $libobjs $deplibs $compiler_flags']) ;; esac fi @@ -4820,19 +4924,19 @@ _LT_EOF irix5* | irix6* | nonstopux*) if test "$GCC" = yes; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' # Try to use the -exported_symbol ld option, if it does not # work, assume that -exports_file does not work either and # implicitly export all symbols. save_LDFLAGS="$LDFLAGS" LDFLAGS="$LDFLAGS -shared ${wl}-exported_symbol ${wl}foo ${wl}-update_registry ${wl}/dev/null" AC_LINK_IFELSE(int foo(void) {}, - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations ${wl}-exports_file ${wl}$export_symbols -o $lib' ) LDFLAGS="$save_LDFLAGS" else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -exports_file $export_symbols -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' @@ -4894,17 +4998,17 @@ _LT_EOF _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' _LT_TAGVAR(hardcode_minus_L, $1)=yes _LT_TAGVAR(allow_undefined_flag, $1)=unsupported - _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~$ECHO DATA >> $output_objdir/$libname.def~$ECHO " SINGLE NONSHARED" >> $output_objdir/$libname.def~$ECHO EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' + _LT_TAGVAR(archive_cmds, $1)='$ECHO "LIBRARY $libname INITINSTANCE" > $output_objdir/$libname.def~$ECHO "DESCRIPTION \"$libname\"" >> $output_objdir/$libname.def~echo DATA >> $output_objdir/$libname.def~echo " SINGLE NONSHARED" >> $output_objdir/$libname.def~echo EXPORTS >> $output_objdir/$libname.def~emxexp $libobjs >> $output_objdir/$libname.def~$CC -Zdll -Zcrtdll -o $lib $libobjs $deplibs $compiler_flags $output_objdir/$libname.def' _LT_TAGVAR(old_archive_from_new_cmds, $1)='emximp -o $output_objdir/$libname.a $output_objdir/$libname.def' ;; osf3*) if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' fi _LT_TAGVAR(archive_cmds_need_lc, $1)='no' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' @@ -4914,13 +5018,13 @@ _LT_EOF osf4* | osf5*) # as osf3* with the addition of -msym flag if test "$GCC" = yes; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' else _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $libobjs $deplibs $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done; printf "%s\\n" "-hidden">> $lib.exp~ - $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' + $CC -shared${allow_undefined_flag} ${wl}-input ${wl}$lib.exp $compiler_flags $libobjs $deplibs -soname $soname `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~$RM $lib.exp' # Both c and cxx compiler support -rpath directly _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' @@ -5111,36 +5215,38 @@ x|xyes) # Test whether the compiler implicitly links with -lc since on some # systems, -lgcc has to come before -lc. If gcc already passes -lc # to ld, don't add -lc before -lgcc. - AC_MSG_CHECKING([whether -lc should be explicitly linked in]) - $RM conftest* - echo "$lt_simple_compile_test_code" > conftest.$ac_ext - - if AC_TRY_EVAL(ac_compile) 2>conftest.err; then - soname=conftest - lib=conftest - libobjs=conftest.$ac_objext - deplibs= - wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) - pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) - compiler_flags=-v - linker_flags=-v - verstring= - output_objdir=. - libname=conftest - lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) - _LT_TAGVAR(allow_undefined_flag, $1)= - if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) - then - _LT_TAGVAR(archive_cmds_need_lc, $1)=no - else - _LT_TAGVAR(archive_cmds_need_lc, $1)=yes - fi - _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag - else - cat conftest.err 1>&5 - fi - $RM conftest* - AC_MSG_RESULT([$_LT_TAGVAR(archive_cmds_need_lc, $1)]) + AC_CACHE_CHECK([whether -lc should be explicitly linked in], + [lt_cv_]_LT_TAGVAR(archive_cmds_need_lc, $1), + [$RM conftest* + echo "$lt_simple_compile_test_code" > conftest.$ac_ext + + if AC_TRY_EVAL(ac_compile) 2>conftest.err; then + soname=conftest + lib=conftest + libobjs=conftest.$ac_objext + deplibs= + wl=$_LT_TAGVAR(lt_prog_compiler_wl, $1) + pic_flag=$_LT_TAGVAR(lt_prog_compiler_pic, $1) + compiler_flags=-v + linker_flags=-v + verstring= + output_objdir=. + libname=conftest + lt_save_allow_undefined_flag=$_LT_TAGVAR(allow_undefined_flag, $1) + _LT_TAGVAR(allow_undefined_flag, $1)= + if AC_TRY_EVAL(_LT_TAGVAR(archive_cmds, $1) 2\>\&1 \| $GREP \" -lc \" \>/dev/null 2\>\&1) + then + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=no + else + lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1)=yes + fi + _LT_TAGVAR(allow_undefined_flag, $1)=$lt_save_allow_undefined_flag + else + cat conftest.err 1>&5 + fi + $RM conftest* + ]) + _LT_TAGVAR(archive_cmds_need_lc, $1)=$lt_cv_[]_LT_TAGVAR(archive_cmds_need_lc, $1) ;; esac fi @@ -5310,37 +5416,21 @@ CC="$lt_save_CC" ])# _LT_LANG_C_CONFIG -# _LT_PROG_CXX -# ------------ -# Since AC_PROG_CXX is broken, in that it returns g++ if there is no c++ -# compiler, we have our own version here. -m4_defun([_LT_PROG_CXX], -[ -pushdef([AC_MSG_ERROR], [_lt_caught_CXX_error=yes]) -AC_PROG_CXX -if test -n "$CXX" && ( test "X$CXX" != "Xno" && - ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || - (test "X$CXX" != "Xg++"))) ; then - AC_PROG_CXXCPP -else - _lt_caught_CXX_error=yes -fi -popdef([AC_MSG_ERROR]) -])# _LT_PROG_CXX - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([_LT_PROG_CXX], []) - - # _LT_LANG_CXX_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a C++ compiler are suitably # defined. These variables are subsequently used by _LT_CONFIG to write # the compiler configuration to `libtool'. m4_defun([_LT_LANG_CXX_CONFIG], -[AC_REQUIRE([_LT_PROG_CXX])dnl -m4_require([_LT_FILEUTILS_DEFAULTS])dnl +[m4_require([_LT_FILEUTILS_DEFAULTS])dnl m4_require([_LT_DECL_EGREP])dnl +if test -n "$CXX" && ( test "X$CXX" != "Xno" && + ( (test "X$CXX" = "Xg++" && `g++ -v >/dev/null 2>&1` ) || + (test "X$CXX" != "Xg++"))) ; then + AC_PROG_CXXCPP +else + _lt_caught_CXX_error=yes +fi AC_LANG_PUSH(C++) _LT_TAGVAR(archive_cmds_need_lc, $1)=no @@ -5362,6 +5452,8 @@ _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no @@ -5464,7 +5556,7 @@ if test "$_lt_caught_CXX_error" != yes; then # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else GXX=no @@ -5576,7 +5668,7 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_SYS_MODULE_PATH_AIX _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-blibpath:$libdir:'"$aix_libpath" - _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then $ECHO "X${wl}${allow_undefined_flag}" | $Xsed; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" + _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -o $output_objdir/$soname $libobjs $deplibs '"\${wl}$no_entry_flag"' $compiler_flags `if test "x${allow_undefined_flag}" != "x"; then func_echo_all "${wl}${allow_undefined_flag}"; else :; fi` '"\${wl}$exp_sym_flag:\$export_symbols $shared_flag" else if test "$host_cpu" = ia64; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $libdir:/usr/lib:/lib' @@ -5591,8 +5683,13 @@ if test "$_lt_caught_CXX_error" != yes; then # -berok will link without error, but may produce a broken library. _LT_TAGVAR(no_undefined_flag, $1)=' ${wl}-bernotok' _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-berok' - # Exported symbols can be pulled into shared objects from archives - _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + if test "$with_gnu_ld" = yes; then + # We only use this code for GNU lds that support --whole-archive. + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive$convenience ${wl}--no-whole-archive' + else + # Exported symbols can be pulled into shared objects from archives + _LT_TAGVAR(whole_archive_flag_spec, $1)='$convenience' + fi _LT_TAGVAR(archive_cmds_need_lc, $1)=yes # This is similar to how AIX traditionally builds its shared # libraries. @@ -5625,6 +5722,7 @@ if test "$_lt_caught_CXX_error" != yes; then # _LT_TAGVAR(hardcode_libdir_flag_spec, $1) is actually meaningless, # as there is no search path for DLLs. _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-L$libdir' + _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-all-symbols' _LT_TAGVAR(allow_undefined_flag, $1)=unsupported _LT_TAGVAR(always_export_symbols, $1)=no _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=yes @@ -5685,6 +5783,11 @@ if test "$_lt_caught_CXX_error" != yes; then gnu*) ;; + haiku*) + _LT_TAGVAR(archive_cmds, $1)='$CC -shared $libobjs $deplibs $compiler_flags ${wl}-soname $wl$soname -o $lib' + _LT_TAGVAR(link_all_deplibs, $1)=yes + ;; + hpux9*) _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}+b ${wl}$libdir' _LT_TAGVAR(hardcode_libdir_separator, $1)=: @@ -5709,7 +5812,7 @@ if test "$_lt_caught_CXX_error" != yes; then # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $EGREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then @@ -5774,7 +5877,7 @@ if test "$_lt_caught_CXX_error" != yes; then # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + output_verbose_link_cmd='templist=`($CC -b $CFLAGS -v conftest.$objext 2>&1) | $GREP "\-L"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes; then @@ -5817,7 +5920,7 @@ if test "$_lt_caught_CXX_error" != yes; then case $cc_basename in CC*) # SGI C++ - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -all -multigot $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' # Archives containing C++ object files must be created using # "CC -ar", where "CC" is the IRIX C++ compiler. This is @@ -5828,9 +5931,9 @@ if test "$_lt_caught_CXX_error" != yes; then *) if test "$GXX" = yes; then if test "$with_gnu_ld" = no; then - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' else - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` -o $lib' fi fi _LT_TAGVAR(link_all_deplibs, $1)=yes @@ -5841,7 +5944,7 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(inherit_rpath, $1)=yes ;; - linux* | k*bsd*-gnu) + linux* | k*bsd*-gnu | kopensolaris*-gnu) case $cc_basename in KCC*) # Kuck and Associates, Inc. (KAI) C++ Compiler @@ -5859,7 +5962,7 @@ if test "$_lt_caught_CXX_error" != yes; then # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + output_verbose_link_cmd='templist=`$CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 | $GREP "ld"`; rm -f libconftest$shared_ext; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath,$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' @@ -5896,26 +5999,26 @@ if test "$_lt_caught_CXX_error" != yes; then pgCC* | pgcpp*) # Portland Group C++ compiler case `$CC -V` in - *pgCC\ [[1-5]]* | *pgcpp\ [[1-5]]*) + *pgCC\ [[1-5]].* | *pgcpp\ [[1-5]].*) _LT_TAGVAR(prelink_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $objs $libobjs $compile_deplibs~ - compile_command="$compile_command `find $tpldir -name \*.o | $NL2SP`"' + compile_command="$compile_command `find $tpldir -name \*.o | sort | $NL2SP`"' _LT_TAGVAR(old_archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $oldobjs$old_deplibs~ - $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | $NL2SP`~ + $AR $AR_FLAGS $oldlib$oldobjs$old_deplibs `find $tpldir -name \*.o | sort | $NL2SP`~ $RANLIB $oldlib' _LT_TAGVAR(archive_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='tpldir=Template.dir~ rm -rf $tpldir~ $CC --prelink_objects --instantiation_dir $tpldir $predep_objects $libobjs $deplibs $convenience $postdep_objects~ - $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' + $CC -shared $pic_flag $predep_objects $libobjs $deplibs `find $tpldir -name \*.o | sort | $NL2SP` $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; - *) # Version 6 will use weak symbols + *) # Version 6 and above use weak symbols _LT_TAGVAR(archive_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -shared $pic_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname ${wl}-retain-symbols-file ${wl}$export_symbols -o $lib' ;; @@ -5923,7 +6026,7 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}--rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`for conv in $convenience\"\"; do test -n \"$conv\" && new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' ;; cxx*) # Compaq C++ @@ -5942,9 +6045,9 @@ if test "$_lt_caught_CXX_error" != yes; then # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld .*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "X$list" | $Xsed' ;; - xl*) + xl* | mpixl* | bgxl*) # IBM XL 8.0 on PPC, with GNU ld _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}--export-dynamic' @@ -5964,13 +6067,13 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(archive_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G${allow_undefined_flag} -h$soname -o $lib $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-retain-symbols-file ${wl}$export_symbols' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-R$libdir' - _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; $ECHO \"$new_convenience\"` ${wl}--no-whole-archive' + _LT_TAGVAR(whole_archive_flag_spec, $1)='${wl}--whole-archive`new_convenience=; for conv in $convenience\"\"; do test -z \"$conv\" || new_convenience=\"$new_convenience,$conv\"; done; func_echo_all \"$new_convenience\"` ${wl}--no-whole-archive' _LT_TAGVAR(compiler_needs_object, $1)=yes # Not sure whether something based on # $CC $CFLAGS -v conftest.$objext -o libconftest$shared_ext 2>&1 # would be better. - output_verbose_link_cmd='echo' + output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is @@ -6039,7 +6142,7 @@ if test "$_lt_caught_CXX_error" != yes; then _LT_TAGVAR(export_dynamic_flag_spec, $1)='${wl}-E' _LT_TAGVAR(whole_archive_flag_spec, $1)="$wlarc"'--whole-archive$convenience '"$wlarc"'--no-whole-archive' fi - output_verbose_link_cmd=echo + output_verbose_link_cmd=func_echo_all else _LT_TAGVAR(ld_shlibs, $1)=no fi @@ -6074,15 +6177,15 @@ if test "$_lt_caught_CXX_error" != yes; then case $host in osf3*) _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && $ECHO "X${wl}-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname $soname `test -n "$verstring" && func_echo_all "${wl}-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-rpath ${wl}$libdir' ;; *) _LT_TAGVAR(allow_undefined_flag, $1)=' -expect_unresolved \*' - _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname `test -n "$verstring" && func_echo_all "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib' _LT_TAGVAR(archive_expsym_cmds, $1)='for i in `cat $export_symbols`; do printf "%s %s\\n" -exported_symbol "\$i" >> $lib.exp; done~ echo "-hidden">> $lib.exp~ - $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "X-set_version $verstring" | $Xsed` -update_registry ${output_objdir}/so_locations -o $lib~ + $CC -shared$allow_undefined_flag $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags -msym -soname $soname ${wl}-input ${wl}$lib.exp `test -n "$verstring" && $ECHO "-set_version $verstring"` -update_registry ${output_objdir}/so_locations -o $lib~ $RM $lib.exp' _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='-rpath $libdir' ;; @@ -6098,17 +6201,17 @@ if test "$_lt_caught_CXX_error" != yes; then # explicitly linking system object files so we need to strip them # from the output so that they don't get included in the library # dependencies. - output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`$ECHO "X$templist" | $Xsed -e "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; $ECHO "X$list" | $Xsed' + output_verbose_link_cmd='templist=`$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "ld" | $GREP -v "ld:"`; templist=`func_echo_all "$templist" | $SED "s/\(^.*ld.*\)\( .*ld.*$\)/\1/"`; list=""; for z in $templist; do case $z in conftest.$objext) list="$list $z";; *.$objext);; *) list="$list $z";;esac; done; func_echo_all "$list"' ;; *) if test "$GXX" = yes && test "$with_gnu_ld" = no; then _LT_TAGVAR(allow_undefined_flag, $1)=' ${wl}-expect_unresolved ${wl}\*' case $host in osf3*) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "X${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; *) - _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && $ECHO "${wl}-set_version ${wl}$verstring" | $Xsed` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' + _LT_TAGVAR(archive_cmds, $1)='$CC -shared -nostdlib ${allow_undefined_flag} $predep_objects $libobjs $deplibs $postdep_objects $compiler_flags ${wl}-msym ${wl}-soname ${wl}$soname `test -n "$verstring" && func_echo_all "${wl}-set_version ${wl}$verstring"` ${wl}-update_registry ${wl}${output_objdir}/so_locations -o $lib' ;; esac @@ -6118,7 +6221,7 @@ if test "$_lt_caught_CXX_error" != yes; then # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # FIXME: insert proper C++ library support @@ -6154,7 +6257,7 @@ if test "$_lt_caught_CXX_error" != yes; then solaris*) case $cc_basename in - CC*) + CC* | sunCC*) # Sun C++ 4.2, 5.x and Centerline C++ _LT_TAGVAR(archive_cmds_need_lc,$1)=yes _LT_TAGVAR(no_undefined_flag, $1)=' -zdefs' @@ -6175,7 +6278,7 @@ if test "$_lt_caught_CXX_error" != yes; then esac _LT_TAGVAR(link_all_deplibs, $1)=yes - output_verbose_link_cmd='echo' + output_verbose_link_cmd='func_echo_all' # Archives containing C++ object files must be created using # "CC -xar", where "CC" is the Sun C++ compiler. This is @@ -6202,7 +6305,7 @@ if test "$_lt_caught_CXX_error" != yes; then # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' + output_verbose_link_cmd='$CC -shared $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' else # g++ 2.7 appears to require `-G' NOT `-shared' on this # platform. @@ -6213,7 +6316,7 @@ if test "$_lt_caught_CXX_error" != yes; then # Commands to make compiler produce verbose output that lists # what "hidden" libraries, object files and flags are used when # linking a shared library. - output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP "\-L"' + output_verbose_link_cmd='$CC -G $CFLAGS -v conftest.$objext 2>&1 | $GREP -v "^Configured with:" | $GREP "\-L"' fi _LT_TAGVAR(hardcode_libdir_flag_spec, $1)='${wl}-R $wl$libdir' @@ -6267,6 +6370,10 @@ if test "$_lt_caught_CXX_error" != yes; then CC*) _LT_TAGVAR(archive_cmds, $1)='$CC -G ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' _LT_TAGVAR(archive_expsym_cmds, $1)='$CC -G ${wl}-Bexport:$export_symbols ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' + _LT_TAGVAR(old_archive_cmds, $1)='$CC -Tprelink_objects $oldobjs~ + '"$_LT_TAGVAR(old_archive_cmds, $1)" + _LT_TAGVAR(reload_cmds, $1)='$CC -Tprelink_objects $reload_objs~ + '"$_LT_TAGVAR(reload_cmds, $1)" ;; *) _LT_TAGVAR(archive_cmds, $1)='$CC -shared ${wl}-h,$soname -o $lib $libobjs $deplibs $compiler_flags' @@ -6513,7 +6620,7 @@ linux*) solaris*) case $cc_basename in - CC*) + CC* | sunCC*) # The more standards-conforming stlport4 library is # incompatible with the Cstd library. Avoid specifying # it if it's in CXXFLAGS. Ignore libCrun as @@ -6557,32 +6664,16 @@ _LT_TAGDECL([], [compiler_lib_search_path], [1], ])# _LT_SYS_HIDDEN_LIBDEPS -# _LT_PROG_F77 -# ------------ -# Since AC_PROG_F77 is broken, in that it returns the empty string -# if there is no fortran compiler, we have our own version here. -m4_defun([_LT_PROG_F77], -[ -pushdef([AC_MSG_ERROR], [_lt_disable_F77=yes]) -AC_PROG_F77 -if test -z "$F77" || test "X$F77" = "Xno"; then - _lt_disable_F77=yes -fi -popdef([AC_MSG_ERROR]) -])# _LT_PROG_F77 - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([_LT_PROG_F77], []) - - # _LT_LANG_F77_CONFIG([TAG]) # -------------------------- # Ensure that the configuration variables for a Fortran 77 compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_F77_CONFIG], -[AC_REQUIRE([_LT_PROG_F77])dnl -AC_LANG_PUSH(Fortran 77) +[AC_LANG_PUSH(Fortran 77) +if test -z "$F77" || test "X$F77" = "Xno"; then + _lt_disable_F77=yes +fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= @@ -6601,6 +6692,8 @@ _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no @@ -6700,32 +6793,17 @@ AC_LANG_POP ])# _LT_LANG_F77_CONFIG -# _LT_PROG_FC -# ----------- -# Since AC_PROG_FC is broken, in that it returns the empty string -# if there is no fortran compiler, we have our own version here. -m4_defun([_LT_PROG_FC], -[ -pushdef([AC_MSG_ERROR], [_lt_disable_FC=yes]) -AC_PROG_FC -if test -z "$FC" || test "X$FC" = "Xno"; then - _lt_disable_FC=yes -fi -popdef([AC_MSG_ERROR]) -])# _LT_PROG_FC - -dnl aclocal-1.4 backwards compatibility: -dnl AC_DEFUN([_LT_PROG_FC], []) - - # _LT_LANG_FC_CONFIG([TAG]) # ------------------------- # Ensure that the configuration variables for a Fortran compiler are # suitably defined. These variables are subsequently used by _LT_CONFIG # to write the compiler configuration to `libtool'. m4_defun([_LT_LANG_FC_CONFIG], -[AC_REQUIRE([_LT_PROG_FC])dnl -AC_LANG_PUSH(Fortran) +[AC_LANG_PUSH(Fortran) + +if test -z "$FC" || test "X$FC" = "Xno"; then + _lt_disable_FC=yes +fi _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(allow_undefined_flag, $1)= @@ -6744,6 +6822,8 @@ _LT_TAGVAR(module_cmds, $1)= _LT_TAGVAR(module_expsym_cmds, $1)= _LT_TAGVAR(link_all_deplibs, $1)=unknown _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds _LT_TAGVAR(no_undefined_flag, $1)= _LT_TAGVAR(whole_archive_flag_spec, $1)= _LT_TAGVAR(enable_shared_with_static_runtimes, $1)=no @@ -6889,6 +6969,8 @@ _LT_CC_BASENAME([$compiler]) _LT_TAGVAR(archive_cmds_need_lc, $1)=no _LT_TAGVAR(old_archive_cmds, $1)=$old_archive_cmds +_LT_TAGVAR(reload_flag, $1)=$reload_flag +_LT_TAGVAR(reload_cmds, $1)=$reload_cmds ## CAVEAT EMPTOR: ## There is no encapsulation within the following macros, do not change @@ -7256,7 +7338,7 @@ _LT_EOF func_dirname () { # Extract subdirectory from the argument. - func_dirname_result=`$ECHO "X${1}" | $Xsed -e "$dirname"` + func_dirname_result=`$ECHO "${1}" | $SED "$dirname"` if test "X$func_dirname_result" = "X${1}"; then func_dirname_result="${3}" else @@ -7267,7 +7349,7 @@ func_dirname () # func_basename file func_basename () { - func_basename_result=`$ECHO "X${1}" | $Xsed -e "$basename"` + func_basename_result=`$ECHO "${1}" | $SED "$basename"` } dnl func_dirname_and_basename @@ -7283,10 +7365,8 @@ dnl so there is no need for it here. func_stripname () { case ${2} in - .*) func_stripname_result=`$ECHO "X${3}" \ - | $Xsed -e "s%^${1}%%" -e "s%\\\\${2}\$%%"`;; - *) func_stripname_result=`$ECHO "X${3}" \ - | $Xsed -e "s%^${1}%%" -e "s%${2}\$%%"`;; + .*) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%\\\\${2}\$%%"`;; + *) func_stripname_result=`$ECHO "${3}" | $SED "s%^${1}%%; s%${2}\$%%"`;; esac } @@ -7297,20 +7377,20 @@ my_sed_long_arg='1s/^-[[^=]]*=//' # func_opt_split func_opt_split () { - func_opt_split_opt=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_opt"` - func_opt_split_arg=`$ECHO "X${1}" | $Xsed -e "$my_sed_long_arg"` + func_opt_split_opt=`$ECHO "${1}" | $SED "$my_sed_long_opt"` + func_opt_split_arg=`$ECHO "${1}" | $SED "$my_sed_long_arg"` } # func_lo2o object func_lo2o () { - func_lo2o_result=`$ECHO "X${1}" | $Xsed -e "$lo2o"` + func_lo2o_result=`$ECHO "${1}" | $SED "$lo2o"` } # func_xform libobj-or-source func_xform () { - func_xform_result=`$ECHO "X${1}" | $Xsed -e 's/\.[[^.]]*$/.lo/'` + func_xform_result=`$ECHO "${1}" | $SED 's/\.[[^.]]*$/.lo/'` } # func_arith arithmetic-term... diff --git a/m4/ltoptions.m4 b/m4/ltoptions.m4 index 34151a3..17cfd51 100644 --- a/m4/ltoptions.m4 +++ b/m4/ltoptions.m4 @@ -1,13 +1,14 @@ # Helper functions for option handling. -*- Autoconf -*- # -# Copyright (C) 2004, 2005, 2007, 2008 Free Software Foundation, Inc. +# Copyright (C) 2004, 2005, 2007, 2008, 2009 Free Software Foundation, +# Inc. # Written by Gary V. Vaughan, 2004 # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. -# serial 6 ltoptions.m4 +# serial 7 ltoptions.m4 # This is to help aclocal find these macros, as it can't see m4_define. AC_DEFUN([LTOPTIONS_VERSION], [m4_if([1])]) @@ -125,7 +126,7 @@ LT_OPTION_DEFINE([LT_INIT], [win32-dll], [enable_win32_dll=yes case $host in -*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-cegcc*) +*-*-cygwin* | *-*-mingw* | *-*-pw32* | *-*-cegcc*) AC_CHECK_TOOL(AS, as, false) AC_CHECK_TOOL(DLLTOOL, dlltool, false) AC_CHECK_TOOL(OBJDUMP, objdump, false) @@ -133,13 +134,13 @@ case $host in esac test -z "$AS" && AS=as -_LT_DECL([], [AS], [0], [Assembler program])dnl +_LT_DECL([], [AS], [1], [Assembler program])dnl test -z "$DLLTOOL" && DLLTOOL=dlltool -_LT_DECL([], [DLLTOOL], [0], [DLL creation program])dnl +_LT_DECL([], [DLLTOOL], [1], [DLL creation program])dnl test -z "$OBJDUMP" && OBJDUMP=objdump -_LT_DECL([], [OBJDUMP], [0], [Object dumper program])dnl +_LT_DECL([], [OBJDUMP], [1], [Object dumper program])dnl ])# win32-dll AU_DEFUN([AC_LIBTOOL_WIN32_DLL], diff --git a/m4/ltversion.m4 b/m4/ltversion.m4 index f3c5309..93fc771 100644 --- a/m4/ltversion.m4 +++ b/m4/ltversion.m4 @@ -9,15 +9,15 @@ # Generated from ltversion.in. -# serial 3017 ltversion.m4 +# serial 3175 ltversion.m4 # This file is part of GNU Libtool -m4_define([LT_PACKAGE_VERSION], [2.2.6b]) -m4_define([LT_PACKAGE_REVISION], [1.3017]) +m4_define([LT_PACKAGE_VERSION], [2.2.10]) +m4_define([LT_PACKAGE_REVISION], [1.3175]) AC_DEFUN([LTVERSION_VERSION], -[macro_version='2.2.6b' -macro_revision='1.3017' +[macro_version='2.2.10' +macro_revision='1.3175' _LT_DECL(, macro_version, 0, [Which release of libtool.m4 was used?]) _LT_DECL(, macro_revision, 0) ]) diff --git a/m4/lt~obsolete.m4 b/m4/lt~obsolete.m4 index 637bb20..c573da9 100644 --- a/m4/lt~obsolete.m4 +++ b/m4/lt~obsolete.m4 @@ -1,13 +1,13 @@ # lt~obsolete.m4 -- aclocal satisfying obsolete definitions. -*-Autoconf-*- # -# Copyright (C) 2004, 2005, 2007 Free Software Foundation, Inc. +# Copyright (C) 2004, 2005, 2007, 2009 Free Software Foundation, Inc. # Written by Scott James Remnant, 2004. # # This file is free software; the Free Software Foundation gives # unlimited permission to copy and/or distribute it, with or without # modifications, as long as this notice is preserved. -# serial 4 lt~obsolete.m4 +# serial 5 lt~obsolete.m4 # These exist entirely to fool aclocal when bootstrapping libtool. # @@ -77,7 +77,6 @@ m4_ifndef([AC_DISABLE_FAST_INSTALL], [AC_DEFUN([AC_DISABLE_FAST_INSTALL])]) m4_ifndef([_LT_AC_LANG_CXX], [AC_DEFUN([_LT_AC_LANG_CXX])]) m4_ifndef([_LT_AC_LANG_F77], [AC_DEFUN([_LT_AC_LANG_F77])]) m4_ifndef([_LT_AC_LANG_GCJ], [AC_DEFUN([_LT_AC_LANG_GCJ])]) -m4_ifndef([AC_LIBTOOL_RC], [AC_DEFUN([AC_LIBTOOL_RC])]) m4_ifndef([AC_LIBTOOL_LANG_C_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_C_CONFIG])]) m4_ifndef([_LT_AC_LANG_C_CONFIG], [AC_DEFUN([_LT_AC_LANG_C_CONFIG])]) m4_ifndef([AC_LIBTOOL_LANG_CXX_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_CXX_CONFIG])]) @@ -90,3 +89,10 @@ m4_ifndef([AC_LIBTOOL_LANG_RC_CONFIG], [AC_DEFUN([AC_LIBTOOL_LANG_RC_CONFIG])]) m4_ifndef([_LT_AC_LANG_RC_CONFIG], [AC_DEFUN([_LT_AC_LANG_RC_CONFIG])]) m4_ifndef([AC_LIBTOOL_CONFIG], [AC_DEFUN([AC_LIBTOOL_CONFIG])]) m4_ifndef([_LT_AC_FILE_LTDLL_C], [AC_DEFUN([_LT_AC_FILE_LTDLL_C])]) +m4_ifndef([_LT_REQUIRED_DARWIN_CHECKS], [AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS])]) +m4_ifndef([_LT_AC_PROG_CXXCPP], [AC_DEFUN([_LT_AC_PROG_CXXCPP])]) +m4_ifndef([_LT_PREPARE_SED_QUOTE_VARS], [AC_DEFUN([_LT_PREPARE_SED_QUOTE_VARS])]) +m4_ifndef([_LT_PROG_ECHO_BACKSLASH], [AC_DEFUN([_LT_PROG_ECHO_BACKSLASH])]) +m4_ifndef([_LT_PROG_F77], [AC_DEFUN([_LT_PROG_F77])]) +m4_ifndef([_LT_PROG_FC], [AC_DEFUN([_LT_PROG_FC])]) +m4_ifndef([_LT_PROG_CXX], [AC_DEFUN([_LT_PROG_CXX])]) diff --git a/nonunix.h b/nonunix.h deleted file mode 100644 index 09de9d2..0000000 --- a/nonunix.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * (c) 2006 Quest Software, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of Quest Software, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _NONUNIX_H -#define _NONUNIX_H - -void -sudo_nonunix_groupcheck_init(void); - -void -sudo_nonunix_groupcheck_cleanup(void); - -int -sudo_nonunix_groupcheck( const char* group, const char* user, const struct passwd* pwd ); - -int -sudo_nonunix_groupcheck_available(void); - -#endif /* _NONUNIX_H */ diff --git a/pathnames.h.in b/pathnames.h.in index 96c4523..32bff86 100644 --- a/pathnames.h.in +++ b/pathnames.h.in @@ -55,6 +55,13 @@ #define _PATH_ENVIRONMENT "/etc/environment" #endif /* _PATH_ENVIRONMENT */ +/* + * NOTE: _PATH_SUDO_CONF is usually overridden by the Makefile. + */ +#ifndef _PATH_SUDO_CONF +#define _PATH_SUDO_CONF "/etc/sudo.conf" +#endif /* _PATH_SUDO_CONF */ + /* * NOTE: _PATH_SUDOERS is usually overridden by the Makefile. */ @@ -102,6 +109,10 @@ #undef _PATH_SUDO_ASKPASS #endif /* _PATH_SUDO_ASKPASS */ +#ifndef _PATH_SUDO_PLUGIN_DIR +#undef _PATH_SUDO_PLUGIN_DIR +#endif /* _PATH_SUDO_PLUGIN_DIR */ + #ifndef _PATH_VI #undef _PATH_VI #endif /* _PATH_VI */ @@ -130,6 +141,10 @@ #undef _PATH_MAILDIR #endif /* _PATH_MAILDIR */ +#ifndef _PATH_UTMP +#undef _PATH_UTMP +#endif /* _PATH_UTMP */ + #ifndef _PATH_SUDO_SESH #undef _PATH_SUDO_SESH #endif /* _PATH_SUDO_SESH */ diff --git a/plugins/sample/Makefile.in b/plugins/sample/Makefile.in new file mode 100644 index 0000000..180dee3 --- /dev/null +++ b/plugins/sample/Makefile.in @@ -0,0 +1,123 @@ +# +# Copyright (c) 2011 Todd C. Miller +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# @configure_input@ +# + +#### Start of system configuration section. #### + +srcdir = @srcdir@ +devdir = @devdir@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +incdir = $(top_srcdir)/include + +# Compiler & tools to use +CC = @CC@ +LIBTOOL = @LIBTOOL@ @LT_STATIC@ + +# Our install program supports extra flags... +INSTALL = $(SHELL) $(top_srcdir)/install-sh -c + +# Libraries +LIBS = $(LIBOBJDIR)/libreplace.la + +# C preprocessor flags +CPPFLAGS = -I$(incdir) -I$(top_builddir) @CPPFLAGS@ + +# Usually -O and/or -g +CFLAGS = @CFLAGS@ + +# Flags to pass to the link stage +LDFLAGS = @LDFLAGS@ +LTLDFLAGS = @LTLDFLAGS@ + +# Where to install things... +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +sbindir = @sbindir@ +sysconfdir = @sysconfdir@ +libexecdir = @libexecdir@ +datarootdir = @datarootdir@ +localstatedir = @localstatedir@ +plugindir = @PLUGINDIR@ +soext = @SOEXT@ + +# OS dependent defines +DEFS = @OSDEFS@ + +#### End of system configuration section. #### + +SHELL = @SHELL@ + +OBJS = sample_plugin.lo + +LIBOBJDIR = $(top_builddir)/@ac_config_libobj_dir@/ + +VERSION = @PACKAGE_VERSION@ + +all: sample_plugin.la + +Makefile: $(srcdir)/Makefile.in + (cd $(top_builddir) && ./config.status --file plugins/sample/Makefile) + +.SUFFIXES: .o .c .h .lo + +.c.lo: + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $< + +sample_plugin.lo: $(srcdir)/sample_plugin.c + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/sample_plugin.c + +sample_plugin.la: $(OBJS) + $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(LTLDFLAGS) -o $@ $(OBJS) $(LIBS) -module -export-symbols $(srcdir)/sample_plugin.sym -avoid-version -rpath $(plugindir) + +pre-install: + +install: install-dirs install-plugin + +install-dirs: + $(SHELL) $(top_srcdir)/mkinstalldirs $(DESTDIR)$(plugindir) + +install-binaries: + +install-includes: + +install-doc: + +install-plugin: install-dirs sample_plugin.la + $(INSTALL) -b~ -M 0755 .libs/sample_plugin$(soext) $(DESTDIR)$(plugindir) + +uninstall: + -rm -f $(DESTDIR)$(plugindir)/sample_plugin$(soext) + +check: + +clean: + -$(LIBTOOL) --mode=clean rm -f *.lo *.o *.la *.a stamp-* core *.core core.* + +mostlyclean: clean + +distclean: clean + -rm -rf Makefile .libs + +clobber: distclean + +realclean: distclean + rm -f TAGS tags + +cleandir: realclean diff --git a/plugins/sample/sample_plugin.c b/plugins/sample/sample_plugin.c new file mode 100644 index 0000000..5ac19a4 --- /dev/null +++ b/plugins/sample/sample_plugin.c @@ -0,0 +1,511 @@ +/* + * Copyright (c) 2010-2011 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include +#include + +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS) +# include +# endif +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#include +#include +#include +#include +#include +#include + +#include +#include "sudo_plugin.h" +#include "missing.h" + +/* + * Sample plugin module that allows any user who knows the password + * ("test") to run any command as root. Since there is no credential + * caching the validate and invalidate functions are NULL. + */ + +#ifdef __TANDEM +# define ROOT_UID 65535 +#else +# define ROOT_UID 0 +#endif + +#undef TRUE +#define TRUE 1 +#undef FALSE +#define FALSE 0 +#undef ERROR +#define ERROR -1 + +static struct plugin_state { + char **envp; + char * const *settings; + char * const *user_info; +} plugin_state; +static sudo_conv_t sudo_conv; +static sudo_printf_t sudo_log; +static FILE *input, *output; +static uid_t runas_uid = ROOT_UID; +static gid_t runas_gid = -1; +static int use_sudoedit = FALSE; + +/* + * Allocate storage for a name=value string and return it. + */ +static char * +fmt_string(const char *var, const char *val) +{ + size_t var_len = strlen(var); + size_t val_len = strlen(val); + char *cp, *str; + + cp = str = malloc(var_len + 1 + val_len + 1); + if (str != NULL) { + memcpy(cp, var, var_len); + cp += var_len; + *cp++ = '='; + memcpy(cp, val, val_len); + cp += val_len; + *cp = '\0'; + } + + return str; +} + +/* + * Plugin policy open function. + */ +static int +policy_open(unsigned int version, sudo_conv_t conversation, + sudo_printf_t sudo_printf, char * const settings[], + char * const user_info[], char * const user_env[]) +{ + char * const *ui; + struct passwd *pw; + const char *runas_user = NULL; + struct group *gr; + const char *runas_group = NULL; + + if (!sudo_conv) + sudo_conv = conversation; + if (!sudo_log) + sudo_log = sudo_printf; + + if (SUDO_API_VERSION_GET_MAJOR(version) != SUDO_API_VERSION_MAJOR) { + sudo_log(SUDO_CONV_ERROR_MSG, + "the sample plugin requires API version %d.x\n", + SUDO_API_VERSION_MAJOR); + return ERROR; + } + + /* Only allow commands to be run as root. */ + for (ui = settings; *ui != NULL; ui++) { + if (strncmp(*ui, "runas_user=", sizeof("runas_user=") - 1) == 0) { + runas_user = *ui + sizeof("runas_user=") - 1; + } + if (strncmp(*ui, "runas_group=", sizeof("runas_group=") - 1) == 0) { + runas_group = *ui + sizeof("runas_group=") - 1; + } +#if !defined(HAVE_GETPROGNAME) && !defined(HAVE___PROGNAME) + if (strncmp(*ui, "progname=", sizeof("progname=") - 1) == 0) { + setprogname(*ui + sizeof("progname=") - 1); + } +#endif + /* Check to see if sudo was called as sudoedit or with -e flag. */ + if (strncmp(*ui, "sudoedit=", sizeof("sudoedit=") - 1) == 0) { + if (strcasecmp(*ui + sizeof("sudoedit=") - 1, "true") == 0) + use_sudoedit = TRUE; + } + /* This plugin doesn't support running sudo with no arguments. */ + if (strncmp(*ui, "implied_shell=", sizeof("implied_shell=") - 1) == 0) { + if (strcasecmp(*ui + sizeof("implied_shell=") - 1, "true") == 0) + return -2; /* usage error */ + } + } + if (runas_user != NULL) { + if ((pw = getpwnam(runas_user)) == NULL) { + sudo_log(SUDO_CONV_ERROR_MSG, "unknown user %s\n", runas_user); + return 0; + } + runas_uid = pw->pw_uid; + } + if (runas_group != NULL) { + if ((gr = getgrnam(runas_group)) == NULL) { + sudo_log(SUDO_CONV_ERROR_MSG, "unknown group %s\n", runas_group); + return 0; + } + runas_gid = gr->gr_gid; + } + + /* Plugin state. */ + plugin_state.envp = (char **)user_env; + plugin_state.settings = settings; + plugin_state.user_info = user_info; + + return 1; +} + +static char * +find_in_path(char *command, char **envp) +{ + struct stat sb; + char *path, *path0, **ep, *cp; + char pathbuf[PATH_MAX], *qualified = NULL; + + if (strchr(command, '/') != NULL) + return command; + + path = _PATH_DEFPATH; + for (ep = plugin_state.envp; *ep != NULL; ep++) { + if (strncmp(*ep, "PATH=", 5) == 0) { + path = *ep + 5; + break; + } + } + path = path0 = strdup(path); + do { + if ((cp = strchr(path, ':'))) + *cp = '\0'; + snprintf(pathbuf, sizeof(pathbuf), "%s/%s", *path ? path : ".", + command); + if (stat(pathbuf, &sb) == 0) { + if (S_ISREG(sb.st_mode) && (sb.st_mode & 0000111)) { + qualified = pathbuf; + break; + } + } + path = cp + 1; + } while (cp != NULL); + free(path0); + return qualified ? strdup(qualified) : NULL; +} + +static int +check_passwd(void) +{ + struct sudo_conv_message msg; + struct sudo_conv_reply repl; + + /* Prompt user for password via conversation function. */ + memset(&msg, 0, sizeof(msg)); + msg.msg_type = SUDO_CONV_PROMPT_ECHO_OFF; + msg.msg = "Password: "; + memset(&repl, 0, sizeof(repl)); + sudo_conv(1, &msg, &repl); + if (repl.reply == NULL) { + sudo_log(SUDO_CONV_ERROR_MSG, "missing password\n"); + return FALSE; + } + if (strcmp(repl.reply, "test") != 0) { + sudo_log(SUDO_CONV_ERROR_MSG, "incorrect password\n"); + return FALSE; + } + return TRUE; +} + +static char ** +build_command_info(char *command) +{ + static char **command_info; + int i = 0; + + /* Setup command info. */ + command_info = calloc(32, sizeof(char *)); + if (command_info == NULL) + return NULL; + if ((command_info[i++] = fmt_string("command", command)) == NULL || + asprintf(&command_info[i++], "runas_euid=%ld", (long)runas_uid) == -1 || + asprintf(&command_info[i++], "runas_uid=%ld", (long)runas_uid) == -1) { + return NULL; + } + if (runas_gid != -1) { + if (asprintf(&command_info[i++], "runas_gid=%ld", (long)runas_gid) == -1 || + asprintf(&command_info[i++], "runas_egid=%ld", (long)runas_gid) == -1) { + return NULL; + } + } + if (use_sudoedit) { + command_info[i] = strdup("sudoedit=true"); + if (command_info[i++] == NULL) + return NULL; + } +#ifdef USE_TIMEOUT + command_info[i++] = "timeout=30"; +#endif + return command_info; +} + +static char * +find_editor(int nfiles, char * const files[], char **argv_out[]) +{ + char *cp, **ep, **nargv, *editor, *editor_path; + int ac, i, nargc, wasblank; + + /* Lookup EDITOR in user's environment. */ + editor = _PATH_VI; + for (ep = plugin_state.envp; *ep != NULL; ep++) { + if (strncmp(*ep, "EDITOR=", 7) == 0) { + editor = *ep + 7; + break; + } + } + editor = strdup(editor); + if (editor == NULL) { + sudo_log(SUDO_CONV_ERROR_MSG, "unable to allocate memory\n"); + return NULL; + } + + /* + * Split editor into an argument vector; editor is reused (do not free). + * The EDITOR environment variables may contain command + * line args so look for those and alloc space for them too. + */ + nargc = 1; + for (wasblank = 0, cp = editor; *cp != '\0'; cp++) { + if (isblank((unsigned char) *cp)) + wasblank = 1; + else if (wasblank) { + wasblank = 0; + nargc++; + } + } + /* If we can't find the editor in the user's PATH, give up. */ + cp = strtok(editor, " \t"); + if (cp == NULL || + (editor_path = find_in_path(editor, plugin_state.envp)) == NULL) { + return NULL; + } + nargv = (char **) malloc((nargc + 1 + nfiles + 1) * sizeof(char *)); + if (nargv == NULL) { + sudo_log(SUDO_CONV_ERROR_MSG, "unable to allocate memory\n"); + return NULL; + } + for (ac = 0; cp != NULL && ac < nargc; ac++) { + nargv[ac] = cp; + cp = strtok(NULL, " \t"); + } + nargv[ac++] = "--"; + for (i = 0; i < nfiles; ) + nargv[ac++] = files[i++]; + nargv[ac] = NULL; + + *argv_out = nargv; + return editor_path; +} + +/* + * Plugin policy check function. + * Simple example that prompts for a password, hard-coded to "test". + */ +static int +policy_check(int argc, char * const argv[], + char *env_add[], char **command_info_out[], + char **argv_out[], char **user_env_out[]) +{ + char *command; + + if (!argc || argv[0] == NULL) { + sudo_log(SUDO_CONV_ERROR_MSG, "no command specified\n"); + return FALSE; + } + + if (!check_passwd()) + return FALSE; + + command = find_in_path(argv[0], plugin_state.envp); + if (command == NULL) { + sudo_log(SUDO_CONV_ERROR_MSG, "%s: command not found\n", argv[0]); + return FALSE; + } + + /* If "sudo vi" is run, auto-convert to sudoedit. */ + if (strcmp(command, _PATH_VI) == 0) + use_sudoedit = TRUE; + + if (use_sudoedit) { + /* Rebuild argv using editor */ + command = find_editor(argc - 1, argv + 1, argv_out); + if (command == NULL) { + sudo_log(SUDO_CONV_ERROR_MSG, "unable to find valid editor\n"); + return ERROR; + } + use_sudoedit = TRUE; + } else { + /* No changes needd to argv */ + *argv_out = (char **)argv; + } + + /* No changes to envp */ + *user_env_out = plugin_state.envp; + + /* Setup command info. */ + *command_info_out = build_command_info(command); + if (*command_info_out == NULL) { + sudo_log(SUDO_CONV_ERROR_MSG, "out of memory\n"); + return ERROR; + } + + return TRUE; +} + +static int +policy_list(int argc, char * const argv[], int verbose, const char *list_user) +{ + /* + * List user's capabilities. + */ + sudo_log(SUDO_CONV_INFO_MSG, "Validated users may run any command\n"); + return TRUE; +} + +static int +policy_version(int verbose) +{ + sudo_log(SUDO_CONV_INFO_MSG, "Sample policy plugin version %s\n", PACKAGE_VERSION); + return TRUE; +} + +static void +policy_close(int exit_status, int error) +{ + /* + * The policy might log the command exit status here. + * In this example, we just print a message. + */ + if (error) { + sudo_log(SUDO_CONV_ERROR_MSG, "Command error: %s\n", strerror(error)); + } else { + if (WIFEXITED(exit_status)) { + sudo_log(SUDO_CONV_INFO_MSG, "Command exited with status %d\n", + WEXITSTATUS(exit_status)); + } else if (WIFSIGNALED(exit_status)) { + sudo_log(SUDO_CONV_INFO_MSG, "Command killed by signal %d\n", + WTERMSIG(exit_status)); + } + } +} + +static int +io_open(unsigned int version, sudo_conv_t conversation, + sudo_printf_t sudo_printf, char * const settings[], + char * const user_info[], char * const command_info[], + int argc, char * const argv[], char * const user_env[]) +{ + int fd; + char path[PATH_MAX]; + + if (!sudo_conv) + sudo_conv = conversation; + if (!sudo_log) + sudo_log = sudo_printf; + + /* Open input and output files. */ + snprintf(path, sizeof(path), "/var/tmp/sample-%u.output", + (unsigned int)getpid()); + fd = open(path, O_WRONLY|O_CREAT|O_EXCL, 0644); + if (fd == -1) + return FALSE; + output = fdopen(fd, "w"); + + snprintf(path, sizeof(path), "/var/tmp/sample-%u.input", + (unsigned int)getpid()); + fd = open(path, O_WRONLY|O_CREAT|O_EXCL, 0644); + if (fd == -1) + return FALSE; + input = fdopen(fd, "w"); + + return TRUE; +} + +static void +io_close(int exit_status, int error) +{ + fclose(input); + fclose(output); +} + +static int +io_version(int verbose) +{ + sudo_log(SUDO_CONV_INFO_MSG, "Sample I/O plugin version %s\n", + PACKAGE_VERSION); + return TRUE; +} + +static int +io_log_input(const char *buf, unsigned int len) +{ + fwrite(buf, len, 1, input); + return TRUE; +} + +static int +io_log_output(const char *buf, unsigned int len) +{ + fwrite(buf, len, 1, output); + return TRUE; +} + +struct policy_plugin sample_policy = { + SUDO_POLICY_PLUGIN, + SUDO_API_VERSION, + policy_open, + policy_close, + policy_version, + policy_check, + policy_list, + NULL, /* validate */ + NULL /* invalidate */ +}; + +/* + * Note: This plugin does not differentiate between tty and pipe I/O. + * It all gets logged to the same file. + */ +struct io_plugin sample_io = { + SUDO_IO_PLUGIN, + SUDO_API_VERSION, + io_open, + io_close, + io_version, + io_log_input, /* tty input */ + io_log_output, /* tty output */ + io_log_input, /* command stdin if not tty */ + io_log_output, /* command stdout if not tty */ + io_log_output /* command stderr if not tty */ +}; diff --git a/plugins/sample/sample_plugin.sym b/plugins/sample/sample_plugin.sym new file mode 100644 index 0000000..9f85094 --- /dev/null +++ b/plugins/sample/sample_plugin.sym @@ -0,0 +1,2 @@ +sample_policy +sample_io diff --git a/plugins/sample_group/Makefile.in b/plugins/sample_group/Makefile.in new file mode 100644 index 0000000..eda9f1f --- /dev/null +++ b/plugins/sample_group/Makefile.in @@ -0,0 +1,126 @@ +# +# Copyright (c) 2011 Todd C. Miller +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# @configure_input@ +# + +#### Start of system configuration section. #### + +srcdir = @srcdir@ +devdir = @devdir@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +incdir = $(top_srcdir)/include + +# Compiler & tools to use +CC = @CC@ +LIBTOOL = @LIBTOOL@ @LT_STATIC@ + +# Our install program supports extra flags... +INSTALL = $(SHELL) $(top_srcdir)/install-sh -c + +# Libraries +LIBS = $(LIBOBJDIR)/libreplace.la + +# C preprocessor flags +CPPFLAGS = -I$(incdir) -I$(top_builddir) @CPPFLAGS@ + +# Usually -O and/or -g +CFLAGS = @CFLAGS@ + +# Flags to pass to the link stage +LDFLAGS = @LDFLAGS@ +LTLDFLAGS = @LTLDFLAGS@ + +# Where to install things... +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +sbindir = @sbindir@ +sysconfdir = @sysconfdir@ +libexecdir = @libexecdir@ +datarootdir = @datarootdir@ +localstatedir = @localstatedir@ +plugindir = @PLUGINDIR@ +soext = @SOEXT@ + +# OS dependent defines +DEFS = @OSDEFS@ + +#### End of system configuration section. #### + +SHELL = @SHELL@ + +OBJS = sample_group.lo getgrent.lo + +LIBOBJDIR = $(top_builddir)/@ac_config_libobj_dir@/ + +VERSION = @PACKAGE_VERSION@ + +all: sample_group.la + +Makefile: $(srcdir)/Makefile.in + (cd $(top_builddir) && ./config.status --file plugins/sample_group/Makefile) + +.SUFFIXES: .o .c .h .lo + +.c.lo: + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $< + +getgrent.lo: $(srcdir)/getgrent.c + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/getgrent.c + +sample_group.lo: $(srcdir)/sample_group.c + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/sample_group.c + +sample_group.la: $(OBJS) + $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) $(LTLDFLAGS) -o $@ $(OBJS) $(LIBS) -module -export-symbols $(srcdir)/sample_group.sym -avoid-version -rpath $(plugindir) + +pre-install: + +install: install-dirs install-plugin + +install-dirs: + $(SHELL) $(top_srcdir)/mkinstalldirs $(DESTDIR)$(plugindir) + +install-binaries: + +install-includes: + +install-doc: + +install-plugin: install-dirs sample_group.la + $(INSTALL) -b~ -M 0755 .libs/sample_group$(soext) $(DESTDIR)$(plugindir) + +uninstall: + -rm -f $(DESTDIR)$(plugindir)/sample_group$(soext) + +check: + +clean: + -$(LIBTOOL) --mode=clean rm -f *.lo *.o *.la *.a stamp-* core *.core core.* + +mostlyclean: clean + +distclean: clean + -rm -rf Makefile .libs + +clobber: distclean + +realclean: distclean + rm -f TAGS tags + +cleandir: realclean diff --git a/plugins/sample_group/getgrent.c b/plugins/sample_group/getgrent.c new file mode 100644 index 0000000..aa98c14 --- /dev/null +++ b/plugins/sample_group/getgrent.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2005,2008,2010-2011 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Trivial replacements for the libc getgr{uid,nam}() routines. + */ + +#include + +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS) +# include +# endif +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#include +#include +#include +#include + +#include "missing.h" + +#ifndef LINE_MAX +# define LINE_MAX 2048 +#endif + +#undef GRMEM_MAX +#define GRMEM_MAX 200 + +static FILE *grf; +static const char *grfile = "/etc/group"; +static int gr_stayopen; + +void mysetgrfile(const char *); +void mysetgrent(void); +void myendgrent(void); +struct group *mygetgrent(void); +struct group *mygetgrnam(const char *); +struct group *mygetgrgid(gid_t); + +void +mysetgrfile(const char *file) +{ + grfile = file; + if (grf != NULL) + myendgrent(); +} + +void +mysetgrent(void) +{ + if (grf == NULL) { + grf = fopen(grfile, "r"); + if (grf != NULL) + fcntl(fileno(grf), F_SETFD, FD_CLOEXEC); + } else { + rewind(grf); + } + gr_stayopen = 1; +} + +void +myendgrent(void) +{ + if (grf != NULL) { + fclose(grf); + grf = NULL; + } + gr_stayopen = 0; +} + +struct group * +mygetgrent(void) +{ + static struct group gr; + static char grbuf[LINE_MAX], *gr_mem[GRMEM_MAX+1]; + size_t len; + char *cp, *colon; + int n; + + if ((colon = fgets(grbuf, sizeof(grbuf), grf)) == NULL) + return NULL; + + memset(&gr, 0, sizeof(gr)); + if ((colon = strchr(cp = colon, ':')) == NULL) + return NULL; + *colon++ = '\0'; + gr.gr_name = cp; + if ((colon = strchr(cp = colon, ':')) == NULL) + return NULL; + *colon++ = '\0'; + gr.gr_passwd = cp; + if ((colon = strchr(cp = colon, ':')) == NULL) + return NULL; + *colon++ = '\0'; + gr.gr_gid = atoi(cp); + len = strlen(colon); + if (len > 0 && colon[len - 1] == '\n') + colon[len - 1] = '\0'; + if (*colon != '\0') { + gr.gr_mem = gr_mem; + cp = strtok(colon, ","); + for (n = 0; cp != NULL && n < GRMEM_MAX; n++) { + gr.gr_mem[n] = cp; + cp = strtok(NULL, ","); + } + gr.gr_mem[n++] = NULL; + } else + gr.gr_mem = NULL; + return &gr; +} + +struct group * +mygetgrnam(const char *name) +{ + struct group *gr; + + if (grf == NULL) { + if ((grf = fopen(grfile, "r")) == NULL) + return NULL; + fcntl(fileno(grf), F_SETFD, FD_CLOEXEC); + } else { + rewind(grf); + } + while ((gr = mygetgrent()) != NULL) { + if (strcmp(gr->gr_name, name) == 0) + break; + } + if (!gr_stayopen) { + fclose(grf); + grf = NULL; + } + return gr; +} + +struct group * +mygetgrgid(gid_t gid) +{ + struct group *gr; + + if (grf == NULL) { + if ((grf = fopen(grfile, "r")) == NULL) + return NULL; + fcntl(fileno(grf), F_SETFD, FD_CLOEXEC); + } else { + rewind(grf); + } + while ((gr = mygetgrent()) != NULL) { + if (gr->gr_gid == gid) + break; + } + if (!gr_stayopen) { + fclose(grf); + grf = NULL; + } + return gr; +} diff --git a/plugins/sample_group/plugin_test.c b/plugins/sample_group/plugin_test.c new file mode 100644 index 0000000..87077a5 --- /dev/null +++ b/plugins/sample_group/plugin_test.c @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2010-2011 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sudo_plugin.h" + +/* + * Simple driver to test sudoer group plugins. + * usage: plugin_test [-p "plugin.so plugin_args ..."] user:group ... + */ + +static void *group_handle; +static struct sudoers_group_plugin *group_plugin; + +static int +plugin_printf(int msg_type, const char *fmt, ...) +{ + va_list ap; + FILE *fp; + + switch (msg_type) { + case SUDO_CONV_INFO_MSG: + fp = stdout; + break; + case SUDO_CONV_ERROR_MSG: + fp = stderr; + break; + default: + errno = EINVAL; + return -1; + } + + va_start(ap, fmt); + vfprintf(fp, fmt, ap); + va_end(ap); + + return 0; +} + +/* + * Load the specified plugin and run its init function. + * Returns -1 if unable to open the plugin, else it returns + * the value from the plugin's init function. + */ +static int +group_plugin_load(char *plugin_info) +{ + char *args, path[PATH_MAX], savedch; + char **argv = NULL; + int rc; + + /* + * Fill in .so path and split out args (if any). + */ + if ((args = strpbrk(plugin_info, " \t")) != NULL) { + savedch = *args; + *args = '\0'; + } + strncpy(path, plugin_info, sizeof(path) - 1); + path[sizeof(path) - 1] = '\0'; + if (args != NULL) + *args++ = savedch; + + /* Open plugin and map in symbol. */ + group_handle = dlopen(path, RTLD_LAZY); + if (!group_handle) { + fprintf(stderr, "unable to dlopen %s: %s\n", path, dlerror()); + return -1; + } + group_plugin = dlsym(group_handle, "group_plugin"); + if (group_plugin == NULL) { + fprintf(stderr, "unable to find symbol \"group_plugin\" in %s\n", path); + return -1; + } + + if (GROUP_API_VERSION_GET_MAJOR(group_plugin->version) != GROUP_API_VERSION_MAJOR) { + fprintf(stderr, + "%s: incompatible group plugin major version %d, expected %d\n", + path, GROUP_API_VERSION_GET_MAJOR(group_plugin->version), + GROUP_API_VERSION_MAJOR); + return -1; + } + + /* + * Split args into a vector if specified. + */ + if (args != NULL) { + int ac = 0, wasblank = 1; + char *cp; + + for (cp = args; *cp != '\0'; cp++) { + if (isblank((unsigned char)*cp)) { + wasblank = 1; + } else if (wasblank) { + wasblank = 0; + ac++; + } + } + if (ac != 0) { + argv = malloc(ac * sizeof(char *)); + if (argv == NULL) { + fprintf(stderr, "unable to allocate memory\n"); + return -1; + } + ac = 0; + for ((cp = strtok(args, " \t")); cp; (cp = strtok(NULL, " \t"))) + argv[ac++] = cp; + } + } + + rc = (group_plugin->init)(GROUP_API_VERSION, plugin_printf, argv); + + free(argv); + + return rc; +} + +static void +group_plugin_unload(void) +{ + (group_plugin->cleanup)(); + dlclose(group_handle); + group_handle = NULL; +} + +static int +group_plugin_query(const char *user, const char *group, + const struct passwd *pwd) +{ + return group_plugin->query)(user, group, pwd; +} + +static void +usage(void) +{ + fprintf(stderr, + "usage: plugin_test [-p \"plugin.so plugin_args ...\"] user:group ...\n"); + exit(1); +} + +int +main(int argc, char *argv[]) +{ + int ch, i, found; + char *plugin = "sample_group.so"; + char *user, *group; + struct passwd *pwd; + + while ((ch = getopt(argc, argv, "p:")) != -1) { + switch (ch) { + case 'p': + plugin = optarg; + break; + default: + usage(); + } + } + argc -= optind; + argv += optind; + + if (argc < 1) + usage(); + + if (group_plugin_load(plugin) != 1) { + fprintf(stderr, "unable to load plugin: %s\n", plugin); + exit(1); + } + + for (i = 0; argv[i] != NULL; i++) { + user = argv[i]; + group = strchr(argv[i], ':'); + if (group == NULL) + continue; + *group++ = '\0'; + pwd = getpwnam(user); + found = group_plugin_query(user, group, pwd); + printf("user %s %s in group %s\n", user, found ? "is" : "NOT ", group); + } + group_plugin_unload(); + + exit(0); +} + diff --git a/plugins/sample_group/sample_group.c b/plugins/sample_group/sample_group.c new file mode 100644 index 0000000..dbd1c27 --- /dev/null +++ b/plugins/sample_group/sample_group.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2010 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include + +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS) +# include +# endif +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#include +#include +#include +#include +#include +#include + +#include "sudo_plugin.h" +#include "missing.h" + +/* + * Sample sudoers group plugin that uses an extra group file with the + * same format as /etc/group. + */ + +#undef TRUE +#define TRUE 1 +#undef FALSE +#define FALSE 0 +#undef ERROR +#define ERROR -1 + +static sudo_printf_t sudo_log; + +extern void mysetgrfile(const char *); +extern void mysetgrent(void); +extern void myendgrent(void); +extern struct group *mygetgrnam(const char *); + +static int +sample_init(int version, sudo_printf_t sudo_printf, char *const argv[]) +{ + struct stat sb; + + sudo_log = sudo_printf; + + if (GROUP_API_VERSION_GET_MAJOR(version) != GROUP_API_VERSION_MAJOR) { + sudo_log(SUDO_CONV_ERROR_MSG, + "sample_group: incompatible major version %d, expected %d\n", + GROUP_API_VERSION_GET_MAJOR(version), + GROUP_API_VERSION_MAJOR); + return ERROR; + } + + /* Sanity check the specified group file. */ + if (argv == NULL || argv[0] == NULL) { + sudo_log(SUDO_CONV_ERROR_MSG, + "sample_group: path to group file not specified\n"); + return ERROR; + } + if (stat(argv[0], &sb) != 0) { + sudo_log(SUDO_CONV_ERROR_MSG, + "sample_group: %s: %s\n", argv[0], strerror(errno)); + return ERROR; + } + if ((sb.st_mode & (S_IWGRP|S_IWOTH)) != 0) { + sudo_log(SUDO_CONV_ERROR_MSG, + "%s must be only be writable by owner\n", argv[0]); + return ERROR; + } + + mysetgrfile(argv[0]); + mysetgrent(); + + return TRUE; +} + +static void +sample_cleanup(void) +{ + myendgrent(); +} + +/* + * Returns TRUE if "user" is a member of "group", else FALSE. + */ +static int +sample_query(const char *user, const char *group, const struct passwd *pwd) +{ + struct group *grp; + char **member; + + grp = mygetgrnam(group); + if (grp != NULL) { + for (member = grp->gr_mem; *member != NULL; member++) { + if (strcasecmp(user, *member) == 0) + return TRUE; + } + } + + return FALSE; +} + +struct sudoers_group_plugin group_plugin = { + GROUP_API_VERSION, + sample_init, + sample_cleanup, + sample_query +}; diff --git a/plugins/sample_group/sample_group.sym b/plugins/sample_group/sample_group.sym new file mode 100644 index 0000000..a859d6c --- /dev/null +++ b/plugins/sample_group/sample_group.sym @@ -0,0 +1 @@ +group_plugin diff --git a/plugins/sudoers/Makefile.in b/plugins/sudoers/Makefile.in new file mode 100644 index 0000000..d8c298b --- /dev/null +++ b/plugins/sudoers/Makefile.in @@ -0,0 +1,453 @@ +# +# Copyright (c) 1996, 1998-2005, 2007-2011 +# Todd C. Miller +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# Sponsored in part by the Defense Advanced Research Projects +# Agency (DARPA) and Air Force Research Laboratory, Air Force +# Materiel Command, USAF, under agreement number F39502-99-1-0512. +# +# @configure_input@ +# + +#### Start of system configuration section. #### + +srcdir = @srcdir@ +devdir = @devdir@ +authdir = $(srcdir)/auth +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +incdir = $(top_srcdir)/include +docdir = @docdir@ +timedir = @timedir@ + +# Compiler & tools to use +CC = @CC@ +LIBTOOL = @LIBTOOL@ +FLEX = @FLEX@ +YACC = @YACC@ + +# Our install program supports extra flags... +INSTALL = $(SHELL) $(top_srcdir)/install-sh -c + +# Libraries +LIBS = $(top_builddir)/common/libcommon.la $(top_builddir)/@ac_config_libobj_dir@/libreplace.la +NET_LIBS = @NET_LIBS@ +SUDOERS_LIBS = @SUDOERS_LIBS@ @AFS_LIBS@ @GETGROUPS_LIB@ $(LIBS) $(NET_LIBS) @ZLIB@ +REPLAY_LIBS = @REPLAY_LIBS@ @ZLIB@ + +# C preprocessor flags +CPPFLAGS = -I$(incdir) -I$(top_builddir) -I$(srcdir) -I$(top_srcdir) @CPPFLAGS@ + +# Usually -O and/or -g +CFLAGS = @CFLAGS@ + +# Flags to pass to the link stage +LDFLAGS = @LDFLAGS@ +SUDOERS_LDFLAGS = $(LDFLAGS) @SUDOERS_LDFLAGS@ +LTLDFLAGS = @LTLDFLAGS@ + +# Where to install things... +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +sbindir = @sbindir@ +sysconfdir = @sysconfdir@ +libexecdir = @libexecdir@ +datarootdir = @datarootdir@ +localstatedir = @localstatedir@ + +# File extension for shared objects +soext = @SOEXT@ + +# Directory in which to install the sudoers plugin +plugindir = @PLUGINDIR@ + +# Directory in which to install the sudoers file +sudoersdir = $(sysconfdir) + +# Directory in which to install sudoreplay. +replaydir = $(bindir) + +# Directory in which to install visudo +visudodir = $(sbindir) + +# User and group ids the installed files should be "owned" by +install_uid = 0 +install_gid = 0 + +# User, group, and mode the sudoers file should be "owned" by (configure) +sudoers_uid = @SUDOERS_UID@ +sudoers_gid = @SUDOERS_GID@ +sudoers_mode = @SUDOERS_MODE@ + +# Pass in paths and uid/gid + OS dependent defines +DEFS = @OSDEFS@ -D_PATH_SUDOERS=\"$(sudoersdir)/sudoers\" -DSUDOERS_UID=$(sudoers_uid) -DSUDOERS_GID=$(sudoers_gid) -DSUDOERS_MODE=$(sudoers_mode) + +#### End of system configuration section. #### + +SHELL = @SHELL@ + +PROGS = sudoers.la visudo sudoreplay testsudoers + +TEST_PROGS = check_iolog_path check_fill + +AUTH_OBJS = sudo_auth.lo @AUTH_OBJS@ + +LIBSUDOERS_OBJS = alias.lo audit.lo defaults.lo gram.lo match.lo pwutil.lo \ + timestr.lo toke.lo toke_util.lo redblack.lo + +SUDOERS_OBJS = $(AUTH_OBJS) boottime.lo check.lo env.lo goodpath.lo \ + group_plugin.lo find_path.lo interfaces.lo logging.lo \ + parse.lo set_perms.lo sudoers.lo sudo_nss.lo iolog.lo \ + iolog_path.lo @SUDOERS_OBJS@ + +VISUDO_OBJS = visudo.o goodpath.o find_path.o error.o + +REPLAY_OBJS = getdate.o sudoreplay.o error.o + +TEST_OBJS = interfaces.o testsudoers.o tsgetgrpw.o error.o group_plugin.o \ + net_ifs.o + +CHECK_IOLOG_PATH_OBJS = check_iolog_path.o error.o iolog_path.lo pwutil.lo \ + redblack.lo + +VERSION = @PACKAGE_VERSION@ +PACKAGE_TARNAME = @PACKAGE_TARNAME@ + +SUDODEP = $(srcdir)/sudoers.h $(srcdir)/defaults.h $(incdir)/error.h \ + $(incdir)/list.h $(srcdir)/logging.h $(incdir)/missing.h \ + $(srcdir)/sudo_nss.h $(devdir)/def_data.h \ + $(top_builddir)/pathnames.h $(top_builddir)/config.h + +AUTHDEP = $(SUDODEP) $(authdir)/sudo_auth.h + +INSDEP = $(srcdir)/ins_2001.h $(srcdir)/ins_classic.h $(srcdir)/ins_csops.h \ + $(srcdir)/ins_goons.h $(srcdir)/insults.h + +all: $(PROGS) + +.SUFFIXES: .o .c .h .l .y .lo + +.c.o: + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $< + +.c.lo: + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $< + +# Prevent default rules from building .c files from .l and .y files +.l.c: + +.y.c: + +Makefile: $(srcdir)/Makefile.in + (cd $(top_builddir) && ./config.status --file plugins/sudoers/Makefile) + +libsudoers.la: $(LIBSUDOERS_OBJS) + $(LIBTOOL) --mode=link $(CC) -o $@ $(LIBSUDOERS_OBJS) -no-install + +sudoers.la: $(SUDOERS_OBJS) libsudoers.la + $(LIBTOOL) @LT_STATIC@ --mode=link $(CC) $(SUDOERS_LDFLAGS) $(LTLDFLAGS) -o $@ $(SUDOERS_OBJS) libsudoers.la $(SUDOERS_LIBS) -module -export-symbols $(srcdir)/sudoers.sym -avoid-version -rpath $(plugindir) + +visudo: libsudoers.la $(VISUDO_OBJS) $(LIBS) + $(LIBTOOL) --mode=link $(CC) -o $@ $(VISUDO_OBJS) $(LDFLAGS) libsudoers.la $(LIBS) $(NET_LIBS) + +sudoreplay: $(REPLAY_OBJS) $(LIBS) + $(LIBTOOL) --mode=link $(CC) -o $@ $(REPLAY_OBJS) $(LDFLAGS) timestr.lo $(REPLAY_LIBS) $(LIBS) + +testsudoers: libsudoers.la $(TEST_OBJS) $(LIBS) + $(LIBTOOL) --mode=link $(CC) -o $@ $(TEST_OBJS) $(LDFLAGS) libsudoers.la $(LIBS) $(NET_LIBS) @LIBDL@ + +check_iolog_path: $(CHECK_IOLOG_PATH_OBJS) $(LIBS) + $(LIBTOOL) --mode=link $(CC) -o $@ $(CHECK_IOLOG_PATH_OBJS) $(LDFLAGS) $(LIBS) + +check_fill: check_fill.o toke_util.lo error.o $(LIBS) + $(LIBTOOL) --mode=link $(CC) -o $@ check_fill.o toke_util.lo error.o $(LDFLAGS) $(LIBS) + +# Uncomment the following if you want "make distclean" to clean the parser +@DEV@GENERATED = gram.h gram.c toke.c def_data.c def_data.h getdate.c + +# Uncomment the lines before -@true if you intend to modify gram.y +$(devdir)/gram.c $(devdir)/gram.h: $(srcdir)/gram.y +@DEV@ $(YACC) -d $(srcdir)/gram.y +@DEV@ echo "#include " > $(devdir)/gram.c +@DEV@ cat y.tab.c >> $(devdir)/gram.c +@DEV@ rm -f y.tab.c +@DEV@ mv -f y.tab.h $(devdir)/gram.h + -@true + +# Uncomment the lines before -@true if you intend to modify toke.l +$(devdir)/toke.c: $(srcdir)/toke.l +@DEV@ $(FLEX) $(srcdir)/toke.l +@DEV@ echo "#include " > $(devdir)/toke.c +@DEV@ cat lex.yy.c >> $(devdir)/toke.c +@DEV@ rm -f lex.yy.c + -@true + +# Uncomment the lines before -@true if you intend to modify getdate.y +$(devdir)/getdate.c: $(srcdir)/getdate.y +@DEV@ echo "expect 10 shift/reduce conflicts" +@DEV@ $(YACC) $(srcdir)/getdate.y +@DEV@ echo "#include " > $(devdir)/getdate.c +@DEV@ cat y.tab.c >> $(devdir)/getdate.c +@DEV@ rm -f y.tab.c + -@true + +# Uncomment the following if you intend to modify def_data.in +@DEV@$(devdir)/def_data.c $(devdir)/def_data.h: $(srcdir)/def_data.in +@DEV@ perl $(srcdir)/mkdefaults -o $(devdir)/def_data $(srcdir)/def_data.in + +sudoers: $(srcdir)/sudoers.in + (cd $(top_builddir) && $(SHELL) config.status --file=plugins/sudoers/$@) + +# Sudoers dependencies +alias.lo: $(srcdir)/alias.c $(SUDODEP) $(srcdir)/parse.h $(incdir)/list.h $(srcdir)/redblack.h + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/alias.c +audit.lo: $(srcdir)/audit.c $(SUDODEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/audit.c +bsm_audit.lo: $(srcdir)/bsm_audit.c $(SUDODEP) $(srcdir)/bsm_audit.h + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/bsm_audit.c +boottime.lo: $(srcdir)/boottime.c $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/boottime.c +check.lo: $(srcdir)/check.c $(SUDODEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/check.c +defaults.lo: $(srcdir)/defaults.c $(SUDODEP) $(devdir)/def_data.c $(authdir)/sudo_auth.h $(devdir)/gram.h + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/defaults.c +env.lo: $(srcdir)/env.c $(SUDODEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/env.c +find_path.lo: $(srcdir)/find_path.c $(SUDODEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/find_path.c +getspwuid.lo: $(srcdir)/getspwuid.c $(SUDODEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/getspwuid.c +goodpath.lo: $(srcdir)/goodpath.c $(SUDODEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/goodpath.c +gram.lo: $(devdir)/gram.c $(SUDODEP) $(srcdir)/parse.h $(incdir)/list.h $(devdir)/gram.h + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(devdir)/gram.c +group_plugin.lo: $(srcdir)/group_plugin.c $(SUDODEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/group_plugin.c +interfaces.lo: $(srcdir)/interfaces.c $(SUDODEP) $(srcdir)/interfaces.h + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/interfaces.c +iolog.lo: $(srcdir)/iolog.c $(SUDODEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/iolog.c +iolog_path.lo: $(srcdir)/iolog_path.c $(SUDODEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/iolog_path.c +ldap.lo: $(srcdir)/ldap.c $(SUDODEP) $(srcdir)/parse.h $(incdir)/list.h + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/ldap.c +linux_audit.lo: $(srcdir)/linux_audit.c $(SUDODEP) $(srcdir)/linux_audit.h + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/linux_audit.c +logging.lo: $(srcdir)/logging.c $(SUDODEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/logging.c +match.lo: $(srcdir)/match.c $(SUDODEP) $(srcdir)/parse.h $(incdir)/list.h $(srcdir)/interfaces.h $(devdir)/gram.h + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/match.c +parse.lo: $(srcdir)/parse.c $(SUDODEP) $(srcdir)/parse.h $(incdir)/list.h $(devdir)/gram.h + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/parse.c +pwutil.lo: $(srcdir)/pwutil.c $(SUDODEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/pwutil.c +redblack.lo: $(srcdir)/redblack.c $(SUDODEP) $(srcdir)/redblack.h + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/redblack.c +set_perms.lo: $(srcdir)/set_perms.c $(SUDODEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/set_perms.c +sudo_nss.lo: $(srcdir)/sudo_nss.c $(SUDODEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/sudo_nss.c +sudoers.lo: $(srcdir)/sudoers.c $(SUDODEP) $(srcdir)/interfaces.h + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/sudoers.c +timestr.lo: $(srcdir)/timestr.c $(incdir)/missing.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/timestr.c +toke.lo: $(devdir)/toke.c $(SUDODEP) $(srcdir)/parse.h $(incdir)/list.h $(srcdir)/toke.h $(devdir)/gram.h + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(devdir)/toke.c +toke_util.lo: $(srcdir)/toke_util.c $(SUDODEP) $(srcdir)/parse.h $(srcdir)/toke.h $(devdir)/gram.h + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/toke_util.c +tsgetgrpw.lo: $(srcdir)/tsgetgrpw.c $(SUDODEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/tsgetgrpw.c +plugin_error.lo: $(srcdir)/plugin_error.c $(incdir)/error.h $(incdir)/missing.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/plugin_error.c + +# Auth dependencies +sudo_auth.lo: $(authdir)/sudo_auth.c $(AUTHDEP) $(INSDEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(authdir)/sudo_auth.c +afs.lo: $(authdir)/afs.c $(AUTHDEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(authdir)/afs.c +aix_auth.lo: $(authdir)/aix_auth.c $(AUTHDEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(authdir)/aix_auth.c +bsdauth.lo: $(authdir)/bsdauth.c $(AUTHDEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(authdir)/bsdauth.c +dce.lo: $(authdir)/dce.c $(AUTHDEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(authdir)/dce.c +fwtk.lo: $(authdir)/fwtk.c $(AUTHDEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(authdir)/fwtk.c +kerb4.lo: $(authdir)/kerb4.c $(AUTHDEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(authdir)/kerb4.c +kerb5.lo: $(authdir)/kerb5.c $(AUTHDEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(authdir)/kerb5.c +pam.lo: $(authdir)/pam.c $(AUTHDEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(authdir)/pam.c +passwd.lo: $(authdir)/passwd.c $(AUTHDEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(authdir)/passwd.c +rfc1938.lo: $(authdir)/rfc1938.c $(AUTHDEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(authdir)/rfc1938.c +secureware.lo: $(authdir)/secureware.c $(AUTHDEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(authdir)/secureware.c +securid.lo: $(authdir)/securid.c $(AUTHDEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(authdir)/securid.c +securid5.lo: $(authdir)/securid5.c $(AUTHDEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(authdir)/securid5.c +sia.lo: $(authdir)/sia.c $(AUTHDEP) + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(authdir)/sia.c + +# Command dependencies (sudoreplay, testsudoers, visudo) +check_iolog_path.o: $(srcdir)/regress/iolog_path/check_iolog_path.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/regress/iolog_path/check_iolog_path.c +error.o: $(top_srcdir)/src/error.c $(incdir)/error.h $(incdir)/missing.h $(top_builddir)/config.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(top_srcdir)/src/error.c +find_path.o: find_path.lo +getdate.o: $(devdir)/getdate.c $(incdir)/missing.h $(top_builddir)/config.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(devdir)/getdate.c +goodpath.o: goodpath.lo +interfaces.o: interfaces.lo +net_ifs.o: $(top_srcdir)/src/net_ifs.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(top_srcdir)/src/net_ifs.c +sudoreplay.o: $(srcdir)/sudoreplay.c $(incdir)/alloc.h $(incdir)/missing.h $(incdir)/error.h $(incdir)/missing.h $(top_builddir)/config.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/sudoreplay.c +check_fill.o: $(srcdir)/regress/parser/check_fill.c + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/regress/parser/check_fill.c +testsudoers.o: $(srcdir)/testsudoers.c $(SUDODEP) $(srcdir)/parse.h $(incdir)/list.h $(srcdir)/interfaces.h $(devdir)/gram.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/testsudoers.c +tsgetgrpw.o: $(srcdir)/tsgetgrpw.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/tsgetgrpw.c +visudo.o: $(srcdir)/visudo.c $(SUDODEP) $(devdir)/gram.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/visudo.c + +pre-install: + @if test -r $(DESTDIR)$(sudoersdir)/sudoers; then \ + echo "Checking existing sudoers file for syntax errors."; \ + ./visudo -c -f $(DESTDIR)$(sudoersdir)/sudoers; \ + fi + +install: install-dirs install-plugin install-binaries install-sudoers install-doc + +install-dirs: + $(SHELL) $(top_srcdir)/mkinstalldirs $(DESTDIR)$(plugindir) \ + $(DESTDIR)$(visudodir) $(DESTDIR)$(replaydir) \ + $(DESTDIR)$(sudoersdir) $(DESTDIR)$(docdir) + $(SHELL) $(top_srcdir)/mkinstalldirs -m 0700 $(DESTDIR)$(timedir) + +install-binaries: visudo sudoreplay install-dirs + $(INSTALL) -b~ -O $(install_uid) -G $(install_gid) -M 0111 sudoreplay $(DESTDIR)$(replaydir)/sudoreplay + $(INSTALL) -b~ -O $(install_uid) -G $(install_gid) -M 0111 visudo $(DESTDIR)$(visudodir)/visudo + +install-includes: + +install-doc: install-dirs + @LDAP@$(INSTALL) -O $(install_uid) -G $(install_gid) -M 0555 $(srcdir)/sudoers2ldif $(DESTDIR)$(docdir) + +install-plugin: sudoers.la install-dirs + $(INSTALL) -b~ -O $(install_uid) -G $(install_gid) -M 0755 .libs/sudoers$(soext) $(DESTDIR)$(plugindir) + +install-sudoers: install-dirs + $(INSTALL) -d -O $(sudoers_uid) -G $(sudoers_gid) -M 0750 \ + $(DESTDIR)$(sudoersdir)/sudoers.d + test -r $(DESTDIR)$(sudoersdir)/sudoers || \ + $(INSTALL) -O $(sudoers_uid) -G $(sudoers_gid) -M $(sudoers_mode) \ + sudoers $(DESTDIR)$(sudoersdir)/sudoers + +uninstall: + -rm -f $(DESTDIR)$(plugindir)/sudoers$(soext) + -rm -f $(DESTDIR)$(replaydir)/sudoreplay + -rm -f $(DESTDIR)$(visudodir)/visudo + -cmp $(DESTDIR)$(sudoersdir)/sudoers $(srcdir)/sudoers >/dev/null && \ + rm -f $(DESTDIR)$(sudoersdir)/sudoers + +check: $(TEST_PROGS) visudo testsudoers + @-rval=0; \ + ./check_iolog_path $(srcdir)/regress/iolog_path/data; \ + rval=`expr $$rval + $$?`; \ + ./check_fill; \ + rval=`expr $$rval + $$?`; \ + passed=0; failed=0; total=0; \ + for t in $(srcdir)/regress/sudoers/*.in; do \ + dir=`dirname $$t`; \ + dirbase=`basename $$dir`; \ + base=`basename $$t .in`; \ + out="$${base}.out"; \ + toke="$${base}.toke"; \ + ./testsudoers -dt <$$t >$$out 2>$$toke; \ + if cmp $$out $$dir/$$out.ok >/dev/null; then \ + passed=`expr $$passed + 1`; \ + echo "$$dirbase/$$base (parse): OK"; \ + else \ + failed=`expr $$failed + 1`; \ + echo "$$dirbase/$$base: FAIL"; \ + diff $$out $$dir/$$out.ok; \ + fi; \ + total=`expr $$total + 1`; \ + if cmp $$toke $$dir/$$toke.ok >/dev/null; then \ + passed=`expr $$passed + 1`; \ + echo "$$dirbase/$$base (toke): OK"; \ + else \ + failed=`expr $$failed + 1`; \ + echo "$$dirbase/$$base (toke): FAIL"; \ + diff $$out $$dir/$$out.ok; \ + fi; \ + total=`expr $$total + 1`; \ + done; \ + echo "$$dirbase: $$passed/$$total tests passed; $$failed/$$total tests failed"; \ + rval=$$failed; passed=0; failed=0; total=0; \ + for t in $(srcdir)/regress/*/*.sh; do \ + dir=`dirname $$t`; \ + dirbase=`basename $$dir`; \ + base=`basename $$t .sh`; \ + out="$${base}.out"; \ + err="$${base}.err"; \ + $(SHELL) $$t >$$out 2>$$err; \ + if cmp $$out $$dir/$$out.ok >/dev/null; then \ + passed=`expr $$passed + 1`; \ + echo "$$dirbase/$$base: OK"; \ + else \ + failed=`expr $$failed + 1`; \ + echo "$$dirbase/$$base: FAIL"; \ + diff $$out $$dir/$$out.ok; \ + fi; \ + total=`expr $$total + 1`; \ + if test -s $$dir/$$err.ok; then \ + if cmp $$err $$dir/$$err.ok >/dev/null; then \ + passed=`expr $$passed + 1`; \ + echo "$$dirbase/$$base (stderr): OK"; \ + else \ + failed=`expr $$failed + 1`; \ + echo "$$dirbase/$$base (stderr): FAIL"; \ + diff $$out $$dir/$$out.ok; \ + fi; \ + total=`expr $$total + 1`; \ + elif test -s $$err; then \ + cat $$err 1>&2; \ + fi; \ + done; \ + echo "$$dirbase: $$passed/$$total tests passed; $$failed/$$total tests failed"; \ + rval=`expr $$rval + $$failed`; exit $$rval + +clean: + -$(LIBTOOL) --mode=clean rm -f $(PROGS) *.lo *.o *.la *.a stamp-* core *.core core.* *.out + +mostlyclean: clean + +distclean: clean + -rm -rf Makefile sudoers sudoers.lo .libs $(LINKS) + +clobber: distclean + +realclean: distclean + rm -f TAGS tags + +cleandir: realclean diff --git a/aixcrypt.exp b/plugins/sudoers/aixcrypt.exp similarity index 100% rename from aixcrypt.exp rename to plugins/sudoers/aixcrypt.exp diff --git a/alias.c b/plugins/sudoers/alias.c similarity index 90% rename from alias.c rename to plugins/sudoers/alias.c index 238830c..274b446 100644 --- a/alias.c +++ b/plugins/sudoers/alias.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2005, 2007-2010 + * Copyright (c) 2004-2005, 2007-2011 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -40,7 +40,7 @@ # include #endif /* HAVE_UNISTD_H */ -#include "sudo.h" +#include "sudoers.h" #include "parse.h" #include "redblack.h" #include @@ -56,8 +56,7 @@ unsigned int alias_seqno; * Aliases are sorted by name with the type used as a tie-breaker. */ int -alias_compare(v1, v2) - const void *v1, *v2; +alias_compare(const void *v1, const void *v2) { const struct alias *a1 = (const struct alias *)v1; const struct alias *a2 = (const struct alias *)v2; @@ -77,9 +76,7 @@ alias_compare(v1, v2) * Returns a pointer to the alias structure or NULL if not found. */ struct alias * -alias_find(name, type) - char *name; - int type; +alias_find(char *name, int type) { struct alias key; struct rbnode *node; @@ -106,10 +103,7 @@ alias_find(name, type) * Returns NULL on success and an error string on failure. */ char * -alias_add(name, type, members) - char *name; - int type; - struct member *members; +alias_add(char *name, int type, struct member *members) { static char errbuf[512]; struct alias *a; @@ -131,9 +125,7 @@ alias_add(name, type, members) * Apply a function to each alias entry and pass in a cookie. */ void -alias_apply(func, cookie) - int (*func) __P((void *, void *)); - void *cookie; +alias_apply(int (*func)(void *, void *), void *cookie) { rbapply(aliases, func, cookie, inorder); } @@ -142,7 +134,7 @@ alias_apply(func, cookie) * Returns TRUE if there are no aliases, else FALSE. */ int -no_aliases() +no_aliases(void) { return rbisempty(aliases); } @@ -151,8 +143,7 @@ no_aliases() * Free memory used by an alias struct and its members. */ void -alias_free(v) - void *v; +alias_free(void *v) { struct alias *a = (struct alias *)v; struct member *m; @@ -177,9 +168,7 @@ alias_free(v) * Find the named alias, remove it from the tree and return it. */ struct alias * -alias_remove(name, type) - char *name; - int type; +alias_remove(char *name, int type) { struct rbnode *node; struct alias key; @@ -192,7 +181,7 @@ alias_remove(name, type) } void -init_aliases() +init_aliases(void) { if (aliases != NULL) rbdestroy(aliases, alias_free); diff --git a/audit.c b/plugins/sudoers/audit.c similarity index 76% rename from audit.c rename to plugins/sudoers/audit.c index 15ac8ee..2cb1130 100644 --- a/audit.c +++ b/plugins/sudoers/audit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Todd C. Miller + * Copyright (c) 2009-2010 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -26,11 +26,7 @@ # include # endif #endif /* STDC_HEADERS */ -#ifdef __STDC__ -# include -#else -# include -#endif +#include #include "missing.h" #include "logging.h" @@ -43,12 +39,7 @@ #endif void -#ifdef __STDC__ audit_success(char *exec_args[]) -#else -audit_success(exec_args) - const char *exec_args[]; -#endif { #ifdef HAVE_BSM_AUDIT bsm_audit_success(exec_args); @@ -59,22 +50,11 @@ audit_success(exec_args) } void -#ifdef __STDC__ -audit_failure(char *exec_args[], char const *const fmt, ...) -#else -audit_failure(exec_args, fmt, va_alist) - const char *exec_args[]; - char const *const fmt; - va_dcl -#endif +audit_failure(char **exec_args, char const *const fmt, ...) { va_list ap; -#ifdef __STDC__ va_start(ap, fmt); -#else - va_start(ap); -#endif #ifdef HAVE_BSM_AUDIT bsm_audit_failure(exec_args, fmt, ap); #endif diff --git a/auth/API b/plugins/sudoers/auth/API similarity index 65% rename from auth/API rename to plugins/sudoers/auth/API index fd183fe..24bd510 100644 --- a/auth/API +++ b/plugins/sudoers/auth/API @@ -7,15 +7,17 @@ Purpose: to provide a simple API for authentication methods that The sudo_auth struct looks like this: typedef struct sudo_auth { - short flags; /* various flags, see below */ - short status; /* status from verify routine */ + int flags; /* various flags, see below */ + int status; /* status from verify routine */ char *name; /* name of the method in string form */ void *data; /* method-specific data pointer */ - int (*init) __P((struct passwd *pw, char **prompt, sudo_auth *auth)); - int (*setup) __P((struct passwd *pw, char **prompt, sudo_auth *auth)); - int (*verify) __P((struct passwd *pw, char *p, sudo_auth *auth)); - int (*cleanup) __P((struct passwd *pw, sudo_auth *auth)); + int (*init)(struct passwd *pw, char **prompt, sudo_auth *auth); + int (*setup)(struct passwd *pw, char **prompt, sudo_auth *auth); + int (*verify)(struct passwd *pw, char *p, sudo_auth *auth); + int (*cleanup)(struct passwd *pw, sudo_auth *auth); + int (*begin_session)(struct passwd *pw, sudo_auth *auth); + int (*end_session)(sudo_auth *auth); } sudo_auth; The variables in the struct are as follows: @@ -34,10 +36,11 @@ Possible values of sudo_auth.flags: FLAG_USER Whether or not the auth functions should run with the euid of the invoking user instead of 0. - FLAG_CONFIGURED If set then the auth method is assumed to have been - configured successfully. All auth methods start out - with this set. If an "init" or "setup" function - fails, this bit is cleared. + FLAG_DISABLED Set if an "init" or "setup" function fails. + + FLAG_STANDALONE If set, this indicates that the method must + be the only auth method configured, and that + it will prompt for the password itself. FLAG_ONEANDONLY If set, this indicates that the method is the only one in use. Can be used by auth functions @@ -97,32 +100,23 @@ Adding a new authentication method: Each method should live in its own file. Add prototypes for the functions in sudo_auth.h. -If this is a standalone method, add it to the standalone #if cascade -in sudo_auth.h. For instance, for a method, ``fooauth'', add: - -#elif defined(HAVE_FOOAUTH) -# define AUTH_STANDALONE \ - AUTH_ENTRY(0, "foo", \ - foo_init, foo_setup, foo_verify, foo_cleanup) - -If the method needs to run as the user, not root, replace the first -parameter to AUTH_ENTRY (0) with FLAG_USER. If you don't have a -init/setup/cleanup routine, just use a NULL for that field. +Add the method to the ``auth_switch'' in sudo_auth.c. Note that +standalone methods must go first. If ``fooauth'' is a normal auth +method, its entry would look like: -For a normal authentication method, add it to the ``auth_switch'' in -sudo_auth.c. If ``fooauth'' is a normal auth method, its entry -would look like: +#ifdef HAVE_FOOAUTH +AUTH_ENTRY("foo", 0, foo_init, foo_setup, foo_verify, + foo_cleanup, foo_begin_session, foo_end_session) +#endif -# ifdef HAVE_FOOAUTH - AUTH_ENTRY(0, "foo", foo_init, foo_setup, foo_verify, foo_cleanup) -# endif +If this is a standalone method, it would be: -Again, if the method doesn't need to run as root, replace the 0 with -FLAG_USER. Likewise, if you don't have a init/setup/cleanup routine, -just use a NULL for that field. +#ifdef HAVE_FOOAUTH +AUTH_ENTRY("foo", FLAG_STANDALONE, foo_init, foo_setup, foo_verify, + foo_cleanup, foo_begin_session, foo_end_session) +#endif -NOTE: You should not make a method both ``standalone'' and - ``normal''. Just use the --without-passwd configure argument - to disable passwd/shadow file checking and then have your - auth routines check the FLAG_ONEANDONLY flag to see if - they are running standalone and act accordingly. +If the method needs to run as the user, not root, add FLAG_USER to +the second argument in the AUTH_ENTRY line. If you don't have an +init/setup/cleanup/begin/end routine, just use a NULL for that +field. diff --git a/auth/afs.c b/plugins/sudoers/auth/afs.c similarity index 93% rename from auth/afs.c rename to plugins/sudoers/auth/afs.c index 393605a..389bd9d 100644 --- a/auth/afs.c +++ b/plugins/sudoers/auth/afs.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2001-2005, 2007, 2010 + * Copyright (c) 1999, 2001-2005, 2007, 2010-2011 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -46,14 +46,11 @@ #include #include -#include "sudo.h" +#include "sudoers.h" #include "sudo_auth.h" int -afs_verify(pw, pass, auth) - struct passwd *pw; - char *pass; - sudo_auth *auth; +afs_verify(struct passwd *pw, char *pass, sudo_auth *auth) { struct ktc_encryptionKey afs_key; struct ktc_token afs_token; diff --git a/auth/aix_auth.c b/plugins/sudoers/auth/aix_auth.c similarity index 85% rename from auth/aix_auth.c rename to plugins/sudoers/auth/aix_auth.c index fe65b0b..9f54f91 100644 --- a/auth/aix_auth.c +++ b/plugins/sudoers/auth/aix_auth.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005, 2007-2010 Todd C. Miller + * Copyright (c) 1999-2005, 2007-2011 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -41,9 +41,8 @@ # include #endif /* HAVE_UNISTD_H */ #include -#include -#include "sudo.h" +#include "sudoers.h" #include "sudo_auth.h" /* @@ -51,17 +50,14 @@ * http://publib16.boulder.ibm.com/doc_link/en_US/a_doc_lib/libs/basetrf1/authenticate.htm */ int -aixauth_verify(pw, prompt, auth) - struct passwd *pw; - char *prompt; - sudo_auth *auth; +aixauth_verify(struct passwd *pw, char *prompt, sudo_auth *auth) { char *pass; char *message = NULL; int reenter = 1; int rval = AUTH_FAILURE; - pass = tgetpass(prompt, def_passwd_timeout * 60, tgetpass_flags); + pass = auth_getpass(prompt, def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF); if (pass) { /* XXX - should probably print message on failure. */ if (authenticate(pw->pw_name, pass, &reenter, &message) == 0) @@ -73,9 +69,7 @@ aixauth_verify(pw, prompt, auth) } int -aixauth_cleanup(pw, auth) - struct passwd *pw; - sudo_auth *auth; +aixauth_cleanup(struct passwd *pw, sudo_auth *auth) { /* Unset AUTHSTATE as it may not be correct for the runas user. */ unsetenv("AUTHSTATE"); diff --git a/auth/bsdauth.c b/plugins/sudoers/auth/bsdauth.c similarity index 88% rename from auth/bsdauth.c rename to plugins/sudoers/auth/bsdauth.c index 727df13..f70e424 100644 --- a/auth/bsdauth.c +++ b/plugins/sudoers/auth/bsdauth.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2005, 2007-2008, 2010 + * Copyright (c) 2000-2005, 2007-2008, 2010-2011 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -48,16 +48,13 @@ #include #include -#include "sudo.h" +#include "sudoers.h" #include "sudo_auth.h" extern char *login_style; /* from sudo.c */ int -bsdauth_init(pw, promptp, auth) - struct passwd *pw; - char **promptp; - sudo_auth *auth; +bsdauth_init(struct passwd *pw, char **promptp, sudo_auth *auth) { static auth_session_t *as; extern login_cap_t *lc; /* from sudo.c */ @@ -89,10 +86,7 @@ bsdauth_init(pw, promptp, auth) } int -bsdauth_verify(pw, prompt, auth) - struct passwd *pw; - char *prompt; - sudo_auth *auth; +bsdauth_verify(struct passwd *pw, char *prompt, sudo_auth *auth) { char *pass; char *s; @@ -114,9 +108,9 @@ bsdauth_verify(pw, prompt, auth) * S/Key. */ if ((s = auth_challenge(as)) == NULL) { - pass = tgetpass(prompt, def_passwd_timeout * 60, tgetpass_flags); + pass = auth_getpass(prompt, def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF); } else { - pass = tgetpass(s, def_passwd_timeout * 60, tgetpass_flags); + pass = auth_getpass(prompt, def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF); if (pass && *pass == '\0') { if ((prompt = strrchr(s, '\n'))) prompt++; @@ -131,8 +125,8 @@ bsdauth_verify(pw, prompt, auth) while (isspace(prompt[len]) || prompt[len] == ':') prompt[len--] = '\0'; easprintf(&s, "%s [echo on]: ", prompt); - pass = tgetpass(s, def_passwd_timeout * 60, - tgetpass_flags | TGP_ECHO); + pass = auth_getpass(prompt, def_passwd_timeout * 60, + SUDO_CONV_PROMPT_ECHO_ON); free(s); } } @@ -157,9 +151,7 @@ bsdauth_verify(pw, prompt, auth) } int -bsdauth_cleanup(pw, auth) - struct passwd *pw; - sudo_auth *auth; +bsdauth_cleanup(struct passwd *pw, sudo_auth *auth) { auth_session_t *as = (auth_session_t *) auth->data; diff --git a/auth/dce.c b/plugins/sudoers/auth/dce.c similarity index 95% rename from auth/dce.c rename to plugins/sudoers/auth/dce.c index 3333a72..a4ffd34 100644 --- a/auth/dce.c +++ b/plugins/sudoers/auth/dce.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 1998-2005, 2010 + * Copyright (c) 1996, 1998-2005, 2010-2011 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -61,16 +61,13 @@ #include #include /* required to call dce_error_inq_text routine */ -#include "sudo.h" +#include "sudoers.h" #include "sudo_auth.h" -static int check_dce_status __P((error_status_t, char *)); +static int check_dce_status(error_status_t, char *); int -dce_verify(pw, plain_pw, auth) - struct passwd *pw; - char *plain_pw; - sudo_auth *auth; +dce_verify(struct passwd *pw, char *plain_pw, sudo_auth *auth) { struct passwd temp_pw; sec_passwd_rec_t password_rec; @@ -187,9 +184,7 @@ dce_verify(pw, plain_pw, auth) /* Returns 0 for DCE "ok" status, 1 otherwise */ static int -check_dce_status(input_status, comment) - error_status_t input_status; - char *comment; +check_dce_status(error_status_t input_status, char *comment) { int error_stat; unsigned char error_string[dce_c_error_string_len]; diff --git a/auth/fwtk.c b/plugins/sudoers/auth/fwtk.c similarity index 86% rename from auth/fwtk.c rename to plugins/sudoers/auth/fwtk.c index f1c164e..a3a5cff 100644 --- a/auth/fwtk.c +++ b/plugins/sudoers/auth/fwtk.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005, 2008, 2010 + * Copyright (c) 1999-2005, 2008, 2010-2011 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -46,14 +46,11 @@ #include #include -#include "sudo.h" +#include "sudoers.h" #include "sudo_auth.h" int -fwtk_init(pw, promptp, auth) - struct passwd *pw; - char **promptp; - sudo_auth *auth; +fwtk_init(struct passwd *pw, char **promptp, sudo_auth *auth) { static Cfg *confp; /* Configuration entry struct */ char resp[128]; /* Response from the server */ @@ -82,10 +79,7 @@ fwtk_init(pw, promptp, auth) } int -fwtk_verify(pw, prompt, auth) - struct passwd *pw; - char *prompt; - sudo_auth *auth; +fwtk_verify(struct passwd *pw, char *prompt, sudo_auth *auth) { char *pass; /* Password from the user */ char buf[SUDO_PASS_MAX + 12]; /* General prupose buffer */ @@ -103,16 +97,17 @@ restart: /* Get the password/response from the user. */ if (strncmp(resp, "challenge ", 10) == 0) { (void) snprintf(buf, sizeof(buf), "%s\nResponse: ", &resp[10]); - pass = tgetpass(buf, def_passwd_timeout * 60, tgetpass_flags); + pass = auth_getpass(buf, def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF); if (pass && *pass == '\0') { - pass = tgetpass("Response [echo on]: ", - def_passwd_timeout * 60, tgetpass_flags | TGP_ECHO); + pass = auth_getpass("Response [echo on]: ", + def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_ON); } } else if (strncmp(resp, "chalnecho ", 10) == 0) { - pass = tgetpass(&resp[10], def_passwd_timeout * 60, tgetpass_flags); + pass = auth_getpass(&resp[10], def_passwd_timeout * 60, + SUDO_CONV_PROMPT_ECHO_OFF); } else if (strncmp(resp, "password", 8) == 0) { - pass = tgetpass(prompt, def_passwd_timeout * 60, - tgetpass_flags); + pass = auth_getpass(prompt, def_passwd_timeout * 60, + SUDO_CONV_PROMPT_ECHO_OFF); } else if (strncmp(resp, "display ", 8) == 0) { fprintf(stderr, "%s\n", &resp[8]); strlcpy(buf, "response dummy", sizeof(buf)); @@ -149,9 +144,7 @@ done: } int -fwtk_cleanup(pw, auth) - struct passwd *pw; - sudo_auth *auth; +fwtk_cleanup(struct passwd *pw, sudo_auth *auth) { auth_close(); diff --git a/auth/kerb4.c b/plugins/sudoers/auth/kerb4.c similarity index 91% rename from auth/kerb4.c rename to plugins/sudoers/auth/kerb4.c index 883035d..176d6a7 100644 --- a/auth/kerb4.c +++ b/plugins/sudoers/auth/kerb4.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005, 2007, 2010 + * Copyright (c) 1999-2005, 2007, 2010-2011 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -44,14 +44,11 @@ #include #include -#include "sudo.h" +#include "sudoers.h" #include "sudo_auth.h" int -kerb4_init(pw, promptp, auth) - struct passwd *pw; - char **promptp; - sudo_auth *auth; +kerb4_init(struct passwd *pw, char **promptp, sudo_auth *auth) { static char realm[REALM_SZ]; @@ -70,10 +67,7 @@ kerb4_init(pw, promptp, auth) } int -kerb4_verify(pw, pass, auth) - struct passwd *pw; - char *pass; - sudo_auth *auth; +kerb4_verify(struct passwd *pw, char *pass, sudo_auth *auth) { char tkfile[sizeof(_PATH_SUDO_TIMEDIR) + 4 + MAX_UID_T_LEN]; char *realm = (char *) auth->data; diff --git a/auth/kerb5.c b/plugins/sudoers/auth/kerb5.c similarity index 91% rename from auth/kerb5.c rename to plugins/sudoers/auth/kerb5.c index 4ce04aa..38d84cb 100644 --- a/auth/kerb5.c +++ b/plugins/sudoers/auth/kerb5.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005, 2007-2008, 2010 + * Copyright (c) 1999-2005, 2007-2008, 2010-2011 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -50,7 +50,7 @@ #include #endif -#include "sudo.h" +#include "sudoers.h" #include "sudo_auth.h" #ifdef HAVE_HEIMDAL @@ -61,7 +61,7 @@ #endif #ifndef HAVE_KRB5_VERIFY_USER -static int verify_krb_v5_tgt __P((krb5_context, krb5_creds *, char *)); +static int verify_krb_v5_tgt(krb5_context, krb5_creds *, char *); #endif static struct _sudo_krb5_data { krb5_context sudo_context; @@ -72,9 +72,8 @@ typedef struct _sudo_krb5_data *sudo_krb5_datap; #ifndef HAVE_KRB5_GET_INIT_CREDS_OPT_ALLOC static krb5_error_code -krb5_get_init_creds_opt_alloc(context, opts) - krb5_context context; - krb5_get_init_creds_opt **opts; +krb5_get_init_creds_opt_alloc(krb5_context context, + krb5_get_init_creds_opt **opts) { *opts = emalloc(sizeof(krb5_get_init_creds_opt)); krb5_get_init_creds_opt_init(*opts); @@ -82,18 +81,14 @@ krb5_get_init_creds_opt_alloc(context, opts) } static void -krb5_get_init_creds_opt_free(opts) - krb5_get_init_creds_opt *opts; +krb5_get_init_creds_opt_free(krb5_get_init_creds_opt *opts) { free(opts); } #endif int -kerb5_init(pw, promptp, auth) - struct passwd *pw; - char **promptp; - sudo_auth *auth; +kerb5_init(struct passwd *pw, char **promptp, sudo_auth *auth) { krb5_context sudo_context; krb5_ccache ccache; @@ -157,10 +152,7 @@ kerb5_init(pw, promptp, auth) #ifdef HAVE_KRB5_VERIFY_USER int -kerb5_verify(pw, pass, auth) - struct passwd *pw; - char *pass; - sudo_auth *auth; +kerb5_verify(struct passwd *pw, char *pass, sudo_auth *auth) { krb5_context sudo_context; krb5_principal princ; @@ -176,10 +168,7 @@ kerb5_verify(pw, pass, auth) } #else int -kerb5_verify(pw, pass, auth) - struct passwd *pw; - char *pass; - sudo_auth *auth; +kerb5_verify(struct passwd *pw, char *pass, sudo_auth *auth) { krb5_context sudo_context; krb5_principal princ; @@ -248,9 +237,7 @@ done: #endif int -kerb5_cleanup(pw, auth) - struct passwd *pw; - sudo_auth *auth; +kerb5_cleanup(struct passwd *pw, sudo_auth *auth) { krb5_context sudo_context; krb5_principal princ; @@ -281,10 +268,7 @@ kerb5_cleanup(pw, auth) * Returns 0 for successful authentication, non-zero for failure. */ static int -verify_krb_v5_tgt(sudo_context, cred, auth_name) - krb5_context sudo_context; - krb5_creds *cred; - char *auth_name; /* For error reporting */ +verify_krb_v5_tgt(krb5_context sudo_context, krb5_creds *cred, char *auth_name) { krb5_error_code error; krb5_principal server; diff --git a/auth/pam.c b/plugins/sudoers/auth/pam.c similarity index 86% rename from auth/pam.c rename to plugins/sudoers/auth/pam.c index 265de36..4ff4eed 100644 --- a/auth/pam.c +++ b/plugins/sudoers/auth/pam.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005, 2007-2010 Todd C. Miller + * Copyright (c) 1999-2005, 2007-2011 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -58,7 +58,7 @@ # endif #endif -#include "sudo.h" +#include "sudoers.h" #include "sudo_auth.h" /* Only OpenPAM and Linux PAM use const qualifiers. */ @@ -69,8 +69,8 @@ # define PAM_CONST #endif -static int sudo_conv __P((int, PAM_CONST struct pam_message **, - struct pam_response **, void *)); +static int converse(int, PAM_CONST struct pam_message **, + struct pam_response **, void *); static char *def_prompt = "Password:"; static int gotintr; @@ -78,13 +78,10 @@ static int gotintr; #define PAM_DATA_SILENT 0 #endif -static pam_handle_t *pamh; /* global due to pam_prep_user() */ +static pam_handle_t *pamh; int -pam_init(pw, promptp, auth) - struct passwd *pw; - char **promptp; - sudo_auth *auth; +pam_init(struct passwd *pw, char **promptp, sudo_auth *auth) { static struct pam_conv pam_conv; static int pam_status; @@ -92,14 +89,13 @@ pam_init(pw, promptp, auth) /* Initial PAM setup */ if (auth != NULL) auth->data = (void *) &pam_status; - pam_conv.conv = sudo_conv; + pam_conv.conv = converse; #ifdef HAVE_PAM_LOGIN if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) pam_status = pam_start("sudo-i", pw->pw_name, &pam_conv, &pamh); else #endif pam_status = pam_start("sudo", pw->pw_name, &pam_conv, &pamh); - if (pam_status != PAM_SUCCESS) { log_error(USE_ERRNO|NO_EXIT|NO_MAIL, "unable to initialize PAM"); return AUTH_FATAL; @@ -128,15 +124,12 @@ pam_init(pw, promptp, auth) } int -pam_verify(pw, prompt, auth) - struct passwd *pw; - char *prompt; - sudo_auth *auth; +pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth) { const char *s; int *pam_status = (int *) auth->data; - def_prompt = prompt; /* for sudo_conv */ + def_prompt = prompt; /* for converse */ /* PAM_SILENT prevents the authentication service from generating output. */ *pam_status = pam_authenticate(pamh, PAM_SILENT); @@ -188,13 +181,11 @@ pam_verify(pw, prompt, auth) } int -pam_cleanup(pw, auth) - struct passwd *pw; - sudo_auth *auth; +pam_cleanup(struct passwd *pw, sudo_auth *auth) { int *pam_status = (int *) auth->data; - /* If successful, we can't close the session until pam_prep_user() */ + /* If successful, we can't close the session until pam_end_session() */ if (auth->status == AUTH_SUCCESS) return AUTH_SUCCESS; @@ -203,10 +194,22 @@ pam_cleanup(pw, auth) } int -pam_begin_session(pw) - struct passwd *pw; +pam_begin_session(struct passwd *pw, sudo_auth *auth) { - int status = PAM_SUCCESS; + int status = PAM_SUCCESS; + + /* + * If there is no valid user we cannot open a PAM session. + * This is not an error as sudo can run commands with arbitrary + * uids, it just means we are done from a session management standpoint. + */ + if (pw == NULL) { + if (pamh != NULL) { + (void) pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT); + pamh = NULL; + } + goto done; + } /* If the user did not have to authenticate there is no pam handle yet. */ if (pamh == NULL) @@ -230,22 +233,24 @@ pam_begin_session(pw) #ifndef NO_PAM_SESSION status = pam_open_session(pamh, 0); - if (status != PAM_SUCCESS) { + if (status != PAM_SUCCESS) { (void) pam_end(pamh, status | PAM_DATA_SILENT); pamh = NULL; } #endif + +done: return status == PAM_SUCCESS ? AUTH_SUCCESS : AUTH_FAILURE; } int -pam_end_session() +pam_end_session(sudo_auth *auth) { int status = PAM_SUCCESS; - if (pamh != NULL) { + if (pamh) { #ifndef NO_PAM_SESSION - (void) pam_close_session(pamh, 0); + (void) pam_close_session(pamh, PAM_SILENT); #endif status = pam_end(pamh, PAM_SUCCESS | PAM_DATA_SILENT); } @@ -257,27 +262,24 @@ pam_end_session() * XXX - does not handle PAM_BINARY_PROMPT */ static int -sudo_conv(num_msg, msg, response, appdata_ptr) - int num_msg; - PAM_CONST struct pam_message **msg; - struct pam_response **response; - void *appdata_ptr; +converse(int num_msg, PAM_CONST struct pam_message **msg, + struct pam_response **response, void *appdata_ptr) { struct pam_response *pr; PAM_CONST struct pam_message *pm; const char *prompt; char *pass; - int n, flags, std_prompt; + int n, type, std_prompt; if ((*response = malloc(num_msg * sizeof(struct pam_response))) == NULL) return PAM_SYSTEM_ERR; zero_bytes(*response, num_msg * sizeof(struct pam_response)); for (pr = *response, pm = *msg, n = num_msg; n--; pr++, pm++) { - flags = tgetpass_flags; + type = SUDO_CONV_PROMPT_ECHO_OFF; switch (pm->msg_style) { case PAM_PROMPT_ECHO_ON: - SET(flags, TGP_ECHO); + type = SUDO_CONV_PROMPT_ECHO_ON; case PAM_PROMPT_ECHO_OFF: prompt = def_prompt; @@ -303,7 +305,7 @@ sudo_conv(num_msg, msg, response, appdata_ptr) prompt = pm->msg; #endif /* Read the password unless interrupted. */ - pass = tgetpass(prompt, def_passwd_timeout * 60, flags); + pass = auth_getpass(prompt, def_passwd_timeout * 60, type); if (pass == NULL) { /* We got ^C instead of a password; abort quickly. */ if (errno == EINTR) diff --git a/auth/passwd.c b/plugins/sudoers/auth/passwd.c similarity index 91% rename from auth/passwd.c rename to plugins/sudoers/auth/passwd.c index 8835c03..ee0e4d3 100644 --- a/auth/passwd.c +++ b/plugins/sudoers/auth/passwd.c @@ -1,6 +1,5 @@ /* - * Copyright (c) 1999-2005, 2010 - * Todd C. Miller + * Copyright (c) 1999-2005, 2010-2011 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -43,17 +42,14 @@ #endif /* HAVE_UNISTD_H */ #include -#include "sudo.h" +#include "sudoers.h" #include "sudo_auth.h" #define DESLEN 13 #define HAS_AGEINFO(p, l) (l == 18 && p[DESLEN] == ',') int -passwd_init(pw, promptp, auth) - struct passwd *pw; - char **promptp; - sudo_auth *auth; +passwd_init(struct passwd *pw, char **promptp, sudo_auth *auth) { #ifdef HAVE_SKEYACCESS if (skeyaccess(pw, user_tty, NULL, NULL) == 0) @@ -66,10 +62,7 @@ passwd_init(pw, promptp, auth) } int -passwd_verify(pw, pass, auth) - struct passwd *pw; - char *pass; - sudo_auth *auth; +passwd_verify(struct passwd *pw, char *pass, sudo_auth *auth) { char sav, *epass; char *pw_epasswd = auth->data; diff --git a/auth/rfc1938.c b/plugins/sudoers/auth/rfc1938.c similarity index 93% rename from auth/rfc1938.c rename to plugins/sudoers/auth/rfc1938.c index b0640e5..846b7b2 100644 --- a/auth/rfc1938.c +++ b/plugins/sudoers/auth/rfc1938.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994-1996, 1998-2005, 2010 + * Copyright (c) 1994-1996, 1998-2005, 2010-2011 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -46,7 +46,7 @@ #if defined(HAVE_SKEY) # include # define RFC1938 skey -# ifdef __NetBSD__ +# ifdef HAVE_RFC1938_SKEYCHALLENGE # define rfc1938challenge(a,b,c,d) skeychallenge((a),(b),(c),(d)) # else # define rfc1938challenge(a,b,c,d) skeychallenge((a),(b),(c)) @@ -59,14 +59,11 @@ # define rfc1938verify(a,b) opieverify((a),(b)) #endif -#include "sudo.h" +#include "sudoers.h" #include "sudo_auth.h" int -rfc1938_setup(pw, promptp, auth) - struct passwd *pw; - char **promptp; - sudo_auth *auth; +rfc1938_setup(struct passwd *pw, char **promptp, sudo_auth *auth) { char challenge[256]; static char *orig_prompt = NULL, *new_prompt = NULL; @@ -127,10 +124,7 @@ rfc1938_setup(pw, promptp, auth) } int -rfc1938_verify(pw, pass, auth) - struct passwd *pw; - char *pass; - sudo_auth *auth; +rfc1938_verify(struct passwd *pw, char *pass, sudo_auth *auth) { if (rfc1938verify((struct RFC1938 *) auth->data, pass) == 0) diff --git a/auth/secureware.c b/plugins/sudoers/auth/secureware.c similarity index 90% rename from auth/secureware.c rename to plugins/sudoers/auth/secureware.c index c1c43d0..221889d 100644 --- a/auth/secureware.c +++ b/plugins/sudoers/auth/secureware.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998-2005, 2010 Todd C. Miller + * Copyright (c) 1998-2005, 2010-2011 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -49,14 +49,11 @@ #endif /* __hpux */ #include -#include "sudo.h" +#include "sudoers.h" #include "sudo_auth.h" int -secureware_init(pw, promptp, auth) - struct passwd *pw; - char **promptp; - sudo_auth *auth; +secureware_init(struct passwd *pw, char **promptp, sudo_auth *auth) { #ifdef __alpha extern int crypt_type; @@ -71,10 +68,7 @@ secureware_init(pw, promptp, auth) } int -secureware_verify(pw, pass, auth) - struct passwd *pw; - char *pass; - sudo_auth *auth; +secureware_verify(struct passwd *pw, char *pass, sudo_auth *auth) { char *pw_epasswd = auth->data; #ifdef __alpha diff --git a/auth/securid.c b/plugins/sudoers/auth/securid.c similarity index 88% rename from auth/securid.c rename to plugins/sudoers/auth/securid.c index 83ff94c..bcea4e9 100644 --- a/auth/securid.c +++ b/plugins/sudoers/auth/securid.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005, 2007, 2010 + * Copyright (c) 1999-2005, 2007, 2010-2011 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -50,16 +50,13 @@ #include #include -#include "sudo.h" +#include "sudoers.h" #include "sudo_auth.h" union config_record configure; int -securid_init(pw, promptp, auth) - struct passwd *pw; - char **promptp; - sudo_auth *auth; +securid_init(struct passwd *pw, char **promptp, sudo_auth *auth) { static struct SD_CLIENT sd_dat; /* SecurID data block */ @@ -72,10 +69,7 @@ securid_init(pw, promptp, auth) } int -securid_setup(pw, promptp, auth) - struct passwd *pw; - char **promptp; - sudo_auth *auth; +securid_setup(struct passwd *pw, char **promptp, sudo_auth *auth) { struct SD_CLIENT *sd = (struct SD_CLIENT *) auth->data; @@ -91,10 +85,7 @@ securid_setup(pw, promptp, auth) } int -securid_verify(pw, pass, auth) - struct passwd *pw; - char *pass; - sudo_auth *auth; +securid_verify(struct passwd *pw, char *pass, sudo_auth *auth) { struct SD_CLIENT *sd = (struct SD_CLIENT *) auth->data; int rval; diff --git a/auth/securid5.c b/plugins/sudoers/auth/securid5.c similarity index 91% rename from auth/securid5.c rename to plugins/sudoers/auth/securid5.c index 6880c1a..9d0ed4f 100644 --- a/auth/securid5.c +++ b/plugins/sudoers/auth/securid5.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005, 2007, 2010 + * Copyright (c) 1999-2005, 2007, 2010-2011 * Todd C. Miller * Copyright (c) 2002 Michael Stroucken * @@ -52,7 +52,7 @@ #include #include -#include "sudo.h" +#include "sudoers.h" #include "sudo_auth.h" /* @@ -68,10 +68,7 @@ * success. */ int -securid_init(pw, promptp, auth) - struct passwd *pw; - char **promptp; - sudo_auth *auth; +securid_init(struct passwd *pw, char **promptp, sudo_auth *auth) { static SDI_HANDLE sd_dat; /* SecurID handle */ @@ -99,10 +96,7 @@ securid_init(pw, promptp, auth) * otherwise */ int -securid_setup(pw, promptp, auth) - struct passwd *pw; - char **promptp; - sudo_auth *auth; +securid_setup(struct passwd *pw, char **promptp, sudo_auth *auth) { SDI_HANDLE *sd = (SDI_HANDLE *) auth->data; int retval; @@ -152,16 +146,13 @@ securid_setup(pw, promptp, auth) * incorrect authentication, fatal on errors */ int -securid_verify(pw, pass, auth) - struct passwd *pw; - char *pass; - sudo_auth *auth; +securid_verify(struct passwd *pw, char *pass, sudo_auth *auth) { SDI_HANDLE *sd = (SDI_HANDLE *) auth->data; int rval; - pass = (char *) tgetpass("Enter your PASSCODE: ", - def_passwd_timeout * 60, tgetpass_flags); + pass = auth_getpass("Enter your PASSCODE: ", + def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF); /* Have ACE verify password */ switch (SD_Check(*sd, pass, pw->pw_name)) { @@ -192,11 +183,11 @@ securid_verify(pw, pass, auth) /* Sometimes (when current token close to expire?) ACE challenges for the next token displayed (entered without the PIN) */ - pass = (char *) tgetpass("\ + pass = auth_getpass("\ !!! ATTENTION !!!\n\ Wait for the token code to change, \n\ then enter the new token code.\n", \ - def_passwd_timeout * 60, tgetpass_flags); + def_passwd_timeout * 60, SUDO_CONV_PROMPT_ECHO_OFF); if (SD_Next(*sd, pass) == ACM_OK) { rval = AUTH_SUCCESS; diff --git a/auth/sia.c b/plugins/sudoers/auth/sia.c similarity index 77% rename from auth/sia.c rename to plugins/sudoers/auth/sia.c index 6c972c6..65c6653 100644 --- a/auth/sia.c +++ b/plugins/sudoers/auth/sia.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005, 2007, 2010 + * Copyright (c) 1999-2005, 2007, 2010-2011 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -46,24 +46,22 @@ #include #include -#include "sudo.h" +#include "sudoers.h" #include "sudo_auth.h" -static int sudo_collect __P((int, int, uchar_t *, int, prompt_t *)); +static int sudo_collect(int, int, uchar_t *, int, prompt_t *); static char *def_prompt; +static char **sudo_argv; +static int sudo_argc; /* * Collection routine (callback) for limiting the timeouts in SIA * prompts and (possibly) setting a custom prompt. */ static int -sudo_collect(timeout, rendition, title, nprompts, prompts) - int timeout; - int rendition; - uchar_t *title; - int nprompts; - prompt_t *prompts; +sudo_collect(int timeout, int rendition, uchar_t *title, int nprompts, + prompt_t *prompts) { switch (rendition) { case SIAFORM: @@ -87,17 +85,22 @@ sudo_collect(timeout, rendition, title, nprompts, prompts) } int -sia_setup(pw, promptp, auth) - struct passwd *pw; - char **promptp; - sudo_auth *auth; +sia_setup(struct passwd *pw, char **promptp, sudo_auth *auth) { SIAENTITY *siah = NULL; - extern int Argc; - extern char **Argv; + int i; + extern int NewArgc; + extern char **NewArgv; - if (sia_ses_init(&siah, Argc, Argv, NULL, pw->pw_name, ttyname(0), 1, NULL) - != SIASUCCESS) { + /* Rebuild argv for sia_ses_init() */ + sudo_argc = NewArgc + 1; + sudo_argv = emalloc2(sudo_argc + 1, sizeof(char *)); + sudo_argv[0] = "sudo"; + for (i = 0; i < NewArgc; i++) + sudo_argv[i + 1] = NewArgv[i]; + sudo_argv[sudo_argc] = NULL; + + if (sia_ses_init(&siah, sudo_argc, sudo_argv, NULL, pw->pw_name, user_ttypath, 1, NULL) != SIASUCCESS) { log_error(USE_ERRNO|NO_EXIT|NO_MAIL, "unable to initialize SIA session"); @@ -109,10 +112,7 @@ sia_setup(pw, promptp, auth) } int -sia_verify(pw, prompt, auth) - struct passwd *pw; - char *prompt; - sudo_auth *auth; +sia_verify(struct passwd *pw, char *prompt, sudo_auth *auth) { SIAENTITY *siah = (SIAENTITY *) auth->data; @@ -126,12 +126,11 @@ sia_verify(pw, prompt, auth) } int -sia_cleanup(pw, auth) - struct passwd *pw; - sudo_auth *auth; +sia_cleanup(struct passwd *pw, sudo_auth *auth) { SIAENTITY *siah = (SIAENTITY *) auth->data; (void) sia_ses_release(&siah); + efree(sudo_argv); return AUTH_SUCCESS; } diff --git a/plugins/sudoers/auth/sudo_auth.c b/plugins/sudoers/auth/sudo_auth.c new file mode 100644 index 0000000..fc69716 --- /dev/null +++ b/plugins/sudoers/auth/sudo_auth.c @@ -0,0 +1,339 @@ +/* + * Copyright (c) 1999-2005, 2008-2010 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ + +#include + +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#include +#include +#include + +#include "sudoers.h" +#include "sudo_auth.h" +#include "insults.h" + +static sudo_auth auth_switch[] = { +/* Standalone entries first */ +#ifdef HAVE_PAM + AUTH_ENTRY("pam", FLAG_STANDALONE, pam_init, NULL, pam_verify, pam_cleanup, pam_begin_session, pam_end_session) +#endif +#ifdef HAVE_SECURID + AUTH_ENTRY("SecurId", FLAG_STANDALONE, securid_init, securid_setup, securid_verify, NULL, NULL, NULL) +#endif +#ifdef HAVE_SIA_SES_INIT + AUTH_ENTRY("sia", FLAG_STANDALONE, NULL, sia_setup, sia_verify, sia_cleanup, NULL, NULL) +#endif +#ifdef HAVE_AIXAUTH + AUTH_ENTRY("aixauth", FLAG_STANDALONE, NULL, NULL, aixauth_verify, aixauth_cleanup, NULL, NULL) +#endif +#ifdef HAVE_FWTK + AUTH_ENTRY("fwtk", FLAG_STANDALONE, fwtk_init, NULL, fwtk_verify, fwtk_cleanup, NULL, NULL) +#endif +#ifdef HAVE_BSD_AUTH_H + AUTH_ENTRY("bsdauth", FLAG_STANDALONE, bsdauth_init, NULL, bsdauth_verify, bsdauth_cleanup, NULL, NULL) +#endif + +/* Non-standalone entries */ +#ifndef WITHOUT_PASSWD + AUTH_ENTRY("passwd", 0, passwd_init, NULL, passwd_verify, passwd_cleanup, NULL, NULL) +#endif +#if defined(HAVE_GETPRPWNAM) && !defined(WITHOUT_PASSWD) + AUTH_ENTRY("secureware", 0, secureware_init, NULL, secureware_verify, secureware_cleanup, NULL, NULL) +#endif +#ifdef HAVE_AFS + AUTH_ENTRY("afs", 0, NULL, NULL, afs_verify, NULL, NULL, NULL) +#endif +#ifdef HAVE_DCE + AUTH_ENTRY("dce", 0, NULL, NULL, dce_verify, NULL, NULL, NULL) +#endif +#ifdef HAVE_KERB4 + AUTH_ENTRY("kerb4", 0, kerb4_init, NULL, kerb4_verify, NULL, NULL, NULL) +#endif +#ifdef HAVE_KERB5 + AUTH_ENTRY("kerb5", 0, kerb5_init, NULL, kerb5_verify, kerb5_cleanup, NULL, NULL) +#endif +#ifdef HAVE_SKEY + AUTH_ENTRY("S/Key", 0, NULL, rfc1938_setup, rfc1938_verify, NULL, NULL, NULL) +#endif +#ifdef HAVE_OPIE + AUTH_ENTRY("OPIE", 0, NULL, rfc1938_setup, rfc1938_verify, NULL, NULL, NULL) +#endif + AUTH_ENTRY(NULL, 0, NULL, NULL, NULL, NULL, NULL, NULL) +}; + +extern char **NewArgv; /* XXX - for auditing */ + +static void pass_warn(void); + +int +verify_user(struct passwd *pw, char *prompt) +{ + int counter = def_passwd_tries + 1; + int success = AUTH_FAILURE; + int flags, status, standalone, rval; + char *p; + sudo_auth *auth; + sigaction_t sa, osa; + + /* Enable suspend during password entry. */ + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + sa.sa_handler = SIG_DFL; + (void) sigaction(SIGTSTP, &sa, &osa); + + /* Make sure we have at least one auth method. */ + if (auth_switch[0].name == NULL) { + audit_failure(NewArgv, "no authentication methods"); + log_error(0, "%s %s %s", + "There are no authentication methods compiled into sudo!", + "If you want to turn off authentication, use the", + "--disable-authentication configure option."); + return -1; + } + + /* Make sure we haven't mixed standalone and shared auth methods. */ + standalone = IS_STANDALONE(&auth_switch[0]); + if (standalone && auth_switch[1].name != NULL) { + audit_failure(NewArgv, "invalid authentication methods"); + log_error(0, "Invalid authentication methods compiled into sudo! " + "You cannot mix standalone and non-standalone authentication."); + return -1; + } + + /* Set FLAG_ONEANDONLY if there is only one auth method. */ + if (auth_switch[1].name == NULL) + SET(auth_switch[0].flags, FLAG_ONEANDONLY); + + /* Initialize auth methods and unconfigure the method if necessary. */ + for (auth = auth_switch; auth->name; auth++) { + if (auth->init && !IS_DISABLED(auth)) { + if (NEEDS_USER(auth)) + set_perms(PERM_USER); + + status = (auth->init)(pw, &prompt, auth); + if (status == AUTH_FAILURE) + SET(auth->flags, FLAG_DISABLED); + else if (status == AUTH_FATAL) { /* XXX log */ + audit_failure(NewArgv, "authentication failure"); + return -1; /* assume error msg already printed */ + } + + if (NEEDS_USER(auth)) + restore_perms(); + } + } + + while (--counter) { + /* Do any per-method setup and unconfigure the method if needed */ + for (auth = auth_switch; auth->name; auth++) { + if (auth->setup && !IS_DISABLED(auth)) { + if (NEEDS_USER(auth)) + set_perms(PERM_USER); + + status = (auth->setup)(pw, &prompt, auth); + if (status == AUTH_FAILURE) + SET(auth->flags, FLAG_DISABLED); + else if (status == AUTH_FATAL) {/* XXX log */ + audit_failure(NewArgv, "authentication failure"); + return -1; /* assume error msg already printed */ + } + + if (NEEDS_USER(auth)) + restore_perms(); + } + } + + /* Get the password unless the auth function will do it for us */ + if (standalone) { + p = prompt; + } else { + p = auth_getpass(prompt, def_passwd_timeout * 60, + SUDO_CONV_PROMPT_ECHO_OFF); + if (p == NULL) + break; + } + + /* Call authentication functions. */ + for (auth = auth_switch; auth->name; auth++) { + if (IS_DISABLED(auth)) + continue; + + if (NEEDS_USER(auth)) + set_perms(PERM_USER); + + success = auth->status = (auth->verify)(pw, p, auth); + + if (NEEDS_USER(auth)) + restore_perms(); + + if (auth->status != AUTH_FAILURE) + goto cleanup; + } + if (!standalone) + zero_bytes(p, strlen(p)); + pass_warn(); + } + +cleanup: + /* Call cleanup routines. */ + for (auth = auth_switch; auth->name; auth++) { + if (auth->cleanup && !IS_DISABLED(auth)) { + if (NEEDS_USER(auth)) + set_perms(PERM_USER); + + status = (auth->cleanup)(pw, auth); + if (status == AUTH_FATAL) { /* XXX log */ + audit_failure(NewArgv, "authentication failure"); + return -1; /* assume error msg already printed */ + } + + if (NEEDS_USER(auth)) + restore_perms(); + } + } + + switch (success) { + case AUTH_SUCCESS: + (void) sigaction(SIGTSTP, &osa, NULL); + rval = TRUE; + break; + case AUTH_INTR: + case AUTH_FAILURE: + if (counter != def_passwd_tries) { + if (def_mail_badpass || def_mail_always) + flags = 0; + else + flags = NO_MAIL; + log_error(flags, "%d incorrect password attempt%s", + def_passwd_tries - counter, + (def_passwd_tries - counter == 1) ? "" : "s"); + } + audit_failure(NewArgv, "authentication failure"); + rval = FALSE; + break; + case AUTH_FATAL: + default: + audit_failure(NewArgv, "authentication failure"); + rval = -1; + break; + } + + return rval; +} + +int auth_begin_session(struct passwd *pw) +{ + sudo_auth *auth; + int status; + + for (auth = auth_switch; auth->name; auth++) { + if (auth->begin_session && !IS_DISABLED(auth)) { + status = (auth->begin_session)(pw, auth); + if (status == AUTH_FATAL) { /* XXX log */ + audit_failure(NewArgv, "authentication failure"); + return -1; /* assume error msg already printed */ + } + } + } + return TRUE; +} + +int auth_end_session(void) +{ + sudo_auth *auth; + int status; + + for (auth = auth_switch; auth->name; auth++) { + if (auth->end_session && !IS_DISABLED(auth)) { + status = (auth->end_session)(auth); + if (status == AUTH_FATAL) { /* XXX log */ + return -1; /* assume error msg already printed */ + } + } + } + return TRUE; +} + +static void +pass_warn(void) +{ + const char *warning = def_badpass_message; + +#ifdef INSULT + if (def_insults) + warning = INSULT; +#endif + sudo_printf(SUDO_CONV_ERROR_MSG, "%s\n", warning); +} + +char * +auth_getpass(const char *prompt, int timeout, int type) +{ + struct sudo_conv_message msg; + struct sudo_conv_reply repl; + + /* Mask user input if pwfeedback set and echo is off. */ + if (type == SUDO_CONV_PROMPT_ECHO_OFF && def_pwfeedback) + type = SUDO_CONV_PROMPT_MASK; + + /* If visiblepw set, do not error out if there is no tty. */ + if (def_visiblepw) + type |= SUDO_CONV_PROMPT_ECHO_OK; + + /* Call conversation function */ + memset(&msg, 0, sizeof(msg)); + msg.msg_type = type; + msg.timeout = def_passwd_timeout * 60; + msg.msg = prompt; + memset(&repl, 0, sizeof(repl)); + sudo_conv(1, &msg, &repl); + /* XXX - check for ENOTTY? */ + return repl.reply; +} + +void +dump_auth_methods(void) +{ + sudo_auth *auth; + + sudo_printf(SUDO_CONV_INFO_MSG, "Authentication methods:"); + for (auth = auth_switch; auth->name; auth++) + sudo_printf(SUDO_CONV_INFO_MSG, " '%s'", auth->name); + sudo_printf(SUDO_CONV_INFO_MSG, "\n"); +} diff --git a/plugins/sudoers/auth/sudo_auth.h b/plugins/sudoers/auth/sudo_auth.h new file mode 100644 index 0000000..91124bf --- /dev/null +++ b/plugins/sudoers/auth/sudo_auth.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1999-2005, 2007-2010 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef SUDO_AUTH_H +#define SUDO_AUTH_H + +/* Auth function return values. */ +#define AUTH_SUCCESS 0 +#define AUTH_FAILURE 1 +#define AUTH_INTR 2 +#define AUTH_FATAL 3 + +typedef struct sudo_auth { + int flags; /* various flags, see below */ + int status; /* status from verify routine */ + char *name; /* name of the method as a string */ + void *data; /* method-specific data pointer */ + int (*init)(struct passwd *pw, char **prompt, struct sudo_auth *auth); + int (*setup)(struct passwd *pw, char **prompt, struct sudo_auth *auth); + int (*verify)(struct passwd *pw, char *p, struct sudo_auth *auth); + int (*cleanup)(struct passwd *pw, struct sudo_auth *auth); + int (*begin_session)(struct passwd *pw, struct sudo_auth *auth); + int (*end_session)(struct sudo_auth *auth); +} sudo_auth; + +/* Values for sudo_auth.flags. */ +#define FLAG_USER 0x01 /* functions must run as the user, not root */ +#define FLAG_DISABLED 0x02 /* method disabled */ +#define FLAG_STANDALONE 0x04 /* standalone auth method */ +#define FLAG_ONEANDONLY 0x08 /* one and only auth method */ + +/* Shortcuts for using the flags above. */ +#define NEEDS_USER(x) ((x)->flags & FLAG_USER) +#define IS_DISABLED(x) ((x)->flags & FLAG_DISABLED) +#define IS_STANDALONE(x) ((x)->flags & FLAG_STANDALONE) +#define IS_ONEANDONLY(x) ((x)->flags & FLAG_ONEANDONLY) + +/* Like tgetpass() but uses conversation function */ +char *auth_getpass(const char *prompt, int timeout, int type); + +/* Pointer to conversation function to use with auth_getpass(). */ +extern sudo_conv_t sudo_conv; + +/* Prototypes for standalone methods */ +int fwtk_init(struct passwd *pw, char **prompt, sudo_auth *auth); +int fwtk_verify(struct passwd *pw, char *prompt, sudo_auth *auth); +int fwtk_cleanup(struct passwd *pw, sudo_auth *auth); +int pam_init(struct passwd *pw, char **prompt, sudo_auth *auth); +int pam_verify(struct passwd *pw, char *prompt, sudo_auth *auth); +int pam_cleanup(struct passwd *pw, sudo_auth *auth); +int pam_begin_session(struct passwd *pw, sudo_auth *auth); +int pam_end_session(sudo_auth *auth); +int sia_setup(struct passwd *pw, char **prompt, sudo_auth *auth); +int sia_verify(struct passwd *pw, char *prompt, sudo_auth *auth); +int sia_cleanup(struct passwd *pw, sudo_auth *auth); +int aixauth_verify(struct passwd *pw, char *pass, sudo_auth *auth); +int aixauth_cleanup(struct passwd *pw, sudo_auth *auth); +int bsdauth_init(struct passwd *pw, char **prompt, sudo_auth *auth); +int bsdauth_verify(struct passwd *pw, char *prompt, sudo_auth *auth); +int bsdauth_cleanup(struct passwd *pw, sudo_auth *auth); + +/* Prototypes for normal methods */ +int passwd_init(struct passwd *pw, char **prompt, sudo_auth *auth); +int passwd_verify(struct passwd *pw, char *pass, sudo_auth *auth); +int passwd_cleanup(struct passwd *pw, sudo_auth *auth); +int secureware_init(struct passwd *pw, char **prompt, sudo_auth *auth); +int secureware_verify(struct passwd *pw, char *pass, sudo_auth *auth); +int secureware_cleanup(struct passwd *pw, sudo_auth *auth); +int rfc1938_setup(struct passwd *pw, char **prompt, sudo_auth *auth); +int rfc1938_verify(struct passwd *pw, char *pass, sudo_auth *auth); +int afs_verify(struct passwd *pw, char *pass, sudo_auth *auth); +int dce_verify(struct passwd *pw, char *pass, sudo_auth *auth); +int kerb4_init(struct passwd *pw, char **prompt, sudo_auth *auth); +int kerb4_verify(struct passwd *pw, char *pass, sudo_auth *auth); +int kerb5_init(struct passwd *pw, char **prompt, sudo_auth *auth); +int kerb5_verify(struct passwd *pw, char *pass, sudo_auth *auth); +int kerb5_cleanup(struct passwd *pw, sudo_auth *auth); +int securid_init(struct passwd *pw, char **prompt, sudo_auth *auth); +int securid_setup(struct passwd *pw, char **prompt, sudo_auth *auth); +int securid_verify(struct passwd *pw, char *pass, sudo_auth *auth); + +/* Fields: name, flags, init, setup, verify, cleanup, begin_sess, end_sess */ +#define AUTH_ENTRY(n, f, i, s, v, c, b, e) \ + { (f), AUTH_FAILURE, (n), NULL, (i), (s), (v), (c) , (b), (e) }, + +#endif /* SUDO_AUTH_H */ diff --git a/boottime.c b/plugins/sudoers/boottime.c similarity index 83% rename from boottime.c rename to plugins/sudoers/boottime.c index bdcd1f2..96576f8 100644 --- a/boottime.c +++ b/plugins/sudoers/boottime.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2010 Todd C. Miller + * Copyright (c) 2009-2011 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -42,15 +42,15 @@ #if TIME_WITH_SYS_TIME # include #endif -#ifdef HAVE_GETUTXID -# include -#endif -#ifdef HAVE_GETUTID -# include -#endif -#ifdef HAVE_SYSCTL -# include -#endif +#ifndef __linux__ +# if defined(HAVE_SYSCTL) && defined(KERN_BOOTTIME) +# include +# elif defined(HAVE_GETUTXID) +# include +# elif defined(HAVE_GETUTID) +# include +# endif +#endif /* !__linux__ */ #include "missing.h" @@ -61,8 +61,7 @@ #if defined(__linux__) int -get_boottime(tv) - struct timeval *tv; +get_boottime(struct timeval *tv) { char *line = NULL; size_t linesize = 0; @@ -89,8 +88,7 @@ get_boottime(tv) #elif defined(HAVE_SYSCTL) && defined(KERN_BOOTTIME) int -get_boottime(tv) - struct timeval *tv; +get_boottime(struct timeval *tv) { size_t size; int mib[2]; @@ -107,44 +105,43 @@ get_boottime(tv) #elif defined(HAVE_GETUTXID) int -get_boottime(tv) - struct timeval *tv; +get_boottime(struct timeval *tv) { struct utmpx *ut, key; memset(&key, 0, sizeof(key)); key.ut_type = BOOT_TIME; + setutxent(); if ((ut = getutxid(&key)) != NULL) { tv->tv_sec = ut->ut_tv.tv_sec; tv->tv_usec = ut->ut_tv.tv_usec; - endutxent(); } + endutxent(); return ut != NULL; } #elif defined(HAVE_GETUTID) int -get_boottime(tv) - struct timeval *tv; +get_boottime(struct timeval *tv) { struct utmp *ut, key; memset(&key, 0, sizeof(key)); key.ut_type = BOOT_TIME; + setutent(); if ((ut = getutid(&key)) != NULL) { tv->tv_sec = ut->ut_time; tv->tv_usec = 0; - endutent(); } + endutent(); return ut != NULL; } #else int -get_boottime(tv) - struct timeval *tv; +get_boottime(struct timeval *tv) { return 0; } diff --git a/bsm_audit.c b/plugins/sudoers/bsm_audit.c similarity index 98% rename from bsm_audit.c rename to plugins/sudoers/bsm_audit.c index 94ed4a8..8354fe3 100644 --- a/bsm_audit.c +++ b/plugins/sudoers/bsm_audit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2010 Todd C. Miller + * Copyright (c) 2009-2011 Todd C. Miller * Copyright (c) 2009 Christian S.J. Peron * * Permission to use, copy, modify, and distribute this software for any diff --git a/bsm_audit.h b/plugins/sudoers/bsm_audit.h similarity index 93% rename from bsm_audit.h rename to plugins/sudoers/bsm_audit.h index 37be345..bd29764 100644 --- a/bsm_audit.h +++ b/plugins/sudoers/bsm_audit.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009 Todd C. Miller + * Copyright (c) 2009-2010 Todd C. Miller * Copyright (c) 2009 Christian S.J. Peron * * Permission to use, copy, modify, and distribute this software for any diff --git a/check.c b/plugins/sudoers/check.c similarity index 85% rename from check.c rename to plugins/sudoers/check.c index df44bfc..af2412f 100644 --- a/check.c +++ b/plugins/sudoers/check.c @@ -61,7 +61,7 @@ #include #include -#include "sudo.h" +#include "sudoers.h" /* Status codes for timestamp_status() */ #define TS_CURRENT 0 @@ -84,28 +84,25 @@ static struct tty_info { struct timeval ctime; /* tty inode change time */ } tty_info; -static void build_timestamp __P((char **, char **)); -static int timestamp_status __P((char *, char *, char *, int)); -static char *expand_prompt __P((char *, char *, char *)); -static void lecture __P((int)); -static void update_timestamp __P((char *, char *)); -static int tty_is_devpts __P((const char *)); -static struct passwd *get_authpw __P((void)); +static int build_timestamp(char **, char **); +static int timestamp_status(char *, char *, char *, int); +static char *expand_prompt(char *, char *, char *); +static void lecture(int); +static void update_timestamp(char *, char *); +static int tty_is_devpts(const char *); +static struct passwd *get_authpw(void); /* - * This function only returns if the user can successfully - * verify who he/she is. + * Returns TRUE if the user successfully authenticates, else FALSE. */ -void -check_user(validated, mode) - int validated; - int mode; +int +check_user(int validated, int mode) { char *timestampdir = NULL; char *timestampfile = NULL; char *prompt; struct stat sb; - int status; + int status, rval = TRUE; /* Stash the tty's ctime for tty ticket comparison. */ if (def_tty_tickets && user_ttypath && stat(user_ttypath, &sb) == 0) { @@ -117,7 +114,7 @@ check_user(validated, mode) } /* Always prompt for a password when -k was specified with the command. */ - if (ISSET(mode, MODE_INVALIDATE)) { + if (ISSET(mode, MODE_IGNORE_TICKET)) { SET(validated, FLAG_CHECK_USER); } else { /* @@ -127,10 +124,12 @@ check_user(validated, mode) if (user_uid == 0 || (user_uid == runas_pw->pw_uid && (!runas_gr || user_in_group(sudo_user.pw, runas_gr->gr_name))) || user_is_exempt()) - return; + return TRUE; } - build_timestamp(×tampdir, ×tampfile); + if (build_timestamp(×tampdir, ×tampfile) == -1) + return -1; + status = timestamp_status(timestampdir, timestampfile, user_name, TS_MAKE_DIRS); @@ -138,72 +137,70 @@ check_user(validated, mode) struct passwd *auth_pw; /* Bail out if we are non-interactive and a password is required */ - if (ISSET(mode, MODE_NONINTERACTIVE)) - errorx(1, "sorry, a password is required to run %s", getprogname()); - - /* If user specified -A, make sure we have an askpass helper. */ - if (ISSET(tgetpass_flags, TGP_ASKPASS)) { - if (user_askpass == NULL) - log_error(NO_MAIL, - "no askpass program specified, try setting SUDO_ASKPASS"); - } else if (!ISSET(tgetpass_flags, TGP_STDIN)) { - /* If no tty but DISPLAY is set, use askpass if we have it. */ - if (!user_ttypath && !tty_present()) { - if (user_askpass && user_display && *user_display != '\0') { - SET(tgetpass_flags, TGP_ASKPASS); - } else if (!def_visiblepw) { - log_error(NO_MAIL, - "no tty present and no askpass program specified"); - } - } + if (ISSET(mode, MODE_NONINTERACTIVE)) { + warningx("sorry, a password is required to run %s", getprogname()); + return -1; } - if (!ISSET(tgetpass_flags, TGP_ASKPASS)) - lecture(status); + /* XXX - should not lecture if askpass help is being used. */ + lecture(status); /* Expand any escapes in the prompt. */ prompt = expand_prompt(user_prompt ? user_prompt : def_passprompt, user_name, user_shost); auth_pw = get_authpw(); - verify_user(auth_pw, prompt); + rval = verify_user(auth_pw, prompt); pw_delref(auth_pw); } /* Only update timestamp if user was validated. */ - if (ISSET(validated, VALIDATE_OK) && !ISSET(mode, MODE_INVALIDATE) && status != TS_ERROR) + if (rval == TRUE && ISSET(validated, VALIDATE_OK) && + !ISSET(mode, MODE_IGNORE_TICKET) && status != TS_ERROR) update_timestamp(timestampdir, timestampfile); efree(timestampdir); efree(timestampfile); + + return rval; } +static const char lecture_text[] = "\n" +"We trust you have received the usual lecture from the local System\n" +"Administrator. It usually boils down to these three things:\n\n" +" #1) Respect the privacy of others.\n" +" #2) Think before you type.\n" +" #3) With great power comes great responsibility.\n\n"; + /* * Standard sudo lecture. */ static void -lecture(status) - int status; +lecture(int status) { FILE *fp; char buf[BUFSIZ]; ssize_t nread; + struct sudo_conv_message msg; + struct sudo_conv_reply repl; if (def_lecture == never || (def_lecture == once && status != TS_MISSING && status != TS_ERROR)) return; + memset(&msg, 0, sizeof(msg)); + memset(&repl, 0, sizeof(repl)); + if (def_lecture_file && (fp = fopen(def_lecture_file, "r")) != NULL) { - while ((nread = fread(buf, sizeof(char), sizeof(buf), fp)) != 0) - fwrite(buf, nread, 1, stderr); + while ((nread = fread(buf, sizeof(char), sizeof(buf) - 1, fp)) != 0) { + buf[sizeof(buf) - 1] = '\0'; + msg.msg_type = SUDO_CONV_ERROR_MSG; + msg.msg = buf; + sudo_conv(1, &msg, &repl); + } fclose(fp); } else { - (void) fputs("\n\ -We trust you have received the usual lecture from the local System\n\ -Administrator. It usually boils down to these three things:\n\ -\n\ - #1) Respect the privacy of others.\n\ - #2) Think before you type.\n\ - #3) With great power comes great responsibility.\n\n", - stderr); + msg.msg_type = SUDO_CONV_ERROR_MSG; + msg.msg = lecture_text; + sudo_conv(1, &msg, &repl); } } @@ -211,9 +208,7 @@ Administrator. It usually boils down to these three things:\n\ * Update the time on the timestamp file/dir or create it if necessary. */ static void -update_timestamp(timestampdir, timestampfile) - char *timestampdir; - char *timestampfile; +update_timestamp(char *timestampdir, char *timestampfile) { /* If using tty timestamps but we have no tty there is nothing to do. */ if (def_tty_tickets && !user_ttypath) @@ -241,7 +236,7 @@ update_timestamp(timestampdir, timestampfile) } } if (timestamp_uid != 0) - set_perms(PERM_ROOT); + restore_perms(); } /* @@ -249,10 +244,7 @@ update_timestamp(timestampdir, timestampfile) * allocated result. Returns the same string if there are no escapes. */ static char * -expand_prompt(old_prompt, user, host) - char *old_prompt; - char *user; - char *host; +expand_prompt(char *old_prompt, char *user, char *host) { size_t len, n; int subst; @@ -378,7 +370,7 @@ oflow: * Checks if the user is exempt from supplying a password. */ int -user_is_exempt() +user_is_exempt(void) { if (!def_exempt_group) return FALSE; @@ -388,18 +380,18 @@ user_is_exempt() /* * Fills in timestampdir as well as timestampfile if using tty tickets. */ -static void -build_timestamp(timestampdir, timestampfile) - char **timestampdir; - char **timestampfile; +static int +build_timestamp(char **timestampdir, char **timestampfile) { char *dirparent; int len; dirparent = def_timestampdir; len = easprintf(timestampdir, "%s/%s", dirparent, user_name); - if (len >= PATH_MAX) + if (len >= PATH_MAX) { log_error(0, "timestamp path too long: %s", *timestampdir); + return -1; + } /* * Timestamp file may be a file in the directory or NUL to use @@ -417,26 +409,28 @@ build_timestamp(timestampdir, timestampfile) p, runas_pw->pw_name); else len = easprintf(timestampfile, "%s/%s/%s", dirparent, user_name, p); - if (len >= PATH_MAX) + if (len >= PATH_MAX) { log_error(0, "timestamp path too long: %s", *timestampfile); + return -1; + } } else if (def_targetpw) { len = easprintf(timestampfile, "%s/%s/%s", dirparent, user_name, runas_pw->pw_name); - if (len >= PATH_MAX) + if (len >= PATH_MAX) { log_error(0, "timestamp path too long: %s", *timestampfile); + return -1; + } } else *timestampfile = NULL; + + return len; } /* * Check the timestamp file and directory and return their status. */ static int -timestamp_status(timestampdir, timestampfile, user, flags) - char *timestampdir; - char *timestampfile; - char *user; - int flags; +timestamp_status(char *timestampdir, char *timestampfile, char *user, int flags) { struct stat sb; struct timeval boottime, mtime; @@ -483,11 +477,8 @@ timestamp_status(timestampdir, timestampfile, user, flags) status = TS_MISSING; } } - if (status == TS_ERROR) { - if (timestamp_uid != 0) - set_perms(PERM_ROOT); - return status; - } + if (status == TS_ERROR) + goto done; /* * Sanity check the user's ticket dir. We start by downgrading @@ -629,7 +620,7 @@ timestamp_status(timestampdir, timestampfile, user, flags) done: if (timestamp_uid != 0) - set_perms(PERM_ROOT); + restore_perms(); return status; } @@ -637,17 +628,18 @@ done: * Remove the timestamp ticket file/dir. */ void -remove_timestamp(remove) - int remove; +remove_timestamp(int remove) { struct timeval tv; char *timestampdir, *timestampfile, *path; int status; - build_timestamp(×tampdir, ×tampfile); + if (build_timestamp(×tampdir, ×tampfile) == -1) + return; + status = timestamp_status(timestampdir, timestampfile, user_name, TS_REMOVE); - if (status == TS_OLD || status == TS_CURRENT) { + if (status != TS_MISSING && status != TS_ERROR) { path = timestampfile ? timestampfile : timestampdir; if (remove) { if (timestampfile) @@ -679,8 +671,7 @@ remove_timestamp(remove) * file and use it to determine whether the tty ticket file is stale. */ static int -tty_is_devpts(tty) - const char *tty; +tty_is_devpts(const char *tty) { int retval = FALSE; #ifdef __linux__ @@ -711,7 +702,7 @@ tty_is_devpts(tty) * case, this matches sudo_user.pw or runas_pw. */ static struct passwd * -get_authpw() +get_authpw(void) { struct passwd *pw; diff --git a/def_data.c b/plugins/sudoers/def_data.c similarity index 95% rename from def_data.c rename to plugins/sudoers/def_data.c index c63d595..ca02ced 100644 --- a/def_data.c +++ b/plugins/sudoers/def_data.c @@ -286,10 +286,6 @@ struct sudo_defs_types sudo_defs_table[] = { "type", T_STR, "SELinux type to use in the new security context: %s", NULL, - }, { - "askpass", T_STR|T_PATH|T_BOOL, - "Path to the askpass helper program: %s", - NULL, }, { "env_file", T_STR|T_PATH|T_BOOL, "Path to the sudo-specific environment file: %s", @@ -330,10 +326,26 @@ struct sudo_defs_types sudo_defs_table[] = { "use_pty", T_FLAG, "Always run commands in a pseudo-tty", NULL, + }, { + "group_plugin", T_STR, + "Plugin for non-Unix group support", + NULL, }, { "iolog_dir", T_STR|T_PATH, "Directory in which to store input/output logs", NULL, + }, { + "iolog_file", T_STR, + "File in which to store the input/output log", + NULL, + }, { + "set_utmp", T_FLAG, + "Add an entry to the utmp/utmpx file when allocating a pty", + NULL, + }, { + "utmp_runas", T_FLAG, + "Set the user in utmp to the runas user, not the invoking user", + NULL, }, { NULL, 0, NULL } diff --git a/def_data.h b/plugins/sudoers/def_data.h similarity index 82% rename from def_data.h rename to plugins/sudoers/def_data.h index 0996ec8..f41f7cd 100644 --- a/def_data.h +++ b/plugins/sudoers/def_data.h @@ -130,32 +130,38 @@ #define I_ROLE 64 #define def_type (sudo_defs_table[65].sd_un.str) #define I_TYPE 65 -#define def_askpass (sudo_defs_table[66].sd_un.str) -#define I_ASKPASS 66 -#define def_env_file (sudo_defs_table[67].sd_un.str) -#define I_ENV_FILE 67 -#define def_sudoers_locale (sudo_defs_table[68].sd_un.str) -#define I_SUDOERS_LOCALE 68 -#define def_visiblepw (sudo_defs_table[69].sd_un.flag) -#define I_VISIBLEPW 69 -#define def_pwfeedback (sudo_defs_table[70].sd_un.flag) -#define I_PWFEEDBACK 70 -#define def_fast_glob (sudo_defs_table[71].sd_un.flag) -#define I_FAST_GLOB 71 -#define def_umask_override (sudo_defs_table[72].sd_un.flag) -#define I_UMASK_OVERRIDE 72 -#define def_log_input (sudo_defs_table[73].sd_un.flag) -#define I_LOG_INPUT 73 -#define def_log_output (sudo_defs_table[74].sd_un.flag) -#define I_LOG_OUTPUT 74 -#define def_compress_io (sudo_defs_table[75].sd_un.flag) -#define I_COMPRESS_IO 75 -#define def_use_pty (sudo_defs_table[76].sd_un.flag) -#define I_USE_PTY 76 +#define def_env_file (sudo_defs_table[66].sd_un.str) +#define I_ENV_FILE 66 +#define def_sudoers_locale (sudo_defs_table[67].sd_un.str) +#define I_SUDOERS_LOCALE 67 +#define def_visiblepw (sudo_defs_table[68].sd_un.flag) +#define I_VISIBLEPW 68 +#define def_pwfeedback (sudo_defs_table[69].sd_un.flag) +#define I_PWFEEDBACK 69 +#define def_fast_glob (sudo_defs_table[70].sd_un.flag) +#define I_FAST_GLOB 70 +#define def_umask_override (sudo_defs_table[71].sd_un.flag) +#define I_UMASK_OVERRIDE 71 +#define def_log_input (sudo_defs_table[72].sd_un.flag) +#define I_LOG_INPUT 72 +#define def_log_output (sudo_defs_table[73].sd_un.flag) +#define I_LOG_OUTPUT 73 +#define def_compress_io (sudo_defs_table[74].sd_un.flag) +#define I_COMPRESS_IO 74 +#define def_use_pty (sudo_defs_table[75].sd_un.flag) +#define I_USE_PTY 75 +#define def_group_plugin (sudo_defs_table[76].sd_un.str) +#define I_GROUP_PLUGIN 76 #define def_iolog_dir (sudo_defs_table[77].sd_un.str) #define I_IOLOG_DIR 77 +#define def_iolog_file (sudo_defs_table[78].sd_un.str) +#define I_IOLOG_FILE 78 +#define def_set_utmp (sudo_defs_table[79].sd_un.flag) +#define I_SET_UTMP 79 +#define def_utmp_runas (sudo_defs_table[80].sd_un.flag) +#define I_UTMP_RUNAS 80 -enum def_tupple { +enum def_tuple { never, once, always, diff --git a/def_data.in b/plugins/sudoers/def_data.in similarity index 95% rename from def_data.in rename to plugins/sudoers/def_data.in index 4a7ae96..340a5e4 100644 --- a/def_data.in +++ b/plugins/sudoers/def_data.in @@ -211,9 +211,6 @@ role type T_STR "SELinux type to use in the new security context: %s" -askpass - T_STR|T_PATH|T_BOOL - "Path to the askpass helper program: %s" env_file T_STR|T_PATH|T_BOOL "Path to the sudo-specific environment file: %s" @@ -244,6 +241,18 @@ compress_io use_pty T_FLAG "Always run commands in a pseudo-tty" +group_plugin + T_STR + "Plugin for non-Unix group support" iolog_dir T_STR|T_PATH "Directory in which to store input/output logs" +iolog_file + T_STR + "File in which to store the input/output log" +set_utmp + T_FLAG + "Add an entry to the utmp/utmpx file when allocating a pty" +utmp_runas + T_FLAG + "Set the user in utmp to the runas user, not the invoking user" diff --git a/defaults.c b/plugins/sudoers/defaults.c similarity index 84% rename from defaults.c rename to plugins/sudoers/defaults.c index c1f0afa..f9e9961 100644 --- a/defaults.c +++ b/plugins/sudoers/defaults.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005, 2007-2008, 2010 + * Copyright (c) 1999-2005, 2007-2011 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -44,7 +44,7 @@ #include #include -#include "sudo.h" +#include "sudoers.h" #include "parse.h" #include @@ -91,18 +91,18 @@ static struct strmap priorities[] = { /* * Local prototypes. */ -static int store_int __P((char *, struct sudo_defs_types *, int)); -static int store_list __P((char *, struct sudo_defs_types *, int)); -static int store_mode __P((char *, struct sudo_defs_types *, int)); -static int store_str __P((char *, struct sudo_defs_types *, int)); -static int store_syslogfac __P((char *, struct sudo_defs_types *, int)); -static int store_syslogpri __P((char *, struct sudo_defs_types *, int)); -static int store_tuple __P((char *, struct sudo_defs_types *, int)); -static int store_uint __P((char *, struct sudo_defs_types *, int)); -static int store_float __P((char *, struct sudo_defs_types *, int)); -static void list_op __P((char *, size_t, struct sudo_defs_types *, enum list_ops)); -static const char *logfac2str __P((int)); -static const char *logpri2str __P((int)); +static int store_int(char *, struct sudo_defs_types *, int); +static int store_list(char *, struct sudo_defs_types *, int); +static int store_mode(char *, struct sudo_defs_types *, int); +static int store_str(char *, struct sudo_defs_types *, int); +static int store_syslogfac(char *, struct sudo_defs_types *, int); +static int store_syslogpri(char *, struct sudo_defs_types *, int); +static int store_tuple(char *, struct sudo_defs_types *, int); +static int store_uint(char *, struct sudo_defs_types *, int); +static int store_float(char *, struct sudo_defs_types *, int); +static void list_op(char *, size_t, struct sudo_defs_types *, enum list_ops); +static const char *logfac2str(int); +static const char *logpri2str(int); /* * Table describing compile-time and run-time options. @@ -113,7 +113,7 @@ static const char *logpri2str __P((int)); * Print version and configure info. */ void -dump_defaults() +dump_defaults(void) { struct sudo_defs_types *cur; struct list_member *item; @@ -124,54 +124,60 @@ dump_defaults() switch (cur->type & T_MASK) { case T_FLAG: if (cur->sd_un.flag) - puts(cur->desc); + sudo_printf(SUDO_CONV_INFO_MSG, "%s\n", cur->desc); break; case T_STR: if (cur->sd_un.str) { - (void) printf(cur->desc, cur->sd_un.str); - putchar('\n'); + sudo_printf(SUDO_CONV_INFO_MSG, + cur->desc, cur->sd_un.str); + sudo_printf(SUDO_CONV_INFO_MSG, "\n"); } break; case T_LOGFAC: if (cur->sd_un.ival) { - (void) printf(cur->desc, logfac2str(cur->sd_un.ival)); - putchar('\n'); + sudo_printf(SUDO_CONV_INFO_MSG, + cur->desc, logfac2str(cur->sd_un.ival)); + sudo_printf(SUDO_CONV_INFO_MSG, "\n"); } break; case T_LOGPRI: if (cur->sd_un.ival) { - (void) printf(cur->desc, logpri2str(cur->sd_un.ival)); - putchar('\n'); + sudo_printf(SUDO_CONV_INFO_MSG, + cur->desc, logpri2str(cur->sd_un.ival)); + sudo_printf(SUDO_CONV_INFO_MSG, "\n"); } break; case T_UINT: case T_INT: - (void) printf(cur->desc, cur->sd_un.ival); - putchar('\n'); + sudo_printf(SUDO_CONV_INFO_MSG, cur->desc, cur->sd_un.ival); + sudo_printf(SUDO_CONV_INFO_MSG, "\n"); break; case T_FLOAT: - (void) printf(cur->desc, cur->sd_un.fval); - putchar('\n'); + sudo_printf(SUDO_CONV_INFO_MSG, cur->desc, cur->sd_un.fval); + sudo_printf(SUDO_CONV_INFO_MSG, "\n"); break; case T_MODE: - (void) printf(cur->desc, cur->sd_un.mode); - putchar('\n'); + sudo_printf(SUDO_CONV_INFO_MSG, cur->desc, cur->sd_un.mode); + sudo_printf(SUDO_CONV_INFO_MSG, "\n"); break; case T_LIST: if (cur->sd_un.list) { - puts(cur->desc); - for (item = cur->sd_un.list; item; item = item->next) - printf("\t%s\n", item->value); + sudo_printf(SUDO_CONV_INFO_MSG, "%s\n", cur->desc); + for (item = cur->sd_un.list; item; item = item->next) { + sudo_printf(SUDO_CONV_INFO_MSG, + "\t%s\n", item->value); + } } break; case T_TUPLE: for (def = cur->values; def->sval; def++) { if (cur->sd_un.ival == def->ival) { - (void) printf(cur->desc, def->sval); + sudo_printf(SUDO_CONV_INFO_MSG, + cur->desc, def->sval); break; } } - putchar('\n'); + sudo_printf(SUDO_CONV_INFO_MSG, "\n"); break; } } @@ -182,25 +188,29 @@ dump_defaults() * List each option along with its description. */ void -list_options() +list_options(void) { struct sudo_defs_types *cur; char *p; - (void) puts("Available options in a sudoers ``Defaults'' line:\n"); + sudo_printf(SUDO_CONV_INFO_MSG, + "Available options in a sudoers ``Defaults'' line:\n\n"); for (cur = sudo_defs_table; cur->name; cur++) { if (cur->name && cur->desc) { switch (cur->type & T_MASK) { case T_FLAG: - (void) printf("%s: %s\n", cur->name, cur->desc); + sudo_printf(SUDO_CONV_INFO_MSG, + "%s: %s\n", cur->name, cur->desc); break; default: p = strrchr(cur->desc, ':'); - if (p) - (void) printf("%s: %.*s\n", cur->name, - (int) (p - cur->desc), cur->desc); - else - (void) printf("%s: %s\n", cur->name, cur->desc); + if (p) { + sudo_printf(SUDO_CONV_INFO_MSG, "%s: %.*s\n", + cur->name, (int) (p - cur->desc), cur->desc); + } else { + sudo_printf(SUDO_CONV_INFO_MSG, + "%s: %s\n", cur->name, cur->desc); + } break; } } @@ -215,10 +225,7 @@ list_options() * This is only meaningful for variables that are *optional*. */ int -set_default(var, val, op) - char *var; - char *val; - int op; /* TRUE or FALSE */ +set_default(char *var, char *val, int op) { struct sudo_defs_types *cur; int num; @@ -360,7 +367,7 @@ set_default(var, val, op) * Any of these may be overridden at runtime by a "Defaults" file. */ void -init_defaults() +init_defaults(void) { static int firsttime = 1; struct sudo_defs_types *def; @@ -436,9 +443,7 @@ init_defaults() #ifdef UMASK_OVERRIDE def_umask_override = TRUE; #endif -#ifdef _PATH_SUDO_ASKPASS - def_askpass = estrdup(_PATH_SUDO_ASKPASS); -#endif + def_iolog_file = estrdup("%{seq}"); def_iolog_dir = estrdup(_PATH_SUDO_IO_LOGDIR); def_sudoers_locale = estrdup("C"); def_env_reset = ENV_RESET; @@ -493,9 +498,7 @@ init_defaults() def_secure_path = estrdup(SECURE_PATH); #endif def_editor = estrdup(EDITOR); -#ifdef _PATH_SUDO_NOEXEC - def_noexec_file = estrdup(_PATH_SUDO_NOEXEC); -#endif + def_set_utmp = TRUE; /* Finally do the lists (currently just environment tables). */ init_envtables(); @@ -508,8 +511,7 @@ init_defaults() * Pass in an OR'd list of which default types to update. */ int -update_defaults(what) - int what; +update_defaults(int what) { struct defaults *def; int rc = TRUE; @@ -551,10 +553,7 @@ update_defaults(what) } static int -store_int(val, def, op) - char *val; - struct sudo_defs_types *def; - int op; +store_int(char *val, struct sudo_defs_types *def, int op) { char *endp; long l; @@ -574,10 +573,7 @@ store_int(val, def, op) } static int -store_uint(val, def, op) - char *val; - struct sudo_defs_types *def; - int op; +store_uint(char *val, struct sudo_defs_types *def, int op) { char *endp; long l; @@ -597,10 +593,7 @@ store_uint(val, def, op) } static int -store_float(val, def, op) - char *val; - struct sudo_defs_types *def; - int op; +store_float(char *val, struct sudo_defs_types *def, int op) { char *endp; double d; @@ -620,10 +613,7 @@ store_float(val, def, op) } static int -store_tuple(val, def, op) - char *val; - struct sudo_defs_types *def; - int op; +store_tuple(char *val, struct sudo_defs_types *def, int op) { struct def_values *v; @@ -652,10 +642,7 @@ store_tuple(val, def, op) } static int -store_str(val, def, op) - char *val; - struct sudo_defs_types *def; - int op; +store_str(char *val, struct sudo_defs_types *def, int op) { efree(def->sd_un.str); @@ -669,10 +656,7 @@ store_str(val, def, op) } static int -store_list(str, def, op) - char *str; - struct sudo_defs_types *def; - int op; +store_list(char *str, struct sudo_defs_types *def, int op) { char *start, *end; @@ -700,10 +684,7 @@ store_list(str, def, op) } static int -store_syslogfac(val, def, op) - char *val; - struct sudo_defs_types *def; - int op; +store_syslogfac(char *val, struct sudo_defs_types *def, int op) { struct strmap *fac; @@ -727,8 +708,7 @@ store_syslogfac(val, def, op) } static const char * -logfac2str(n) - int n; +logfac2str(int n) { #ifdef LOG_NFACILITIES struct strmap *fac; @@ -742,10 +722,7 @@ logfac2str(n) } static int -store_syslogpri(val, def, op) - char *val; - struct sudo_defs_types *def; - int op; +store_syslogpri(char *val, struct sudo_defs_types *def, int op) { struct strmap *pri; @@ -762,8 +739,7 @@ store_syslogpri(val, def, op) } static const char * -logpri2str(n) - int n; +logpri2str(int n) { struct strmap *pri; @@ -773,10 +749,7 @@ logpri2str(n) } static int -store_mode(val, def, op) - char *val; - struct sudo_defs_types *def; - int op; +store_mode(char *val, struct sudo_defs_types *def, int op) { char *endp; long l; @@ -795,11 +768,7 @@ store_mode(val, def, op) } static void -list_op(val, len, def, op) - char *val; - size_t len; - struct sudo_defs_types *def; - enum list_ops op; +list_op(char *val, size_t len, struct sudo_defs_types *def, enum list_ops op) { struct list_member *cur, *prev, *tmp; diff --git a/defaults.h b/plugins/sudoers/defaults.h similarity index 89% rename from defaults.h rename to plugins/sudoers/defaults.h index eb2188a..1329124 100644 --- a/defaults.h +++ b/plugins/sudoers/defaults.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005, 2008, 2010 + * Copyright (c) 1999-2005, 2008-2010 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -48,12 +48,12 @@ struct sudo_defs_types { int type; char *desc; struct def_values *values; - int (*callback) __P((char *)); + int (*callback)(char *); union { int flag; int ival; double fval; - enum def_tupple tuple; + enum def_tuple tuple; char *str; mode_t mode; struct list_member *list; @@ -105,12 +105,11 @@ struct sudo_defs_types { /* * Prototypes */ -int set_default __P((char *, char *, int)); -int update_defaults __P((int)); -void dump_default __P((void)); -void dump_defaults __P((void)); -void init_defaults __P((void)); -void list_options __P((void)); +void dump_default(void); +void init_defaults(void); +void list_options(void); +int set_default(char *, char *, int); +int update_defaults(int); extern struct sudo_defs_types sudo_defs_table[]; diff --git a/env.c b/plugins/sudoers/env.c similarity index 76% rename from env.c rename to plugins/sudoers/env.c index 654565e..9d1201f 100644 --- a/env.c +++ b/plugins/sudoers/env.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000-2005, 2007-2010 + * Copyright (c) 2000-2005, 2007-2011 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -46,7 +46,7 @@ #include #include -#include "sudo.h" +#include "sudoers.h" /* * Flags used in rebuild_env() @@ -93,16 +93,13 @@ struct environment { char **envp; /* pointer to the new environment */ size_t env_size; /* size of new_environ in char **'s */ size_t env_len; /* number of slots used, not counting NULL */ - int owned; /* do we own envp or is it the system's? */ }; /* * Prototypes */ -static void sudo_setenv __P((const char *, const char *, int)); -static void sudo_putenv __P((char *, int, int)); - -extern char **environ; /* global environment */ +static void sudo_setenv(const char *, const char *, int); +static void sudo_putenv(char *, int, int); /* * Copy of the sudo-managed environment. @@ -215,39 +212,27 @@ static const char *initial_keepenv_table[] = { * Initialize env based on envp. */ void -env_init(lazy) - int lazy; +env_init(char * const envp[]) { char * const *ep; size_t len; - for (ep = environ; *ep != NULL; ep++) + for (ep = envp; *ep != NULL; ep++) continue; - len = (size_t)(ep - environ); + len = (size_t)(ep - envp); - if (lazy) { - /* - * If we are already initialized due to lazy init (usualy via getenv()) - * we need to avoid calling malloc() as it may call getenv() itself. - */ - env.envp = environ; - env.env_len = len; - env.env_size = len; - } else if (!env.owned) { - env.env_len = len; - env.env_size = len + 1 + 128; - env.envp = emalloc2(env.env_size, sizeof(char *)); + env.env_len = len; + env.env_size = len + 1 + 128; + env.envp = emalloc2(env.env_size, sizeof(char *)); #ifdef ENV_DEBUG - memset(env.envp, 0, env.env_size * sizeof(char *)); + memset(env.envp, 0, env.env_size * sizeof(char *)); #endif - memcpy(env.envp, environ, len * sizeof(char *)); - env.envp[len] = '\0'; - env.owned = TRUE; - } + memcpy(env.envp, envp, len * sizeof(char *)); + env.envp[len] = '\0'; } char ** -env_get() +env_get(void) { return env.envp; } @@ -258,10 +243,7 @@ env_get() * whether we need to verify that the variable is not already set. */ static void -sudo_setenv(var, val, dupcheck) - const char *var; - const char *val; - int dupcheck; +sudo_setenv(const char *var, const char *val, int dupcheck) { char *estring; size_t esize; @@ -279,152 +261,6 @@ sudo_setenv(var, val, dupcheck) sudo_putenv(estring, dupcheck, TRUE); } -/* - * Version of getenv(3) that uses our own environ pointer. - */ -char * -getenv(var) - const char *var; -{ - char *cp, **ev; - size_t vlen = strlen(var); - - if (env.envp == NULL) - env_init(TRUE); - - for (ev = env.envp; (cp = *ev) != NULL; ev++) { - if (strncmp(var, cp, vlen) == 0 && cp[vlen] == '=') - return cp + vlen + 1; - } - return NULL; -} - -/* - * Version of setenv(3) that uses our own environ pointer. - */ -int -setenv(var, val, overwrite) - const char *var; - const char *val; - int overwrite; -{ - char *estring, *ep; - const char *cp; - size_t esize; - - if (!var || *var == '\0') { - errno = EINVAL; - return -1; - } - - if (env.envp == NULL) - env_init(TRUE); - - /* - * POSIX says a var name with '=' is an error but BSD - * just ignores the '=' and anything after it. - */ - for (cp = var; *cp && *cp != '='; cp++) - ; - esize = (size_t)(cp - var) + 2; - if (val) { - esize += strlen(val); /* glibc treats a NULL val as "" */ - } - - /* Allocate and fill in estring. */ - estring = ep = emalloc(esize); - for (cp = var; *cp && *cp != '='; cp++) - *ep++ = *cp; - *ep++ = '='; - if (val) { - for (cp = val; *cp; cp++) - *ep++ = *cp; - } - *ep = '\0'; - -#ifdef ENV_DEBUG - if (env.envp[env.env_len] != NULL) - errorx(1, "setenv: corrupted envp, len mismatch"); -#endif - sudo_putenv(estring, TRUE, overwrite); - return 0; -} - -/* - * Version of unsetenv(3) that uses our own environ pointer. - */ -#ifdef UNSETENV_VOID -void -#else -int -#endif -unsetenv(var) - const char *var; -{ - char **ep; - size_t len; - - if (var == NULL || *var == '\0' || strchr(var, '=') != NULL) { - errno = EINVAL; -#ifdef UNSETENV_VOID - return; -#else - return -1; -#endif - } - - if (env.envp == NULL) - env_init(TRUE); - -#ifdef ENV_DEBUG - if (env.envp[env.env_len] != NULL) - errorx(1, "unsetenv: corrupted envp, len mismatch"); -#endif - - len = strlen(var); - for (ep = env.envp; *ep != NULL;) { - if (strncmp(var, *ep, len) == 0 && (*ep)[len] == '=') { - /* Found it; shift remainder + NULL over by one. */ - char **cur = ep; - while ((*cur = *(cur + 1)) != NULL) - cur++; - /* Keep going, could be multiple instances of the var. */ - } else { - ep++; - } - } - env.env_len = ep - env.envp; -#ifndef UNSETENV_VOID - return 0; -#endif -} - -/* - * Version of putenv(3) that uses our own environ pointer. - */ -int -#ifdef PUTENV_CONST -putenv(const char *string) -#else -putenv(string) - char *string; -#endif -{ - if (env.envp == NULL) - env_init(TRUE); - - if (strchr(string, '=') == NULL) { - errno = EINVAL; - return -1; - } -#ifdef ENV_DEBUG - if (env.envp[env.env_len] != NULL) - errorx(1, "putenv: corrupted envp, len mismatch"); -#endif - sudo_putenv((char *)string, TRUE, TRUE); - return 0; -} - /* * Similar to putenv(3) but operates on sudo's private copy of the * environment (not environ) and it always overwrites. The dupcheck param @@ -432,10 +268,7 @@ putenv(string) * Will only overwrite an existing variable if overwrite is set. */ static void -sudo_putenv(str, dupcheck, overwrite) - char *str; - int dupcheck; - int overwrite; +sudo_putenv(char *str, int dupcheck, int overwrite) { char **ep; size_t len; @@ -444,15 +277,7 @@ sudo_putenv(str, dupcheck, overwrite) /* Make sure there is room for the new entry plus a NULL. */ if (env.env_len + 2 > env.env_size) { env.env_size += 128; - if (env.owned) { - env.envp = erealloc3(env.envp, env.env_size, sizeof(char *)); - } else { - /* We don't own env.envp, allocate a new one. */ - ep = emalloc2(env.env_size, sizeof(char *)); - memcpy(ep, env.envp, env.env_size * sizeof(char *)); - env.envp = ep; - env.owned = TRUE; - } + env.envp = erealloc3(env.envp, env.env_size, sizeof(char *)); #ifdef ENV_DEBUG memset(env.envp + env.env_len, 0, (env.env_size - env.env_len) * sizeof(char *)); @@ -501,8 +326,7 @@ sudo_putenv(str, dupcheck, overwrite) * Returns TRUE if the variable was found, else false. */ static int -matches_env_delete(var) - const char *var; +matches_env_delete(const char *var) { struct list_member *cur; size_t len; @@ -532,8 +356,7 @@ matches_env_delete(var) * or -1 if no match. */ static int -matches_env_check(var) - const char *var; +matches_env_check(const char *var) { struct list_member *cur; size_t len; @@ -561,8 +384,7 @@ matches_env_check(var) * Returns TRUE if the variable is allowed else FALSE. */ static int -matches_env_keep(var) - const char *var; +matches_env_keep(const char *var) { struct list_member *cur; size_t len; @@ -591,8 +413,7 @@ matches_env_keep(var) * Also adds sudo-specific variables (SUDO_*). */ void -rebuild_env(noexec) - int noexec; +rebuild_env(void) { char **old_envp, **ep, *cp, *ps1; char idbuf[MAX_UID_T_LEN]; @@ -781,30 +602,6 @@ rebuild_env(noexec) if (!ISSET(didvar, DID_PATH)) sudo_setenv("PATH", _PATH_STDPATH, FALSE); - /* - * Preload a noexec file? For a list of LD_PRELOAD-alikes, see - * http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html - * XXX - should prepend to original value, if any - */ - if (noexec && def_noexec_file != NULL) { -#if defined(__darwin__) || defined(__APPLE__) - sudo_setenv("DYLD_INSERT_LIBRARIES", def_noexec_file, TRUE); - sudo_setenv("DYLD_FORCE_FLAT_NAMESPACE", "", TRUE); -#else -# if defined(__osf__) || defined(__sgi) - easprintf(&cp, "%s:DEFAULT", def_noexec_file); - sudo_setenv("_RLD_LIST", cp, TRUE); - efree(cp); -# else -# ifdef _AIX - sudo_setenv("LDR_PRELOAD", def_noexec_file, TRUE); -# else - sudo_setenv("LD_PRELOAD", def_noexec_file, TRUE); -# endif /* _AIX */ -# endif /* __osf__ || __sgi */ -#endif /* __darwin__ || __APPLE__ */ - } - /* Set PS1 if SUDO_PS1 is set. */ if (ps1 != NULL) sudo_putenv(ps1, TRUE, TRUE); @@ -830,14 +627,16 @@ rebuild_env(noexec) } void -insert_env_vars(env_vars) - struct list_member *env_vars; +insert_env_vars(char * const envp[]) { - struct list_member *cur; + char * const *ep; + + if (envp == NULL) + return; /* Add user-specified environment variables. */ - for (cur = env_vars; cur != NULL; cur = cur->next) - putenv(cur->value); + for (ep = envp; *ep != NULL; ep++) + sudo_putenv(*ep, TRUE, TRUE); } /* @@ -846,33 +645,35 @@ insert_env_vars(env_vars) * Calls log_error() if any specified variables are not allowed. */ void -validate_env_vars(env_vars) - struct list_member *env_vars; +validate_env_vars(char * const env_vars[]) { - struct list_member *var; + char * const *ep; char *eq, *bad = NULL; size_t len, blen = 0, bsize = 0; int okvar; + if (env_vars == NULL) + return; + /* Add user-specified environment variables. */ - for (var = env_vars; var != NULL; var = var->next) { + for (ep = env_vars; *ep != NULL; ep++) { if (def_secure_path && !user_is_exempt() && - strncmp(var->value, "PATH=", 5) == 0) { + strncmp(*ep, "PATH=", 5) == 0) { okvar = FALSE; } else if (def_env_reset) { - okvar = matches_env_check(var->value); + okvar = matches_env_check(*ep); if (okvar == -1) - okvar = matches_env_keep(var->value); + okvar = matches_env_keep(*ep); } else { - okvar = matches_env_delete(var->value) == FALSE; + okvar = matches_env_delete(*ep) == FALSE; if (okvar == FALSE) - okvar = matches_env_check(var->value) != FALSE; + okvar = matches_env_check(*ep) != FALSE; } if (okvar == FALSE) { /* Not allowed, add to error string, allocating as needed. */ - if ((eq = strchr(var->value, '=')) != NULL) + if ((eq = strchr(*ep, '=')) != NULL) *eq = '\0'; - len = strlen(var->value) + 2; + len = strlen(*ep) + 2; if (blen + len >= bsize) { do { bsize += 1024; @@ -880,7 +681,7 @@ validate_env_vars(env_vars) bad = erealloc(bad, bsize); bad[blen] = '\0'; } - strlcat(bad, var->value, bsize); + strlcat(bad, *ep, bsize); strlcat(bad, ", ", bsize); blen += len; if (eq != NULL) @@ -907,9 +708,7 @@ validate_env_vars(env_vars) * character are skipped. */ void -read_env_file(path, overwrite) - const char *path; - int overwrite; +read_env_file(const char *path, int overwrite) { FILE *fp; char *cp, *var, *val; @@ -956,7 +755,7 @@ read_env_file(path, overwrite) } void -init_envtables() +init_envtables(void) { struct list_member *cur; const char **p; diff --git a/find_path.c b/plugins/sudoers/find_path.c similarity index 91% rename from find_path.c rename to plugins/sudoers/find_path.c index fb7fb5f..2566733 100644 --- a/find_path.c +++ b/plugins/sudoers/find_path.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 1998-2005, 2010 + * Copyright (c) 1996, 1998-2005, 2010-2011 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -43,7 +43,7 @@ # include #endif /* HAVE_UNISTD_H */ -#include "sudo.h" +#include "sudoers.h" /* * This function finds the full pathname for a command and @@ -53,12 +53,8 @@ * but it is in '.' and IGNORE_DOT is set. */ int -find_path(infile, outfile, sbp, path, ignore_dot) - char *infile; /* file to find */ - char **outfile; /* result parameter */ - struct stat *sbp; /* stat result parameter */ - char *path; /* path to search */ - int ignore_dot; /* don't check cwd */ +find_path(char *infile, char **outfile, struct stat *sbp, char *path, + int ignore_dot) { static char command[PATH_MAX]; /* qualified filename */ char *n; /* for traversing path */ diff --git a/getdate.c b/plugins/sudoers/getdate.c similarity index 99% rename from getdate.c rename to plugins/sudoers/getdate.c index 7544c3f..cb6aac5 100644 --- a/getdate.c +++ b/plugins/sudoers/getdate.c @@ -110,9 +110,9 @@ static MERIDIAN yyMeridian; static time_t yyRelMonth; static time_t yyRelSeconds; -static int yyerror __P((char *s)); -static int yylex __P((void)); -static int yyparse __P((void)); +static int yyerror(char *s); +static int yylex(void); +static int yyparse(void); #line 107 "getdate.y" #ifndef YYSTYPE_DEFINED diff --git a/getdate.y b/plugins/sudoers/getdate.y similarity index 99% rename from getdate.y rename to plugins/sudoers/getdate.y index 7094083..13483ff 100644 --- a/getdate.y +++ b/plugins/sudoers/getdate.y @@ -98,9 +98,9 @@ static MERIDIAN yyMeridian; static time_t yyRelMonth; static time_t yyRelSeconds; -static int yyerror __P((char *s)); -static int yylex __P((void)); -static int yyparse __P((void)); +static int yyerror(char *s); +static int yylex(void); +static int yyparse(void); %} diff --git a/getspwuid.c b/plugins/sudoers/getspwuid.c similarity index 97% rename from getspwuid.c rename to plugins/sudoers/getspwuid.c index 7a7ffb8..01f4885 100644 --- a/getspwuid.c +++ b/plugins/sudoers/getspwuid.c @@ -65,7 +65,7 @@ # include #endif /* HAVE_GETAUTHUID */ -#include "sudo.h" +#include "sudoers.h" /* * Exported for auth/secureware.c @@ -79,8 +79,7 @@ int crypt_type = INT_MAX; * If shadow passwords are in use, look in the shadow file. */ char * -sudo_getepw(pw) - const struct passwd *pw; +sudo_getepw(const struct passwd *pw) { char *epw = NULL; @@ -147,7 +146,7 @@ done: } void -sudo_setspent() +sudo_setspent(void) { #ifdef HAVE_GETPRPWNAM setprpwent(); @@ -167,7 +166,7 @@ sudo_setspent() } void -sudo_endspent() +sudo_endspent(void) { #ifdef HAVE_GETPRPWNAM endprpwent(); diff --git a/goodpath.c b/plugins/sudoers/goodpath.c similarity index 93% rename from goodpath.c rename to plugins/sudoers/goodpath.c index 45066d3..8d02028 100644 --- a/goodpath.c +++ b/plugins/sudoers/goodpath.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 1998-2005, 2010 + * Copyright (c) 1996, 1998-2005, 2010-2011 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -36,15 +36,13 @@ #endif /* HAVE_UNISTD_H */ #include -#include "sudo.h" +#include "sudoers.h" /* * Verify that path is a normal file and executable by root. */ char * -sudo_goodpath(path, sbp) - const char *path; - struct stat *sbp; +sudo_goodpath(const char *path, struct stat *sbp) { struct stat sb; diff --git a/gram.c b/plugins/sudoers/gram.c similarity index 94% rename from gram.c rename to plugins/sudoers/gram.c index ed7e21b..d95b834 100644 --- a/gram.c +++ b/plugins/sudoers/gram.c @@ -12,7 +12,7 @@ #define YYPREFIX "yy" #line 2 "gram.y" /* - * Copyright (c) 1996, 1998-2005, 2007-2010 + * Copyright (c) 1996, 1998-2005, 2007-2011 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -61,8 +61,9 @@ #endif /* YYBISON && HAVE_ALLOCA_H && !__GNUC__ */ #include -#include "sudo.h" +#include "sudoers.h" /* XXX */ #include "parse.h" +#include "toke.h" /* * We must define SIZE_MAX for yacc's skeleton.c. @@ -94,32 +95,29 @@ struct userspec_list userspecs; /* * Local protoypes */ -static void add_defaults __P((int, struct member *, struct defaults *)); -static void add_userspec __P((struct member *, struct privilege *)); -static struct defaults *new_default __P((char *, char *, int)); -static struct member *new_member __P((char *, int)); - void yyerror __P((const char *)); +static void add_defaults(int, struct member *, struct defaults *); +static void add_userspec(struct member *, struct privilege *); +static struct defaults *new_default(char *, char *, int); +static struct member *new_member(char *, int); + void yyerror(const char *); void -yyerror(s) - const char *s; +yyerror(const char *s) { /* Save the line the first error occurred on. */ if (errorlineno == -1) { errorlineno = sudolineno ? sudolineno - 1 : 0; errorfile = estrdup(sudoers); } - if (verbose && s != NULL) { -#ifndef TRACELEXER - (void) fprintf(stderr, ">>> %s: %s near line %d <<<\n", sudoers, s, + if (trace_print != NULL) { + LEXTRACE("<*> "); + } else if (verbose && s != NULL) { + warningx(">>> %s: %s near line %d <<<", sudoers, s, sudolineno ? sudolineno - 1 : 0); -#else - (void) fprintf(stderr, "<*> "); -#endif } parse_error = TRUE; } -#line 112 "gram.y" +#line 110 "gram.y" #ifndef YYSTYPE_DEFINED #define YYSTYPE_DEFINED typedef union { @@ -135,7 +133,7 @@ typedef union { int tok; } YYSTYPE; #endif /* YYSTYPE_DEFINED */ -#line 138 "y.tab.c" +#line 136 "y.tab.c" #define COMMAND 257 #define ALIAS 258 #define DEFVAR 259 @@ -633,12 +631,9 @@ short *yyss; short *yysslim; YYSTYPE *yyvs; int yystacksize; -#line 606 "gram.y" +#line 604 "gram.y" static struct defaults * -new_default(var, val, op) - char *var; - char *val; - int op; +new_default(char *var, char *val, int op) { struct defaults *d; @@ -655,9 +650,7 @@ new_default(var, val, op) } static struct member * -new_member(name, type) - char *name; - int type; +new_member(char *name, int type) { struct member *m; @@ -676,10 +669,7 @@ new_member(name, type) * runas users the entries apply to (specified by the type). */ static void -add_defaults(type, bmem, defs) - int type; - struct member *bmem; - struct defaults *defs; +add_defaults(int type, struct member *bmem, struct defaults *defs) { struct defaults *d; struct member_list binding; @@ -705,9 +695,7 @@ add_defaults(type, bmem, defs) * and of the userspecs list. */ static void -add_userspec(members, privs) - struct member *members; - struct privilege *privs; +add_userspec(struct member *members, struct privilege *privs) { struct userspec *u; @@ -724,9 +712,7 @@ add_userspec(members, privs) * the current sudoers file to path. */ void -init_parser(path, quiet) - char *path; - int quiet; +init_parser(const char *path, int quiet) { struct defaults *d; struct member *m, *binding; @@ -823,7 +809,7 @@ init_parser(path, quiet) errorfile = NULL; verbose = !quiet; } -#line 774 "y.tab.c" +#line 760 "y.tab.c" /* allocate initial stack or double stack size, up to YYMAXDEPTH */ #if defined(__cplusplus) || defined(__STDC__) static int yygrowstack(void) @@ -1029,127 +1015,127 @@ yyreduce: switch (yyn) { case 1: -#line 187 "gram.y" +#line 185 "gram.y" { ; } break; case 5: -#line 195 "gram.y" +#line 193 "gram.y" { ; } break; case 6: -#line 198 "gram.y" +#line 196 "gram.y" { yyerrok; } break; case 7: -#line 201 "gram.y" +#line 199 "gram.y" { add_userspec(yyvsp[-1].member, yyvsp[0].privilege); } break; case 8: -#line 204 "gram.y" +#line 202 "gram.y" { ; } break; case 9: -#line 207 "gram.y" +#line 205 "gram.y" { ; } break; case 10: -#line 210 "gram.y" +#line 208 "gram.y" { ; } break; case 11: -#line 213 "gram.y" +#line 211 "gram.y" { ; } break; case 12: -#line 216 "gram.y" +#line 214 "gram.y" { add_defaults(DEFAULTS, NULL, yyvsp[0].defaults); } break; case 13: -#line 219 "gram.y" +#line 217 "gram.y" { add_defaults(DEFAULTS_USER, yyvsp[-1].member, yyvsp[0].defaults); } break; case 14: -#line 222 "gram.y" +#line 220 "gram.y" { add_defaults(DEFAULTS_RUNAS, yyvsp[-1].member, yyvsp[0].defaults); } break; case 15: -#line 225 "gram.y" +#line 223 "gram.y" { add_defaults(DEFAULTS_HOST, yyvsp[-1].member, yyvsp[0].defaults); } break; case 16: -#line 228 "gram.y" +#line 226 "gram.y" { add_defaults(DEFAULTS_CMND, yyvsp[-1].member, yyvsp[0].defaults); } break; case 18: -#line 234 "gram.y" +#line 232 "gram.y" { list_append(yyvsp[-2].defaults, yyvsp[0].defaults); yyval.defaults = yyvsp[-2].defaults; } break; case 19: -#line 240 "gram.y" +#line 238 "gram.y" { yyval.defaults = new_default(yyvsp[0].string, NULL, TRUE); } break; case 20: -#line 243 "gram.y" +#line 241 "gram.y" { yyval.defaults = new_default(yyvsp[0].string, NULL, FALSE); } break; case 21: -#line 246 "gram.y" +#line 244 "gram.y" { yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, TRUE); } break; case 22: -#line 249 "gram.y" +#line 247 "gram.y" { yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, '+'); } break; case 23: -#line 252 "gram.y" +#line 250 "gram.y" { yyval.defaults = new_default(yyvsp[-2].string, yyvsp[0].string, '-'); } break; case 25: -#line 258 "gram.y" +#line 256 "gram.y" { list_append(yyvsp[-2].privilege, yyvsp[0].privilege); yyval.privilege = yyvsp[-2].privilege; } break; case 26: -#line 264 "gram.y" +#line 262 "gram.y" { struct privilege *p = emalloc(sizeof(*p)); list2tq(&p->hostlist, yyvsp[-2].member); @@ -1160,51 +1146,51 @@ case 26: } break; case 27: -#line 274 "gram.y" +#line 272 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = FALSE; } break; case 28: -#line 278 "gram.y" +#line 276 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = TRUE; } break; case 29: -#line 284 "gram.y" +#line 282 "gram.y" { yyval.member = new_member(yyvsp[0].string, ALIAS); } break; case 30: -#line 287 "gram.y" +#line 285 "gram.y" { yyval.member = new_member(NULL, ALL); } break; case 31: -#line 290 "gram.y" +#line 288 "gram.y" { yyval.member = new_member(yyvsp[0].string, NETGROUP); } break; case 32: -#line 293 "gram.y" +#line 291 "gram.y" { yyval.member = new_member(yyvsp[0].string, NTWKADDR); } break; case 33: -#line 296 "gram.y" +#line 294 "gram.y" { yyval.member = new_member(yyvsp[0].string, WORD); } break; case 35: -#line 302 "gram.y" +#line 300 "gram.y" { list_append(yyvsp[-2].cmndspec, yyvsp[0].cmndspec); #ifdef HAVE_SELINUX @@ -1237,7 +1223,7 @@ case 35: } break; case 36: -#line 334 "gram.y" +#line 332 "gram.y" { struct cmndspec *cs = emalloc(sizeof(*cs)); if (yyvsp[-3].runas != NULL) { @@ -1264,80 +1250,80 @@ case 36: } break; case 37: -#line 360 "gram.y" +#line 358 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = FALSE; } break; case 38: -#line 364 "gram.y" +#line 362 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = TRUE; } break; case 39: -#line 370 "gram.y" +#line 368 "gram.y" { yyval.string = yyvsp[0].string; } break; case 40: -#line 375 "gram.y" +#line 373 "gram.y" { yyval.string = yyvsp[0].string; } break; case 41: -#line 380 "gram.y" +#line 378 "gram.y" { yyval.seinfo.role = NULL; yyval.seinfo.type = NULL; } break; case 42: -#line 384 "gram.y" +#line 382 "gram.y" { yyval.seinfo.role = yyvsp[0].string; yyval.seinfo.type = NULL; } break; case 43: -#line 388 "gram.y" +#line 386 "gram.y" { yyval.seinfo.type = yyvsp[0].string; yyval.seinfo.role = NULL; } break; case 44: -#line 392 "gram.y" +#line 390 "gram.y" { yyval.seinfo.role = yyvsp[-1].string; yyval.seinfo.type = yyvsp[0].string; } break; case 45: -#line 396 "gram.y" +#line 394 "gram.y" { yyval.seinfo.type = yyvsp[-1].string; yyval.seinfo.role = yyvsp[0].string; } break; case 46: -#line 402 "gram.y" +#line 400 "gram.y" { yyval.runas = NULL; } break; case 47: -#line 405 "gram.y" +#line 403 "gram.y" { yyval.runas = yyvsp[-1].runas; } break; case 48: -#line 410 "gram.y" +#line 408 "gram.y" { yyval.runas = emalloc(sizeof(struct runascontainer)); yyval.runas->runasusers = yyvsp[0].member; @@ -1345,7 +1331,7 @@ case 48: } break; case 49: -#line 415 "gram.y" +#line 413 "gram.y" { yyval.runas = emalloc(sizeof(struct runascontainer)); yyval.runas->runasusers = yyvsp[-2].member; @@ -1353,7 +1339,7 @@ case 49: } break; case 50: -#line 420 "gram.y" +#line 418 "gram.y" { yyval.runas = emalloc(sizeof(struct runascontainer)); yyval.runas->runasusers = NULL; @@ -1361,86 +1347,86 @@ case 50: } break; case 51: -#line 427 "gram.y" +#line 425 "gram.y" { yyval.tag.nopasswd = yyval.tag.noexec = yyval.tag.setenv = yyval.tag.log_input = yyval.tag.log_output = UNSPEC; } break; case 52: -#line 431 "gram.y" +#line 429 "gram.y" { yyval.tag.nopasswd = TRUE; } break; case 53: -#line 434 "gram.y" +#line 432 "gram.y" { yyval.tag.nopasswd = FALSE; } break; case 54: -#line 437 "gram.y" +#line 435 "gram.y" { yyval.tag.noexec = TRUE; } break; case 55: -#line 440 "gram.y" +#line 438 "gram.y" { yyval.tag.noexec = FALSE; } break; case 56: -#line 443 "gram.y" +#line 441 "gram.y" { yyval.tag.setenv = TRUE; } break; case 57: -#line 446 "gram.y" +#line 444 "gram.y" { yyval.tag.setenv = FALSE; } break; case 58: -#line 449 "gram.y" +#line 447 "gram.y" { yyval.tag.log_input = TRUE; } break; case 59: -#line 452 "gram.y" +#line 450 "gram.y" { yyval.tag.log_input = FALSE; } break; case 60: -#line 455 "gram.y" +#line 453 "gram.y" { yyval.tag.log_output = TRUE; } break; case 61: -#line 458 "gram.y" +#line 456 "gram.y" { yyval.tag.log_output = FALSE; } break; case 62: -#line 463 "gram.y" +#line 461 "gram.y" { yyval.member = new_member(NULL, ALL); } break; case 63: -#line 466 "gram.y" +#line 464 "gram.y" { yyval.member = new_member(yyvsp[0].string, ALIAS); } break; case 64: -#line 469 "gram.y" +#line 467 "gram.y" { struct sudo_command *c = emalloc(sizeof(*c)); c->cmnd = yyvsp[0].command.cmnd; @@ -1449,7 +1435,7 @@ case 64: } break; case 67: -#line 481 "gram.y" +#line 479 "gram.y" { char *s; if ((s = alias_add(yyvsp[-2].string, HOSTALIAS, yyvsp[0].member)) != NULL) { @@ -1459,14 +1445,14 @@ case 67: } break; case 69: -#line 491 "gram.y" +#line 489 "gram.y" { list_append(yyvsp[-2].member, yyvsp[0].member); yyval.member = yyvsp[-2].member; } break; case 72: -#line 501 "gram.y" +#line 499 "gram.y" { char *s; if ((s = alias_add(yyvsp[-2].string, CMNDALIAS, yyvsp[0].member)) != NULL) { @@ -1476,14 +1462,14 @@ case 72: } break; case 74: -#line 511 "gram.y" +#line 509 "gram.y" { list_append(yyvsp[-2].member, yyvsp[0].member); yyval.member = yyvsp[-2].member; } break; case 77: -#line 521 "gram.y" +#line 519 "gram.y" { char *s; if ((s = alias_add(yyvsp[-2].string, RUNASALIAS, yyvsp[0].member)) != NULL) { @@ -1493,7 +1479,7 @@ case 77: } break; case 80: -#line 534 "gram.y" +#line 532 "gram.y" { char *s; if ((s = alias_add(yyvsp[-2].string, USERALIAS, yyvsp[0].member)) != NULL) { @@ -1503,96 +1489,96 @@ case 80: } break; case 82: -#line 544 "gram.y" +#line 542 "gram.y" { list_append(yyvsp[-2].member, yyvsp[0].member); yyval.member = yyvsp[-2].member; } break; case 83: -#line 550 "gram.y" +#line 548 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = FALSE; } break; case 84: -#line 554 "gram.y" +#line 552 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = TRUE; } break; case 85: -#line 560 "gram.y" +#line 558 "gram.y" { yyval.member = new_member(yyvsp[0].string, ALIAS); } break; case 86: -#line 563 "gram.y" +#line 561 "gram.y" { yyval.member = new_member(NULL, ALL); } break; case 87: -#line 566 "gram.y" +#line 564 "gram.y" { yyval.member = new_member(yyvsp[0].string, NETGROUP); } break; case 88: -#line 569 "gram.y" +#line 567 "gram.y" { yyval.member = new_member(yyvsp[0].string, USERGROUP); } break; case 89: -#line 572 "gram.y" +#line 570 "gram.y" { yyval.member = new_member(yyvsp[0].string, WORD); } break; case 91: -#line 578 "gram.y" +#line 576 "gram.y" { list_append(yyvsp[-2].member, yyvsp[0].member); yyval.member = yyvsp[-2].member; } break; case 92: -#line 584 "gram.y" +#line 582 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = FALSE; } break; case 93: -#line 588 "gram.y" +#line 586 "gram.y" { yyval.member = yyvsp[0].member; yyval.member->negated = TRUE; } break; case 94: -#line 594 "gram.y" +#line 592 "gram.y" { yyval.member = new_member(yyvsp[0].string, ALIAS); } break; case 95: -#line 597 "gram.y" +#line 595 "gram.y" { yyval.member = new_member(NULL, ALL); } break; case 96: -#line 600 "gram.y" +#line 598 "gram.y" { yyval.member = new_member(yyvsp[0].string, WORD); } break; -#line 1543 "y.tab.c" +#line 1529 "y.tab.c" } yyssp -= yym; yystate = *yyssp; diff --git a/gram.h b/plugins/sudoers/gram.h similarity index 100% rename from gram.h rename to plugins/sudoers/gram.h diff --git a/gram.y b/plugins/sudoers/gram.y similarity index 94% rename from gram.y rename to plugins/sudoers/gram.y index 9a07ee7..b1eed89 100644 --- a/gram.y +++ b/plugins/sudoers/gram.y @@ -1,6 +1,6 @@ %{ /* - * Copyright (c) 1996, 1998-2005, 2007-2010 + * Copyright (c) 1996, 1998-2005, 2007-2011 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -49,8 +49,9 @@ #endif /* YYBISON && HAVE_ALLOCA_H && !__GNUC__ */ #include -#include "sudo.h" +#include "sudoers.h" /* XXX */ #include "parse.h" +#include "toke.h" /* * We must define SIZE_MAX for yacc's skeleton.c. @@ -82,28 +83,25 @@ struct userspec_list userspecs; /* * Local protoypes */ -static void add_defaults __P((int, struct member *, struct defaults *)); -static void add_userspec __P((struct member *, struct privilege *)); -static struct defaults *new_default __P((char *, char *, int)); -static struct member *new_member __P((char *, int)); - void yyerror __P((const char *)); +static void add_defaults(int, struct member *, struct defaults *); +static void add_userspec(struct member *, struct privilege *); +static struct defaults *new_default(char *, char *, int); +static struct member *new_member(char *, int); + void yyerror(const char *); void -yyerror(s) - const char *s; +yyerror(const char *s) { /* Save the line the first error occurred on. */ if (errorlineno == -1) { errorlineno = sudolineno ? sudolineno - 1 : 0; errorfile = estrdup(sudoers); } - if (verbose && s != NULL) { -#ifndef TRACELEXER - (void) fprintf(stderr, ">>> %s: %s near line %d <<<\n", sudoers, s, + if (trace_print != NULL) { + LEXTRACE("<*> "); + } else if (verbose && s != NULL) { + warningx(">>> %s: %s near line %d <<<", sudoers, s, sudolineno ? sudolineno - 1 : 0); -#else - (void) fprintf(stderr, "<*> "); -#endif } parse_error = TRUE; } @@ -604,10 +602,7 @@ group : ALIAS { %% static struct defaults * -new_default(var, val, op) - char *var; - char *val; - int op; +new_default(char *var, char *val, int op) { struct defaults *d; @@ -624,9 +619,7 @@ new_default(var, val, op) } static struct member * -new_member(name, type) - char *name; - int type; +new_member(char *name, int type) { struct member *m; @@ -645,10 +638,7 @@ new_member(name, type) * runas users the entries apply to (specified by the type). */ static void -add_defaults(type, bmem, defs) - int type; - struct member *bmem; - struct defaults *defs; +add_defaults(int type, struct member *bmem, struct defaults *defs) { struct defaults *d; struct member_list binding; @@ -674,9 +664,7 @@ add_defaults(type, bmem, defs) * and of the userspecs list. */ static void -add_userspec(members, privs) - struct member *members; - struct privilege *privs; +add_userspec(struct member *members, struct privilege *privs) { struct userspec *u; @@ -693,9 +681,7 @@ add_userspec(members, privs) * the current sudoers file to path. */ void -init_parser(path, quiet) - char *path; - int quiet; +init_parser(const char *path, int quiet) { struct defaults *d; struct member *m, *binding; diff --git a/plugins/sudoers/group_plugin.c b/plugins/sudoers/group_plugin.c new file mode 100644 index 0000000..bd5203a --- /dev/null +++ b/plugins/sudoers/group_plugin.c @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2010 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#if defined(HAVE_DLOPEN) || defined(HAVE_SHL_LOAD) + +#include +#include +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#if TIME_WITH_SYS_TIME +# include +#endif +#ifdef HAVE_DLOPEN +# include +#else +# include "compat/dlfcn.h" +#endif +#include +#include +#include + +#include "sudoers.h" + +#ifndef RTLD_LOCAL +# define RTLD_LOCAL 0 +#endif + +static void *group_handle; +static struct sudoers_group_plugin *group_plugin; + +/* + * Load the specified plugin and run its init function. + * Returns -1 if unable to open the plugin, else it returns + * the value from the plugin's init function. + */ +int +group_plugin_load(char *plugin_info) +{ + struct stat sb; + char *args, path[PATH_MAX]; + char **argv = NULL; + int len, rc = -1; + + /* + * Fill in .so path and split out args (if any). + */ + args = strpbrk(plugin_info, " \t"); + if ((args = strpbrk(plugin_info, " \t")) != NULL) { + len = snprintf(path, sizeof(path), "%s%.*s", + (*plugin_info != '/') ? _PATH_SUDO_PLUGIN_DIR : "", + (int)(args - plugin_info), plugin_info); + args++; + } else { + len = snprintf(path, sizeof(path), "%s%s", + (*plugin_info != '/') ? _PATH_SUDO_PLUGIN_DIR : "", plugin_info); + } + if (len <= 0 || len >= sizeof(path)) { + warningx("%s%s: %s", + (*plugin_info != '/') ? _PATH_SUDO_PLUGIN_DIR : "", plugin_info, + strerror(ENAMETOOLONG)); + goto done; + } + + /* Sanity check plugin path. */ + if (stat(path, &sb) != 0) { + warning("%s", path); + goto done; + } + if (sb.st_uid != ROOT_UID) { + warningx("%s must be owned by uid %d", path, ROOT_UID); + goto done; + } + if ((sb.st_mode & (S_IWGRP|S_IWOTH)) != 0) { + warningx("%s must be only be writable by owner", path); + goto done; + } + + /* Open plugin and map in symbol. */ + group_handle = dlopen(path, RTLD_LAZY|RTLD_LOCAL); + if (!group_handle) { + warningx("unable to dlopen %s: %s", path, dlerror()); + goto done; + } + group_plugin = dlsym(group_handle, "group_plugin"); + if (group_plugin == NULL) { + warningx("unable to find symbol \"group_plugin\" in %s", path); + goto done; + } + + if (GROUP_API_VERSION_GET_MAJOR(group_plugin->version) != GROUP_API_VERSION_MAJOR) { + warningx("%s: incompatible group plugin major version %d, expected %d", + path, GROUP_API_VERSION_GET_MAJOR(group_plugin->version), + GROUP_API_VERSION_MAJOR); + goto done; + } + + /* + * Split args into a vector if specified. + */ + if (args != NULL) { + int ac = 0, wasblank = TRUE; + char *cp; + + for (cp = args; *cp != '\0'; cp++) { + if (isblank((unsigned char)*cp)) { + wasblank = TRUE; + } else if (wasblank) { + wasblank = FALSE; + ac++; + } + } + if (ac != 0) { + argv = emalloc2(ac, sizeof(char *)); + ac = 0; + for ((cp = strtok(args, " \t")); cp; (cp = strtok(NULL, " \t"))) + argv[ac++] = cp; + } + } + + rc = (group_plugin->init)(GROUP_API_VERSION, sudo_printf, argv); + +done: + efree(argv); + + if (rc != TRUE) { + if (group_handle != NULL) { + dlclose(group_handle); + group_handle = NULL; + group_plugin = NULL; + } + } + + return rc; +} + +void +group_plugin_unload(void) +{ + if (group_plugin != NULL) { + (group_plugin->cleanup)(); + group_plugin = NULL; + } + if (group_handle != NULL) { + dlclose(group_handle); + group_handle = NULL; + } +} + +int +group_plugin_query(const char *user, const char *group, + const struct passwd *pwd) +{ + if (group_plugin == NULL) + return FALSE; + return (group_plugin->query)(user, group, pwd); +} + +#else /* !HAVE_DLOPEN && !HAVE_SHL_LOAD */ + +/* + * No loadable shared object support. + */ + +#ifndef FALSE +#define FALSE 0 +#endif + +struct passwd; + +int +group_plugin_load(char *plugin_info) +{ + return FALSE; +} + +void +group_plugin_unload(void) +{ + return; +} + +int +group_plugin_query(const char *user, const char *group, + const struct passwd *pwd) +{ + return FALSE; +} + +#endif /* HAVE_DLOPEN || HAVE_SHL_LOAD */ diff --git a/ins_2001.h b/plugins/sudoers/ins_2001.h similarity index 100% rename from ins_2001.h rename to plugins/sudoers/ins_2001.h diff --git a/ins_classic.h b/plugins/sudoers/ins_classic.h similarity index 100% rename from ins_classic.h rename to plugins/sudoers/ins_classic.h diff --git a/ins_csops.h b/plugins/sudoers/ins_csops.h similarity index 100% rename from ins_csops.h rename to plugins/sudoers/ins_csops.h diff --git a/ins_goons.h b/plugins/sudoers/ins_goons.h similarity index 100% rename from ins_goons.h rename to plugins/sudoers/ins_goons.h diff --git a/insults.h b/plugins/sudoers/insults.h similarity index 100% rename from insults.h rename to plugins/sudoers/insults.h diff --git a/plugins/sudoers/interfaces.c b/plugins/sudoers/interfaces.c new file mode 100644 index 0000000..acf0568 --- /dev/null +++ b/plugins/sudoers/interfaces.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2010 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS) +# include +# endif +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#include +#include +#include +#include + +#include "sudoers.h" +#include "interfaces.h" + +#ifndef INADDR_NONE +# define INADDR_NONE ((unsigned int)-1) +#endif + +/* + * Parse a space-delimited list of IP address/netmask pairs and + * store in a list of interface structures. + */ +void +set_interfaces(const char *ai) +{ + char *addrinfo, *addr, *mask; + struct interface *ifp; + + addrinfo = estrdup(ai); + for (addr = strtok(addrinfo, " \t"); addr != NULL; addr = strtok(NULL, " \t")) { + /* Separate addr and mask. */ + if ((mask = strchr(addr, '/')) == NULL) + continue; + *mask++ = '\0'; + + /* Parse addr and store in list. */ + ifp = emalloc(sizeof(*ifp)); + if (strchr(addr, ':')) { + /* IPv6 */ +#ifdef HAVE_IN6_ADDR + ifp->family = AF_INET6; + if (inet_pton(AF_INET6, addr, &ifp->addr.ip6) != 1 || + inet_pton(AF_INET6, mask, &ifp->netmask.ip6) != 1) +#endif + { + efree(ifp); + continue; + } + } else { + /* IPv4 */ + ifp->family = AF_INET; + ifp->addr.ip4.s_addr = inet_addr(addr); + ifp->netmask.ip4.s_addr = inet_addr(mask); + if (ifp->addr.ip4.s_addr == INADDR_NONE || + ifp->netmask.ip4.s_addr == INADDR_NONE) { + efree(ifp); + continue; + } + } + ifp->next = interfaces; + interfaces = ifp; + } + efree(addrinfo); +} + +void +dump_interfaces(const char *ai) +{ + char *cp, *addrinfo; + + addrinfo = estrdup(ai); + + sudo_printf(SUDO_CONV_INFO_MSG, "Local IP address and netmask pairs:\n"); + for (cp = strtok(addrinfo, " \t"); cp != NULL; cp = strtok(NULL, " \t")) + sudo_printf(SUDO_CONV_INFO_MSG, "\t%s\n", cp); + + efree(addrinfo); +} diff --git a/interfaces.h b/plugins/sudoers/interfaces.h similarity index 89% rename from interfaces.h rename to plugins/sudoers/interfaces.h index 06b0b85..234d31d 100644 --- a/interfaces.h +++ b/plugins/sudoers/interfaces.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 1998-2005, 2007 + * Copyright (c) 1996, 1998-2005, 2007, 2010 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -39,20 +39,21 @@ struct interface { int family; /* AF_INET or AF_INET6 */ union sudo_in_addr_un addr; union sudo_in_addr_un netmask; + struct interface *next; }; /* * Prototypes for external functions. */ -void load_interfaces __P((void)); -void dump_interfaces __P((void)); +int get_net_ifs(char **addrinfo); +void dump_interfaces(const char *); +void set_interfaces(const char *); /* * Definitions for external variables. */ #ifndef _SUDO_MAIN extern struct interface *interfaces; -extern int num_interfaces; #endif #endif /* _SUDO_INTERFACES_H */ diff --git a/plugins/sudoers/iolog.c b/plugins/sudoers/iolog.c new file mode 100644 index 0000000..903aedf --- /dev/null +++ b/plugins/sudoers/iolog.c @@ -0,0 +1,670 @@ +/* + * Copyright (c) 2009-2011 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#if TIME_WITH_SYS_TIME +# include +#endif +#include +#include +#include +#include +#include +#include +#ifdef HAVE_ZLIB_H +# include +#endif + +#include "sudoers.h" + +/* plugin_error.c */ +extern sigjmp_buf error_jmp; + +union io_fd { + FILE *f; +#ifdef HAVE_ZLIB_H + gzFile g; +#endif + void *v; +}; + +struct script_buf { + int len; /* buffer length (how much read in) */ + int off; /* write position (how much already consumed) */ + char buf[16 * 1024]; +}; + +/* XXX - separate sudoers.h and iolog.h? */ +#undef runas_pw +#undef runas_gr + +struct iolog_details { + const char *cwd; + const char *tty; + const char *user; + const char *command; + const char *iolog_path; + struct passwd *runas_pw; + struct group *runas_gr; + int iolog_stdin; + int iolog_stdout; + int iolog_stderr; + int iolog_ttyin; + int iolog_ttyout; +}; + +#define IOFD_STDIN 0 +#define IOFD_STDOUT 1 +#define IOFD_STDERR 2 +#define IOFD_TTYIN 3 +#define IOFD_TTYOUT 4 +#define IOFD_TIMING 5 +#define IOFD_MAX 6 + +#define SESSID_MAX 2176782336U + +static int iolog_compress; +static struct timeval last_time; +static union io_fd io_fds[IOFD_MAX]; +extern struct io_plugin sudoers_io; + +/* + * Create parent directories for path as needed, but not path itself. + */ +static void +mkdir_parents(char *path) +{ + struct stat sb; + char *slash = path; + + for (;;) { + if ((slash = strchr(slash + 1, '/')) == NULL) + break; + *slash = '\0'; + if (stat(path, &sb) != 0) { + if (mkdir(path, S_IRWXU) != 0) + log_error(USE_ERRNO, "Can't mkdir %s", path); + } else if (!S_ISDIR(sb.st_mode)) { + log_error(0, "%s: %s", path, strerror(ENOTDIR)); + } + *slash = '/'; + } +} + +/* + * Read the on-disk sequence number, set sessid to the next + * number, and update the on-disk copy. + * Uses file locking to avoid sequence number collisions. + */ +void +io_nextid(char *iolog_dir, char sessid[7]) +{ + struct stat sb; + char buf[32], *ep; + int fd, i; + unsigned long id = 0; + int len; + ssize_t nread; + char pathbuf[PATH_MAX]; + static const char b36char[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + + /* + * Create I/O log directory if it doesn't already exist. + */ + mkdir_parents(iolog_dir); + if (stat(iolog_dir, &sb) != 0) { + if (mkdir(iolog_dir, S_IRWXU) != 0) + log_error(USE_ERRNO, "Can't mkdir %s", iolog_dir); + } else if (!S_ISDIR(sb.st_mode)) { + log_error(0, "%s exists but is not a directory (0%o)", + iolog_dir, (unsigned int) sb.st_mode); + } + + /* + * Open sequence file + */ + len = snprintf(pathbuf, sizeof(pathbuf), "%s/seq", iolog_dir); + if (len <= 0 || len >= sizeof(pathbuf)) { + errno = ENAMETOOLONG; + log_error(USE_ERRNO, "%s/seq", pathbuf); + } + fd = open(pathbuf, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR); + if (fd == -1) + log_error(USE_ERRNO, "cannot open %s", pathbuf); + lock_file(fd, SUDO_LOCK); + + /* Read seq number (base 36). */ + nread = read(fd, buf, sizeof(buf)); + if (nread != 0) { + if (nread == -1) + log_error(USE_ERRNO, "cannot read %s", pathbuf); + id = strtoul(buf, &ep, 36); + if (buf == ep || id >= SESSID_MAX) + log_error(0, "invalid sequence number %s", pathbuf); + } + id++; + + /* + * Convert id to a string and stash in sessid. + * Note that that least significant digits go at the end of the string. + */ + for (i = 5; i >= 0; i--) { + buf[i] = b36char[id % 36]; + id /= 36; + } + buf[6] = '\n'; + + /* Stash id logging purposes */ + memcpy(sessid, buf, 6); + sessid[6] = '\0'; + + /* Rewind and overwrite old seq file. */ + if (lseek(fd, 0, SEEK_SET) == (off_t)-1 || write(fd, buf, 7) != 7) + log_error(USE_ERRNO, "Can't write to %s", pathbuf); + close(fd); +} + +/* + * Copy iolog_path to pathbuf and create the directory and any intermediate + * directories. If iolog_path ends in 'XXXXXX', use mkdtemp(). + */ +static size_t +mkdir_iopath(const char *iolog_path, char *pathbuf, size_t pathsize) +{ + size_t len; + + len = strlcpy(pathbuf, iolog_path, pathsize); + if (len >= pathsize) { + errno = ENAMETOOLONG; + log_error(USE_ERRNO, "%s", iolog_path); + } + + /* + * Create path and intermediate subdirs as needed. + * If path ends in at least 6 Xs (ala POSIX mktemp), use mkdtemp(). + */ + mkdir_parents(pathbuf); + if (len >= 6 && strcmp(&pathbuf[len - 6], "XXXXXX") == 0) { + if (mkdtemp(pathbuf) == NULL) + log_error(USE_ERRNO, "Can't create %s", pathbuf); + } else { + if (mkdir(pathbuf, S_IRWXU) != 0) + log_error(USE_ERRNO, "Can't create %s", pathbuf); + } + + return len; +} + +/* + * Append suffix to pathbuf after len chars and open the resulting file. + * Note that the size of pathbuf is assumed to be PATH_MAX. + * Uses zlib if docompress is TRUE. + * Returns the open file handle which has the close-on-exec flag set. + */ +static void * +open_io_fd(char *pathbuf, size_t len, const char *suffix, int docompress) +{ + void *vfd = NULL; + int fd; + + pathbuf[len] = '\0'; + strlcat(pathbuf, suffix, PATH_MAX); + fd = open(pathbuf, O_CREAT|O_EXCL|O_WRONLY, S_IRUSR|S_IWUSR); + if (fd != -1) { + fcntl(fd, F_SETFD, FD_CLOEXEC); +#ifdef HAVE_ZLIB_H + if (docompress) + vfd = gzdopen(fd, "w"); + else +#endif + vfd = fdopen(fd, "w"); + } + return vfd; +} + +/* + * Pull out I/O log related data from user_info and command_info arrays. + */ +static void +iolog_deserialize_info(struct iolog_details *details, char * const user_info[], + char * const command_info[]) +{ + const char *runas_uid_str = "0", *runas_euid_str = NULL; + const char *runas_gid_str = "0", *runas_egid_str = NULL; + char id[MAX_UID_T_LEN + 2], *ep; + char * const *cur; + unsigned long ulval; + uid_t runas_uid = 0; + gid_t runas_gid = 0; + + memset(details, 0, sizeof(*details)); + + for (cur = user_info; *cur != NULL; cur++) { + switch (**cur) { + case 'c': + if (strncmp(*cur, "cwd=", sizeof("cwd=") - 1) == 0) { + details->cwd = *cur + sizeof("cwd=") - 1; + continue; + } + break; + case 't': + if (strncmp(*cur, "tty=", sizeof("tty=") - 1) == 0) { + details->tty = *cur + sizeof("tty=") - 1; + continue; + } + break; + case 'u': + if (strncmp(*cur, "user=", sizeof("user=") - 1) == 0) { + details->user = *cur + sizeof("user=") - 1; + continue; + } + break; + } + } + + for (cur = command_info; *cur != NULL; cur++) { + switch (**cur) { + case 'c': + if (strncmp(*cur, "command=", sizeof("command=") - 1) == 0) { + details->command = *cur + sizeof("command=") - 1; + continue; + } + break; + case 'i': + if (strncmp(*cur, "iolog_path=", sizeof("iolog_path=") - 1) == 0) { + details->iolog_path = *cur + sizeof("iolog_path=") - 1; + continue; + } + if (strncmp(*cur, "iolog_stdin=", sizeof("iolog_stdin=") - 1) == 0) { + if (atobool(*cur + sizeof("iolog_stdin=") - 1) == TRUE) + details->iolog_stdin = TRUE; + continue; + } + if (strncmp(*cur, "iolog_stdout=", sizeof("iolog_stdout=") - 1) == 0) { + if (atobool(*cur + sizeof("iolog_stdout=") - 1) == TRUE) + details->iolog_stdout = TRUE; + continue; + } + if (strncmp(*cur, "iolog_stderr=", sizeof("iolog_stderr=") - 1) == 0) { + if (atobool(*cur + sizeof("iolog_stderr=") - 1) == TRUE) + details->iolog_stderr = TRUE; + continue; + } + if (strncmp(*cur, "iolog_ttyin=", sizeof("iolog_ttyin=") - 1) == 0) { + if (atobool(*cur + sizeof("iolog_ttyin=") - 1) == TRUE) + details->iolog_ttyin = TRUE; + continue; + } + if (strncmp(*cur, "iolog_ttyout=", sizeof("iolog_ttyout=") - 1) == 0) { + if (atobool(*cur + sizeof("iolog_ttyout=") - 1) == TRUE) + details->iolog_ttyout = TRUE; + continue; + } + if (strncmp(*cur, "iolog_compress=", sizeof("iolog_compress=") - 1) == 0) { + if (atobool(*cur + sizeof("iolog_compress=") - 1) == TRUE) + iolog_compress = TRUE; /* must be global */ + continue; + } + break; + case 'r': + if (strncmp(*cur, "runas_gid=", sizeof("runas_gid=") - 1) == 0) { + runas_gid_str = *cur + sizeof("runas_gid=") - 1; + continue; + } + if (strncmp(*cur, "runas_egid=", sizeof("runas_egid=") - 1) == 0) { + runas_egid_str = *cur + sizeof("runas_egid=") - 1; + continue; + } + if (strncmp(*cur, "runas_uid=", sizeof("runas_uid=") - 1) == 0) { + runas_uid_str = *cur + sizeof("runas_uid=") - 1; + continue; + } + if (strncmp(*cur, "runas_euid=", sizeof("runas_euid=") - 1) == 0) { + runas_euid_str = *cur + sizeof("runas_euid=") - 1; + continue; + } + break; + } + } + + /* + * Lookup runas user and group, preferring effective over real uid/gid. + */ + if (runas_euid_str != NULL) + runas_uid_str = runas_euid_str; + if (runas_uid_str != NULL) { + errno = 0; + ulval = strtoul(runas_uid_str, &ep, 0); + if (*runas_uid_str != '\0' && *ep == '\0' && + (errno != ERANGE || ulval != ULONG_MAX)) { + runas_uid = (uid_t)ulval; + } + } + if (runas_egid_str != NULL) + runas_gid_str = runas_egid_str; + if (runas_gid_str != NULL) { + errno = 0; + ulval = strtoul(runas_gid_str, &ep, 0); + if (*runas_gid_str != '\0' && *ep == '\0' && + (errno != ERANGE || ulval != ULONG_MAX)) { + runas_gid = (gid_t)ulval; + } + } + + details->runas_pw = sudo_getpwuid(runas_uid); + if (details->runas_pw == NULL) { + id[0] = '#'; + strlcpy(&id[1], runas_uid_str, sizeof(id) - 1); + details->runas_pw = sudo_fakepwnam(id, runas_gid); + } + + if (runas_gid != details->runas_pw->pw_gid) { + details->runas_gr = sudo_getgrgid(runas_gid); + if (details->runas_gr == NULL) { + id[0] = '#'; + strlcpy(&id[1], runas_gid_str, sizeof(id) - 1); + details->runas_gr = sudo_fakegrnam(id); + } + } +} + +static int +sudoers_io_open(unsigned int version, sudo_conv_t conversation, + sudo_printf_t plugin_printf, char * const settings[], + char * const user_info[], char * const command_info[], + int argc, char * const argv[], char * const user_env[]) +{ + struct iolog_details details; + char pathbuf[PATH_MAX], sessid[7]; + char *tofree = NULL; + char * const *cur; + FILE *io_logfile; + size_t len; + int rval = -1; + + if (!sudo_conv) + sudo_conv = conversation; + if (!sudo_printf) + sudo_printf = plugin_printf; + + /* If we have no command (because -V was specified) just return. */ + if (argc == 0) + return TRUE; + + if (sigsetjmp(error_jmp, 1)) { + /* called via error(), errorx() or log_error() */ + rval = -1; + goto done; + } + + sudo_setpwent(); + sudo_setgrent(); + + /* + * Pull iolog settings out of command_info, if any. + */ + iolog_deserialize_info(&details, user_info, command_info); + /* Did policy module disable I/O logging? */ + if (!details.iolog_stdin && !details.iolog_ttyin && + !details.iolog_stdout && !details.iolog_stderr && + !details.iolog_ttyout) { + rval = FALSE; + goto done; + } + + /* If no I/O log path defined we need to figure it out ourselves. */ + if (details.iolog_path == NULL) { + /* Get next session ID and convert it into a path. */ + tofree = emalloc(sizeof(_PATH_SUDO_IO_LOGDIR) + sizeof(sessid) + 2); + memcpy(tofree, _PATH_SUDO_IO_LOGDIR, sizeof(_PATH_SUDO_IO_LOGDIR)); + io_nextid(tofree, sessid); + snprintf(tofree + sizeof(_PATH_SUDO_IO_LOGDIR), sizeof(sessid) + 2, + "%c%c/%c%c/%c%c", sessid[0], sessid[1], sessid[2], sessid[3], + sessid[4], sessid[5]); + details.iolog_path = tofree; + } + + /* + * Make local copy of I/O log path and create it, along with any + * intermediate subdirs. Calls mkdtemp() if iolog_path ends in XXXXXX. + */ + len = mkdir_iopath(details.iolog_path, pathbuf, sizeof(pathbuf)); + if (len >= sizeof(pathbuf)) + goto done; + + /* + * We create 7 files: a log file, a timing file and 5 for input/output. + */ + io_logfile = open_io_fd(pathbuf, len, "/log", FALSE); + if (io_logfile == NULL) + log_error(USE_ERRNO, "Can't create %s", pathbuf); + + io_fds[IOFD_TIMING].v = open_io_fd(pathbuf, len, "/timing", + iolog_compress); + if (io_fds[IOFD_TIMING].v == NULL) + log_error(USE_ERRNO, "Can't create %s", pathbuf); + + if (details.iolog_ttyin) { + io_fds[IOFD_TTYIN].v = open_io_fd(pathbuf, len, "/ttyin", + iolog_compress); + if (io_fds[IOFD_TTYIN].v == NULL) + log_error(USE_ERRNO, "Can't create %s", pathbuf); + } else { + sudoers_io.log_ttyin = NULL; + } + if (details.iolog_stdin) { + io_fds[IOFD_STDIN].v = open_io_fd(pathbuf, len, "/stdin", + iolog_compress); + if (io_fds[IOFD_STDIN].v == NULL) + log_error(USE_ERRNO, "Can't create %s", pathbuf); + } else { + sudoers_io.log_stdin = NULL; + } + if (details.iolog_ttyout) { + io_fds[IOFD_TTYOUT].v = open_io_fd(pathbuf, len, "/ttyout", + iolog_compress); + if (io_fds[IOFD_TTYOUT].v == NULL) + log_error(USE_ERRNO, "Can't create %s", pathbuf); + } else { + sudoers_io.log_ttyout = NULL; + } + if (details.iolog_stdout) { + io_fds[IOFD_STDOUT].v = open_io_fd(pathbuf, len, "/stdout", + iolog_compress); + if (io_fds[IOFD_STDOUT].v == NULL) + log_error(USE_ERRNO, "Can't create %s", pathbuf); + } else { + sudoers_io.log_stdout = NULL; + } + if (details.iolog_stderr) { + io_fds[IOFD_STDERR].v = open_io_fd(pathbuf, len, "/stderr", + iolog_compress); + if (io_fds[IOFD_STDERR].v == NULL) + log_error(USE_ERRNO, "Can't create %s", pathbuf); + } else { + sudoers_io.log_stderr = NULL; + } + + gettimeofday(&last_time, NULL); + + fprintf(io_logfile, "%ld:%s:%s:%s:%s\n", (long)last_time.tv_sec, + details.user ? details.user : "unknown", details.runas_pw->pw_name, + details.runas_gr ? details.runas_gr->gr_name : "", + details.tty ? details.tty : "unknown"); + fputs(details.cwd ? details.cwd : "unknown", io_logfile); + fputc('\n', io_logfile); + fputs(details.command ? details.command : "unknown", io_logfile); + for (cur = &argv[1]; *cur != NULL; cur++) { + if (cur != &argv[1]) + fputc(' ', io_logfile); + fputs(*cur, io_logfile); + } + fputc('\n', io_logfile); + fclose(io_logfile); + + rval = TRUE; + +done: + efree(tofree); + if (details.runas_pw) + pw_delref(details.runas_pw); + sudo_endpwent(); + if (details.runas_gr) + gr_delref(details.runas_gr); + sudo_endgrent(); + + return rval; +} + +static void +sudoers_io_close(int exit_status, int error) +{ + int i; + + if (sigsetjmp(error_jmp, 1)) { + /* called via error(), errorx() or log_error() */ + return; + } + + for (i = 0; i < IOFD_MAX; i++) { + if (io_fds[i].v == NULL) + continue; +#ifdef HAVE_ZLIB_H + if (iolog_compress) + gzclose(io_fds[i].g); + else +#endif + fclose(io_fds[i].f); + } +} + +static int +sudoers_io_version(int verbose) +{ + if (sigsetjmp(error_jmp, 1)) { + /* called via error(), errorx() or log_error() */ + return -1; + } + + sudo_printf(SUDO_CONV_INFO_MSG, "Sudoers I/O plugin version %s\n", + PACKAGE_VERSION); + + return TRUE; +} + +/* + * Generic I/O logging function. Called by the I/O logging entry points. + */ +static int +sudoers_io_log(const char *buf, unsigned int len, int idx) +{ + struct timeval now, delay; + + gettimeofday(&now, NULL); + + if (sigsetjmp(error_jmp, 1)) { + /* called via error(), errorx() or log_error() */ + return -1; + } + +#ifdef HAVE_ZLIB_H + if (iolog_compress) + gzwrite(io_fds[idx].g, buf, len); + else +#endif + fwrite(buf, 1, len, io_fds[idx].f); + delay.tv_sec = now.tv_sec; + delay.tv_usec = now.tv_usec; + timevalsub(&delay, &last_time); +#ifdef HAVE_ZLIB_H + if (iolog_compress) + gzprintf(io_fds[IOFD_TIMING].g, "%d %f %d\n", idx, + delay.tv_sec + ((double)delay.tv_usec / 1000000), len); + else +#endif + fprintf(io_fds[IOFD_TIMING].f, "%d %f %d\n", idx, + delay.tv_sec + ((double)delay.tv_usec / 1000000), len); + last_time.tv_sec = now.tv_sec; + last_time.tv_usec = now.tv_usec; + + return TRUE; +} + +static int +sudoers_io_log_ttyin(const char *buf, unsigned int len) +{ + return sudoers_io_log(buf, len, IOFD_TTYIN); +} + +static int +sudoers_io_log_ttyout(const char *buf, unsigned int len) +{ + return sudoers_io_log(buf, len, IOFD_TTYOUT); +} + +static int +sudoers_io_log_stdin(const char *buf, unsigned int len) +{ + return sudoers_io_log(buf, len, IOFD_STDIN); +} + +static int +sudoers_io_log_stdout(const char *buf, unsigned int len) +{ + return sudoers_io_log(buf, len, IOFD_STDOUT); +} + +static int +sudoers_io_log_stderr(const char *buf, unsigned int len) +{ + return sudoers_io_log(buf, len, IOFD_STDERR); +} + +struct io_plugin sudoers_io = { + SUDO_IO_PLUGIN, + SUDO_API_VERSION, + sudoers_io_open, + sudoers_io_close, + sudoers_io_version, + sudoers_io_log_ttyin, + sudoers_io_log_ttyout, + sudoers_io_log_stdin, + sudoers_io_log_stdout, + sudoers_io_log_stderr +}; diff --git a/plugins/sudoers/iolog_path.c b/plugins/sudoers/iolog_path.c new file mode 100644 index 0000000..74f5fdf --- /dev/null +++ b/plugins/sudoers/iolog_path.c @@ -0,0 +1,266 @@ +/* + * Copyright (c) 2011 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS) +# include +# endif +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#ifdef HAVE_SETLOCALE +# include +#endif +#include +#include +#include + +#include "sudoers.h" + +struct path_escape { + const char *name; + size_t (*copy_fn)(char *, size_t); +}; + +static size_t fill_seq(char *, size_t); +static size_t fill_user(char *, size_t); +static size_t fill_group(char *, size_t); +static size_t fill_runas_user(char *, size_t); +static size_t fill_runas_group(char *, size_t); +static size_t fill_hostname(char *, size_t); +static size_t fill_command(char *, size_t); + +static struct path_escape escapes[] = { + { "seq", fill_seq }, + { "user", fill_user }, + { "group", fill_group }, + { "runas_user", fill_runas_user }, + { "runas_group", fill_runas_group }, + { "hostname", fill_hostname }, + { "command", fill_command }, + { NULL, NULL } +}; + +static size_t +fill_seq(char *str, size_t strsize) +{ + static char sessid[7]; + int len; + + if (sessid[0] == '\0') + io_nextid(def_iolog_dir, sessid); + + /* Path is of the form /var/log/sudo-io/00/00/01. */ + len = snprintf(str, strsize, "%c%c/%c%c/%c%c", sessid[0], + sessid[1], sessid[2], sessid[3], sessid[4], sessid[5]); + if (len < 0) + return strsize; /* handle non-standard snprintf() */ + return (size_t)len; +} + +static size_t +fill_user(char *str, size_t strsize) +{ + return strlcpy(str, user_name, strsize); +} + +static size_t +fill_group(char *str, size_t strsize) +{ + struct group *grp; + size_t len; + + if ((grp = sudo_getgrgid(user_gid)) != NULL) { + len = strlcpy(str, grp->gr_name, strsize); + gr_delref(grp); + } else { + len = strlen(str); + len = snprintf(str + len, strsize - len, "#%u", + (unsigned int) user_gid); + } + return len; +} + +static size_t +fill_runas_user(char *str, size_t strsize) +{ + return strlcpy(str, runas_pw->pw_name, strsize); +} + +static size_t +fill_runas_group(char *str, size_t strsize) +{ + struct group *grp; + size_t len; + + if (runas_gr != NULL) { + len = strlcpy(str, runas_gr->gr_name, strsize); + } else { + if ((grp = sudo_getgrgid(runas_pw->pw_gid)) != NULL) { + len = strlcpy(str, grp->gr_name, strsize); + gr_delref(grp); + } else { + len = strlen(str); + len = snprintf(str + len, strsize - len, "#%u", + (unsigned int) runas_pw->pw_gid); + } + } + return len; +} + +static size_t +fill_hostname(char *str, size_t strsize) +{ + return strlcpy(str, user_shost, strsize); +} + +static size_t +fill_command(char *str, size_t strsize) +{ + return strlcpy(str, user_base, strsize); +} + +char * +expand_iolog_path(const char *prefix, const char *dir, const char *file, + char **slashp) +{ + size_t plen = 0, psize = 1024; + char *path, *dst; + const char *src = dir, *ep; + int pass, strfit = FALSE; + + /* Concatenate dir + file -> path, expanding any escape sequences. */ + dst = path = emalloc(psize); + *path = '\0'; + + /* Trim leading slashes from file component. */ + while (*file == '/') + file++; + + if (prefix != NULL) { + plen = strlcpy(path, prefix, psize); + dst += plen; + } + for (pass = 0; pass < 3; pass++) { + switch (pass) { + case 0: + src = dir; + break; + case 1: + /* Trim trailing slashes from dir component. */ + while (dst > path && dst[-1] == '/') + dst--; + if (slashp) + *slashp = dst; + src = "/"; + break; + case 2: + src = file; + break; + } + for (; *src != '\0'; src++) { + if (src[0] == '%') { + if (src[1] == '{') { + ep = strchr(src + 2, '}'); + if (ep != NULL) { + struct path_escape *esc; + size_t len = (size_t)(ep - src - 2); + for (esc = escapes; esc->name != NULL; esc++) { + if (strncmp(src + 2, esc->name, len) == 0 && + esc->name[len] == '\0') + break; + } + if (esc->name != NULL) { + for (;;) { + len = esc->copy_fn(dst, psize - (dst - path)); + if (len < psize - (dst - path)) + break; + path = erealloc3(path, 2, psize); + psize *= 2; + dst = path + plen; + } + dst += len; + plen += len; + src = ep; + continue; + } + } + } else if (src[1] == '%') { + /* Collapse %% -> % */ + src++; + } else { + /* May need strftime() */ + strfit = 1; + } + } + /* Need at least 2 chars, including the NUL terminator. */ + if (plen + 2 >= psize) { + path = erealloc3(path, 2, psize); + psize *= 2; + dst = path + plen; + } + *dst++ = *src; + plen++; + } + } + *dst = '\0'; + + if (strfit) { + time_t now; + struct tm *timeptr; + char *buf = NULL; + + time(&now); + timeptr = localtime(&now); + +#ifdef HAVE_SETLOCALE + if (!setlocale(LC_ALL, def_sudoers_locale)) { + warningx("unable to set locale to \"%s\", using \"C\"", + def_sudoers_locale); + setlocale(LC_ALL, "C"); + } +#endif + /* Double the size of the buffer until it is big enough to expand. */ + do { + psize *= 2; + buf = erealloc(buf, psize); + buf[psize - 1] = '\0'; + } while (!strftime(buf, psize, path, timeptr) || buf[psize - 1] != '\0'); +#ifdef HAVE_SETLOCALE + setlocale(LC_ALL, ""); +#endif + if (slashp) + *slashp = buf + (*slashp - path); + efree(path); + path = buf; + } + + return path; +} diff --git a/ldap.c b/plugins/sudoers/ldap.c similarity index 89% rename from ldap.c rename to plugins/sudoers/ldap.c index 3097af7..8d64c35 100644 --- a/ldap.c +++ b/plugins/sudoers/ldap.c @@ -76,7 +76,7 @@ # endif #endif -#include "sudo.h" +#include "sudoers.h" #include "parse.h" #include "lbuf.h" @@ -302,21 +302,20 @@ static struct ldap_config_table ldap_conf_table[] = { }; /* sudo_nss implementation */ -static int sudo_ldap_open __P((struct sudo_nss *nss)); -static int sudo_ldap_close __P((struct sudo_nss *nss)); -static int sudo_ldap_parse __P((struct sudo_nss *nss)); -static int sudo_ldap_setdefs __P((struct sudo_nss *nss)); -static int sudo_ldap_lookup __P((struct sudo_nss *nss, int ret, int pwflag)); -static int sudo_ldap_display_cmnd __P((struct sudo_nss *nss, - struct passwd *pw)); -static int sudo_ldap_display_defaults __P((struct sudo_nss *nss, - struct passwd *pw, struct lbuf *lbuf)); -static int sudo_ldap_display_bound_defaults __P((struct sudo_nss *nss, - struct passwd *pw, struct lbuf *lbuf)); -static int sudo_ldap_display_privs __P((struct sudo_nss *nss, - struct passwd *pw, struct lbuf *lbuf)); -static struct ldap_result *sudo_ldap_result_get __P((struct sudo_nss *nss, - struct passwd *pw)); +static int sudo_ldap_open(struct sudo_nss *nss); +static int sudo_ldap_close(struct sudo_nss *nss); +static int sudo_ldap_parse(struct sudo_nss *nss); +static int sudo_ldap_setdefs(struct sudo_nss *nss); +static int sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pwflag); +static int sudo_ldap_display_cmnd(struct sudo_nss *nss, struct passwd *pw); +static int sudo_ldap_display_defaults(struct sudo_nss *nss, struct passwd *pw, + struct lbuf *lbuf); +static int sudo_ldap_display_bound_defaults(struct sudo_nss *nss, + struct passwd *pw, struct lbuf *lbuf); +static int sudo_ldap_display_privs(struct sudo_nss *nss, struct passwd *pw, + struct lbuf *lbuf); +static struct ldap_result *sudo_ldap_result_get(struct sudo_nss *nss, + struct passwd *pw); /* * LDAP sudo_nss handle. @@ -353,7 +352,7 @@ struct sudo_nss sudo_nss_ldap = { * append one if we want something other than LDAP_PORT. */ static void -sudo_ldap_conf_add_ports() +sudo_ldap_conf_add_ports(void) { char *host, *port, defport[13]; @@ -395,8 +394,7 @@ toobig: * where the trailing slash is optional. */ static int -sudo_ldap_parse_uri(uri_list) - const struct ldap_config_list_str *uri_list; +sudo_ldap_parse_uri(const struct ldap_config_list_str *uri_list) { char *buf, *uri, *host, *cp, *port; char hostbuf[LINE_MAX]; @@ -476,8 +474,7 @@ toobig: } #else static char * -sudo_ldap_join_uri(uri_list) - struct ldap_config_list_str *uri_list; +sudo_ldap_join_uri(struct ldap_config_list_str *uri_list) { struct ldap_config_list_str *uri; size_t len = 0; @@ -502,10 +499,7 @@ sudo_ldap_join_uri(uri_list) #endif /* HAVE_LDAP_INITIALIZE */ static int -sudo_ldap_init(ldp, host, port) - LDAP **ldp; - const char *host; - int port; +sudo_ldap_init(LDAP **ldp, const char *host, int port) { LDAP *ld = NULL; int rc = LDAP_CONNECT_ERROR; @@ -574,10 +568,7 @@ done: * netgroup, else FALSE. */ static int -sudo_ldap_check_user_netgroup(ld, entry, user) - LDAP *ld; - LDAPMessage *entry; - char *user; +sudo_ldap_check_user_netgroup(LDAP *ld, LDAPMessage *entry, char *user) { struct berval **bv, **p; char *val; @@ -611,9 +602,7 @@ sudo_ldap_check_user_netgroup(ld, entry, user) * host match, else FALSE. */ static int -sudo_ldap_check_host(ld, entry) - LDAP *ld; - LDAPMessage *entry; +sudo_ldap_check_host(LDAP *ld, LDAPMessage *entry) { struct berval **bv, **p; char *val; @@ -645,9 +634,7 @@ sudo_ldap_check_host(ld, entry) } static int -sudo_ldap_check_runas_user(ld, entry) - LDAP *ld; - LDAPMessage *entry; +sudo_ldap_check_runas_user(LDAP *ld, LDAPMessage *entry) { struct berval **bv, **p; char *val; @@ -718,9 +705,7 @@ sudo_ldap_check_runas_user(ld, entry) } static int -sudo_ldap_check_runas_group(ld, entry) - LDAP *ld; - LDAPMessage *entry; +sudo_ldap_check_runas_group(LDAP *ld, LDAPMessage *entry) { struct berval **bv, **p; char *val; @@ -754,9 +739,7 @@ sudo_ldap_check_runas_group(ld, entry) * else FALSE. RunAs info is optional. */ static int -sudo_ldap_check_runas(ld, entry) - LDAP *ld; - LDAPMessage *entry; +sudo_ldap_check_runas(LDAP *ld, LDAPMessage *entry) { int ret; @@ -774,10 +757,7 @@ sudo_ldap_check_runas(ld, entry) * FALSE if disallowed and UNSPEC if not matched. */ static int -sudo_ldap_check_command(ld, entry, setenv_implied) - LDAP *ld; - LDAPMessage *entry; - int *setenv_implied; +sudo_ldap_check_command(LDAP *ld, LDAPMessage *entry, int *setenv_implied) { struct berval **bv, **p; char *allowed_cmnd, *allowed_args, *val; @@ -839,10 +819,7 @@ sudo_ldap_check_command(ld, entry, setenv_implied) * Returns TRUE if found and allowed, FALSE if negated, else UNSPEC. */ static int -sudo_ldap_check_bool(ld, entry, option) - LDAP *ld; - LDAPMessage *entry; - char *option; +sudo_ldap_check_bool(LDAP *ld, LDAPMessage *entry, char *option) { struct berval **bv, **p; char ch, *var; @@ -876,9 +853,7 @@ sudo_ldap_check_bool(ld, entry, option) * from the cn=defaults entry and also once when a final sudoRole is matched. */ static void -sudo_ldap_parse_options(ld, entry) - LDAP *ld; - LDAPMessage *entry; +sudo_ldap_parse_options(LDAP *ld, LDAPMessage *entry) { struct berval **bv, **p; char op, *var, *val; @@ -944,9 +919,7 @@ sudo_ldap_parse_options(ld, entry) * no time restriction shall be imposed. */ static int -sudo_ldap_timefilter(buffer, buffersize) - char *buffer; - size_t buffersize; +sudo_ldap_timefilter(char *buffer, size_t buffersize) { struct tm *tp; time_t now; @@ -997,8 +970,7 @@ sudo_ldap_build_default_filter() * Builds up a filter to check against LDAP. */ static char * -sudo_ldap_build_pass1(pw) - struct passwd *pw; +sudo_ldap_build_pass1(struct passwd *pw) { struct group *grp; char *buf, timebuffer[TIMEFILTER_LENGTH]; @@ -1088,7 +1060,7 @@ sudo_ldap_build_pass1(pw) * Builds up a filter to check against netgroup entries in LDAP. */ static char * -sudo_ldap_build_pass2() +sudo_ldap_build_pass2(void) { char *filt, timebuffer[TIMEFILTER_LENGTH]; @@ -1109,48 +1081,8 @@ sudo_ldap_build_pass2() return filt; } -/* - * Map yes/true/on to TRUE, no/false/off to FALSE, else -1 - */ -static int -_atobool(s) - const char *s; -{ - switch (*s) { - case 'y': - case 'Y': - if (strcasecmp(s, "yes") == 0) - return TRUE; - break; - case 't': - case 'T': - if (strcasecmp(s, "true") == 0) - return TRUE; - break; - case 'o': - case 'O': - if (strcasecmp(s, "on") == 0) - return TRUE; - if (strcasecmp(s, "off") == 0) - return FALSE; - break; - case 'n': - case 'N': - if (strcasecmp(s, "no") == 0) - return FALSE; - break; - case 'f': - case 'F': - if (strcasecmp(s, "false") == 0) - return FALSE; - break; - } - return -1; -} - static void -sudo_ldap_read_secret(path) - const char *path; +sudo_ldap_read_secret(const char *path) { FILE *fp; char buf[LINE_MAX], *cp; @@ -1171,7 +1103,7 @@ sudo_ldap_read_secret(path) } static int -sudo_ldap_read_config() +sudo_ldap_read_config(void) { FILE *fp; char *cp, *keyword, *value; @@ -1211,7 +1143,7 @@ sudo_ldap_read_config() if (strcasecmp(keyword, cur->conf_str) == 0) { switch (cur->type) { case CONF_BOOL: - *(int *)(cur->valp) = _atobool(value); + *(int *)(cur->valp) = atobool(value) == TRUE; break; case CONF_INT: *(int *)(cur->valp) = atoi(value); @@ -1246,75 +1178,97 @@ sudo_ldap_read_config() ldap_conf.host = estrdup("localhost"); if (ldap_conf.debug > 1) { - fprintf(stderr, "LDAP Config Summary\n"); - fprintf(stderr, "===================\n"); + sudo_printf(SUDO_CONV_ERROR_MSG, "LDAP Config Summary\n"); + sudo_printf(SUDO_CONV_ERROR_MSG, "===================\n"); if (ldap_conf.uri) { struct ldap_config_list_str *uri = ldap_conf.uri; do { - fprintf(stderr, "uri %s\n", uri->val); + sudo_printf(SUDO_CONV_ERROR_MSG, "uri %s\n", + uri->val); } while ((uri = uri->next) != NULL); } else { - fprintf(stderr, "host %s\n", ldap_conf.host ? - ldap_conf.host : "(NONE)"); - fprintf(stderr, "port %d\n", ldap_conf.port); + sudo_printf(SUDO_CONV_ERROR_MSG, "host %s\n", + ldap_conf.host ? ldap_conf.host : "(NONE)"); + sudo_printf(SUDO_CONV_ERROR_MSG, "port %d\n", + ldap_conf.port); } - fprintf(stderr, "ldap_version %d\n", ldap_conf.version); + sudo_printf(SUDO_CONV_ERROR_MSG, "ldap_version %d\n", + ldap_conf.version); + if (ldap_conf.base) { struct ldap_config_list_str *base = ldap_conf.base; - do { - fprintf(stderr, "sudoers_base %s\n", base->val); + sudo_printf(SUDO_CONV_ERROR_MSG, "sudoers_base %s\n", + base->val); } while ((base = base->next) != NULL); } else { - fprintf(stderr, "sudoers_base %s\n", - "(NONE) <---Sudo will ignore ldap)"); - } - if (ldap_conf.search_filter) - fprintf(stderr, "search_filter %s\n", ldap_conf.search_filter); - fprintf(stderr, "binddn %s\n", ldap_conf.binddn ? - ldap_conf.binddn : "(anonymous)"); - fprintf(stderr, "bindpw %s\n", ldap_conf.bindpw ? - ldap_conf.bindpw : "(anonymous)"); - if (ldap_conf.bind_timelimit > 0) - fprintf(stderr, "bind_timelimit %d\n", ldap_conf.bind_timelimit); - if (ldap_conf.timelimit > 0) - fprintf(stderr, "timelimit %d\n", ldap_conf.timelimit); - if (ldap_conf.timeout > 0) - fprintf(stderr, "timeout %d\n", ldap_conf.timeout); - fprintf(stderr, "ssl %s\n", ldap_conf.ssl ? - ldap_conf.ssl : "(no)"); - if (ldap_conf.tls_checkpeer != -1) - fprintf(stderr, "tls_checkpeer %s\n", ldap_conf.tls_checkpeer ? - "(yes)" : "(no)"); - if (ldap_conf.tls_cacertfile != NULL) - fprintf(stderr, "tls_cacertfile %s\n", ldap_conf.tls_cacertfile); - if (ldap_conf.tls_cacertdir != NULL) - fprintf(stderr, "tls_cacertdir %s\n", ldap_conf.tls_cacertdir); - if (ldap_conf.tls_random_file != NULL) - fprintf(stderr, "tls_random_file %s\n", ldap_conf.tls_random_file); - if (ldap_conf.tls_cipher_suite != NULL) - fprintf(stderr, "tls_cipher_suite %s\n", ldap_conf.tls_cipher_suite); - if (ldap_conf.tls_certfile != NULL) - fprintf(stderr, "tls_certfile %s\n", ldap_conf.tls_certfile); - if (ldap_conf.tls_keyfile != NULL) - fprintf(stderr, "tls_keyfile %s\n", ldap_conf.tls_keyfile); + sudo_printf(SUDO_CONV_ERROR_MSG, "sudoers_base %s\n", + "(NONE: LDAP disabled)"); + } + if (ldap_conf.search_filter) { + sudo_printf(SUDO_CONV_ERROR_MSG, "search_filter %s\n", + ldap_conf.search_filter); + } + sudo_printf(SUDO_CONV_ERROR_MSG, "binddn %s\n", + ldap_conf.binddn ? ldap_conf.binddn : "(anonymous)"); + sudo_printf(SUDO_CONV_ERROR_MSG, "bindpw %s\n", + ldap_conf.bindpw ? ldap_conf.bindpw : "(anonymous)"); + if (ldap_conf.bind_timelimit > 0) { + sudo_printf(SUDO_CONV_ERROR_MSG, "bind_timelimit %d\n", + ldap_conf.bind_timelimit); + } + if (ldap_conf.timelimit > 0) { + sudo_printf(SUDO_CONV_ERROR_MSG, "timelimit %d\n", + ldap_conf.timelimit); + } + sudo_printf(SUDO_CONV_ERROR_MSG, "ssl %s\n", + ldap_conf.ssl ? ldap_conf.ssl : "(no)"); + if (ldap_conf.tls_checkpeer != -1) { + sudo_printf(SUDO_CONV_ERROR_MSG, "tls_checkpeer %s\n", + ldap_conf.tls_checkpeer ? "(yes)" : "(no)"); + } + if (ldap_conf.tls_cacertfile != NULL) { + sudo_printf(SUDO_CONV_ERROR_MSG, "tls_cacertfile %s\n", + ldap_conf.tls_cacertfile); + } + if (ldap_conf.tls_cacertdir != NULL) { + sudo_printf(SUDO_CONV_ERROR_MSG, "tls_cacertdir %s\n", + ldap_conf.tls_cacertdir); + } + if (ldap_conf.tls_random_file != NULL) { + sudo_printf(SUDO_CONV_ERROR_MSG, "tls_random_file %s\n", + ldap_conf.tls_random_file); + } + if (ldap_conf.tls_cipher_suite != NULL) { + sudo_printf(SUDO_CONV_ERROR_MSG, "tls_cipher_suite %s\n", + ldap_conf.tls_cipher_suite); + } + if (ldap_conf.tls_certfile != NULL) { + sudo_printf(SUDO_CONV_ERROR_MSG, "tls_certfile %s\n", + ldap_conf.tls_certfile); + } + if (ldap_conf.tls_keyfile != NULL) { + sudo_printf(SUDO_CONV_ERROR_MSG, "tls_keyfile %s\n", + ldap_conf.tls_keyfile); + } #ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S if (ldap_conf.use_sasl != -1) { - fprintf(stderr, "use_sasl %s\n", + sudo_printf(SUDO_CONV_ERROR_MSG, "use_sasl %s\n", ldap_conf.use_sasl ? "yes" : "no"); - fprintf(stderr, "sasl_auth_id %s\n", ldap_conf.sasl_auth_id ? - ldap_conf.sasl_auth_id : "(NONE)"); - fprintf(stderr, "rootuse_sasl %d\n", ldap_conf.rootuse_sasl); - fprintf(stderr, "rootsasl_auth_id %s\n", ldap_conf.rootsasl_auth_id ? - ldap_conf.rootsasl_auth_id : "(NONE)"); - fprintf(stderr, "sasl_secprops %s\n", ldap_conf.sasl_secprops ? - ldap_conf.sasl_secprops : "(NONE)"); - fprintf(stderr, "krb5_ccname %s\n", ldap_conf.krb5_ccname ? - ldap_conf.krb5_ccname : "(NONE)"); + sudo_printf(SUDO_CONV_ERROR_MSG, "sasl_auth_id %s\n", + ldap_conf.sasl_auth_id ? ldap_conf.sasl_auth_id : "(NONE)"); + sudo_printf(SUDO_CONV_ERROR_MSG, "rootuse_sasl %d\n", + ldap_conf.rootuse_sasl); + sudo_printf(SUDO_CONV_ERROR_MSG, "rootsasl_auth_id %s\n", + ldap_conf.rootsasl_auth_id ? ldap_conf.rootsasl_auth_id : "(NONE)"); + sudo_printf(SUDO_CONV_ERROR_MSG, "sasl_secprops %s\n", + ldap_conf.sasl_secprops ? ldap_conf.sasl_secprops : "(NONE)"); + sudo_printf(SUDO_CONV_ERROR_MSG, "krb5_ccname %s\n", + ldap_conf.krb5_ccname ? ldap_conf.krb5_ccname : "(NONE)"); } #endif - fprintf(stderr, "===================\n"); + sudo_printf(SUDO_CONV_ERROR_MSG, "===================\n"); } if (!ldap_conf.base) return FALSE; /* if no base is defined, ignore LDAP */ @@ -1328,7 +1282,7 @@ sudo_ldap_read_config() if (ldap_conf.ssl != NULL) { if (strcasecmp(ldap_conf.ssl, "start_tls") == 0) ldap_conf.ssl_mode = SUDO_LDAP_STARTTLS; - else if (_atobool(ldap_conf.ssl)) + else if (atobool(ldap_conf.ssl) == TRUE) ldap_conf.ssl_mode = SUDO_LDAP_SSL; } @@ -1413,9 +1367,7 @@ sudo_ldap_read_config() * Extract the dn from an entry and return the first rdn from it. */ static char * -sudo_ldap_get_first_rdn(ld, entry) - LDAP *ld; - LDAPMessage *entry; +sudo_ldap_get_first_rdn(LDAP *ld, LDAPMessage *entry) { #ifdef HAVE_LDAP_STR2DN char *dn, *rdn = NULL; @@ -1444,10 +1396,8 @@ sudo_ldap_get_first_rdn(ld, entry) * Fetch and display the global Options. */ static int -sudo_ldap_display_defaults(nss, pw, lbuf) - struct sudo_nss *nss; - struct passwd *pw; - struct lbuf *lbuf; +sudo_ldap_display_defaults(struct sudo_nss *nss, struct passwd *pw, + struct lbuf *lbuf) { struct berval **bv, **p; struct timeval tv, *tvp = NULL; @@ -1499,10 +1449,8 @@ done: * STUB */ static int -sudo_ldap_display_bound_defaults(nss, pw, lbuf) - struct sudo_nss *nss; - struct passwd *pw; - struct lbuf *lbuf; +sudo_ldap_display_bound_defaults(struct sudo_nss *nss, struct passwd *pw, + struct lbuf *lbuf) { return 0; } @@ -1511,10 +1459,7 @@ sudo_ldap_display_bound_defaults(nss, pw, lbuf) * Print a record in the short form, ala file sudoers. */ static int -sudo_ldap_display_entry_short(ld, entry, lbuf) - LDAP *ld; - LDAPMessage *entry; - struct lbuf *lbuf; +sudo_ldap_display_entry_short(LDAP *ld, LDAPMessage *entry, struct lbuf *lbuf) { struct berval **bv, **p; int count = 0; @@ -1593,10 +1538,7 @@ sudo_ldap_display_entry_short(ld, entry, lbuf) * Print a record in the long form. */ static int -sudo_ldap_display_entry_long(ld, entry, lbuf) - LDAP *ld; - LDAPMessage *entry; - struct lbuf *lbuf; +sudo_ldap_display_entry_long(LDAP *ld, LDAPMessage *entry, struct lbuf *lbuf) { struct berval **bv, **p; char *rdn; @@ -1680,10 +1622,8 @@ sudo_ldap_display_entry_long(ld, entry, lbuf) * Like sudo_ldap_lookup(), except we just print entries. */ static int -sudo_ldap_display_privs(nss, pw, lbuf) - struct sudo_nss *nss; - struct passwd *pw; - struct lbuf *lbuf; +sudo_ldap_display_privs(struct sudo_nss *nss, struct passwd *pw, + struct lbuf *lbuf) { struct sudo_ldap_handle *handle = nss->handle; LDAP *ld; @@ -1712,9 +1652,7 @@ done: } static int -sudo_ldap_display_cmnd(nss, pw) - struct sudo_nss *nss; - struct passwd *pw; +sudo_ldap_display_cmnd(struct sudo_nss *nss, struct passwd *pw) { struct sudo_ldap_handle *handle = nss->handle; LDAP *ld; @@ -1750,11 +1688,8 @@ done: #ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S static int -sudo_ldap_sasl_interact(ld, flags, _auth_id, _interact) - LDAP *ld; - unsigned int flags; - void *_auth_id; - void *_interact; +sudo_ldap_sasl_interact(LDAP *ld, unsigned int flags, void *_auth_id, + void *_interact) { char *auth_id = (char *)_auth_id; sasl_interact_t *interact = (sasl_interact_t *)_interact; @@ -1783,8 +1718,7 @@ sudo_ldap_sasl_interact(ld, flags, _auth_id, _interact) * Set LDAP options based on the config table. */ static int -sudo_ldap_set_options(ld) - LDAP *ld; +sudo_ldap_set_options(LDAP *ld) { struct ldap_config_table *cur; int rc; @@ -1886,7 +1820,7 @@ sudo_ldap_set_options(ld) * Create a new sudo_ldap_result structure. */ static struct ldap_result * -sudo_ldap_result_alloc() +sudo_ldap_result_alloc(void) { struct ldap_result *result; @@ -1904,8 +1838,7 @@ sudo_ldap_result_alloc() * Free the ldap result structure */ static void -sudo_ldap_result_free(lres) - struct ldap_result *lres; +sudo_ldap_result_free(struct ldap_result *lres) { struct ldap_search_list *s; @@ -1929,10 +1862,8 @@ sudo_ldap_result_free(lres) * Add a search result to the ldap_result structure. */ static struct ldap_search_list * -sudo_ldap_result_add_search(lres, ldap, searchresult) - struct ldap_result *lres; - LDAP *ldap; - LDAPMessage *searchresult; +sudo_ldap_result_add_search(struct ldap_result *lres, LDAP *ldap, + LDAPMessage *searchresult) { struct ldap_search_list *s, *news; @@ -1956,8 +1887,7 @@ sudo_ldap_result_add_search(lres, ldap, searchresult) * Connect to the LDAP server specified by ld */ static int -sudo_ldap_bind_s(ld) - LDAP *ld; +sudo_ldap_bind_s(LDAP *ld) { int rc; #ifdef HAVE_LDAP_SASL_INTERACTIVE_BIND_S @@ -2037,8 +1967,7 @@ sudo_ldap_bind_s(ld) * Returns 0 on success and non-zero on failure. */ static int -sudo_ldap_open(nss) - struct sudo_nss *nss; +sudo_ldap_open(struct sudo_nss *nss) { LDAP *ld; int rc, ldapnoinit = FALSE; @@ -2115,8 +2044,7 @@ sudo_ldap_open(nss) } static int -sudo_ldap_setdefs(nss) - struct sudo_nss *nss; +sudo_ldap_setdefs(struct sudo_nss *nss) { struct ldap_config_list_str *base; struct sudo_ldap_handle *handle = nss->handle; @@ -2160,10 +2088,7 @@ sudo_ldap_setdefs(nss) * like sudoers_lookup() - only LDAP style */ static int -sudo_ldap_lookup(nss, ret, pwflag) - struct sudo_nss *nss; - int ret; - int pwflag; +sudo_ldap_lookup(struct sudo_nss *nss, int ret, int pwflag) { struct sudo_ldap_handle *handle = nss->handle; LDAP *ld; @@ -2185,7 +2110,7 @@ sudo_ldap_lookup(nss, ret, pwflag) if (pwflag) { DPRINTF(("perform search for pwflag %d", pwflag), 1); int doauth = UNSPEC; - enum def_tupple pwcheck = + enum def_tuple pwcheck = (pwflag == -1) ? never : sudo_defs_table[pwflag].sd_un.tuple; for (i = 0; i < lres->nentries; i++) { @@ -2284,9 +2209,7 @@ done: * Comparison function for ldap_entry_wrapper structures, descending order. */ static int -ldap_entry_compare(a, b) - const void *a; - const void *b; +ldap_entry_compare(const void *a, const void *b) { const struct ldap_entry_wrapper *aw = a; const struct ldap_entry_wrapper *bw = b; @@ -2301,8 +2224,7 @@ ldap_entry_compare(a, b) * XXX - use a tailq instead? */ static struct ldap_search_list * -sudo_ldap_result_last_search(lres) - struct ldap_result *lres; +sudo_ldap_result_last_search(struct ldap_result *lres) { struct ldap_search_list *result = lres->searches; @@ -2317,9 +2239,7 @@ sudo_ldap_result_last_search(lres) * Add an entry to the result structure. */ static struct ldap_entry_wrapper * -sudo_ldap_result_add_entry(lres, entry) - struct ldap_result *lres; - LDAPMessage *entry; +sudo_ldap_result_add_entry(struct ldap_result *lres, LDAPMessage *entry) { struct ldap_search_list *last; struct berval **bv; @@ -2364,8 +2284,7 @@ sudo_ldap_result_add_entry(lres, entry) * Free the ldap result structure in the sudo_nss handle. */ static void -sudo_ldap_result_free_nss(nss) - struct sudo_nss *nss; +sudo_ldap_result_free_nss(struct sudo_nss *nss) { struct sudo_ldap_handle *handle = nss->handle; @@ -2386,9 +2305,7 @@ sudo_ldap_result_free_nss(nss) * there is one for this user. */ static struct ldap_result * -sudo_ldap_result_get(nss, pw) - struct sudo_nss *nss; - struct passwd *pw; +sudo_ldap_result_get(struct sudo_nss *nss, struct passwd *pw) { struct sudo_ldap_handle *handle = nss->handle; struct ldap_config_list_str *base; @@ -2487,8 +2404,7 @@ sudo_ldap_result_get(nss, pw) * Shut down the LDAP connection. */ static int -sudo_ldap_close(nss) - struct sudo_nss *nss; +sudo_ldap_close(struct sudo_nss *nss) { struct sudo_ldap_handle *handle = nss->handle; @@ -2513,8 +2429,7 @@ sudo_ldap_close(nss) * STUB */ static int -sudo_ldap_parse(nss) - struct sudo_nss *nss; +sudo_ldap_parse(struct sudo_nss *nss) { return 0; } @@ -2527,9 +2442,7 @@ sudo_ldap_parse(nss) * an example of how to use the cached searches. */ static struct ldap_result * -sudo_ldap_result_from_search(ldap, searchresult) - LDAP *ldap; - LDAPMessage *searchresult; +sudo_ldap_result_from_search(LDAP *ldap, LDAPMessage *searchresult) { /* * An ldap_result is built from several search results, which are diff --git a/linux_audit.c b/plugins/sudoers/linux_audit.c similarity index 80% rename from linux_audit.c rename to plugins/sudoers/linux_audit.c index 16e21af..7505f69 100644 --- a/linux_audit.c +++ b/plugins/sudoers/linux_audit.c @@ -90,28 +90,3 @@ linux_audit_command(char *argv[], int result) return rc; } - -#ifdef HAVE_SELINUX -int -linux_audit_role_change(const char *old_context, - const char *new_context, const char *ttyn) -{ - int au_fd, rc; - char *message; - - if ((au_fd = linux_audit_open()) == -1) - return -1; - - /* audit role change using the same format as newrole(1) */ - easprintf(&message, "newrole: old-context=%s new-context=%s", - old_context, new_context); - rc = audit_log_user_message(au_fd, AUDIT_USER_ROLE_CHANGE, - message, NULL, NULL, ttyn, 1); - if (rc <= 0) - warning("unable to send audit message"); - - efree(message); - - return rc; -} -#endif /* HAVE_SELINUX */ diff --git a/linux_audit.h b/plugins/sudoers/linux_audit.h similarity index 90% rename from linux_audit.h rename to plugins/sudoers/linux_audit.h index f2574f6..8f4d46c 100644 --- a/linux_audit.h +++ b/plugins/sudoers/linux_audit.h @@ -18,7 +18,5 @@ #define _SUDO_LINUX_AUDIT_H int linux_audit_command(char *argv[], int result); -int linux_audit_role_change(const char *old_context, - const char *new_context, const char *ttyn); #endif /* _SUDO_LINUX_AUDIT_H */ diff --git a/logging.c b/plugins/sudoers/logging.c similarity index 84% rename from logging.c rename to plugins/sudoers/logging.c index d0aeab9..82f3e69 100644 --- a/logging.c +++ b/plugins/sudoers/logging.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994-1996, 1998-2010 Todd C. Miller + * Copyright (c) 1994-1996, 1998-2011 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -57,17 +57,21 @@ #include #include #include +#include #include #include +#include -#include "sudo.h" +#include "sudoers.h" -static void do_syslog __P((int, char *)); -static void do_logfile __P((char *)); -static void send_mail __P((const char *fmt, ...)); -static int should_mail __P((int)); -static void mysyslog __P((int, const char *, ...)); -static char *new_logline __P((const char *, int)); +static void do_syslog(int, char *); +static void do_logfile(char *); +static void send_mail(const char *fmt, ...); +static int should_mail(int); +static void mysyslog(int, const char *, ...); +static char *new_logline(const char *, int); + +extern sigjmp_buf error_jmp; #define MAXSYSLOGTRIES 16 /* num of retries for broken syslogs */ @@ -80,14 +84,7 @@ static char *new_logline __P((const char *, int)); * Sadly this is a maze of #ifdefs. */ static void -#ifdef __STDC__ mysyslog(int pri, const char *fmt, ...) -#else -mysyslog(pri, fmt, va_alist) - int pri; - const char *fmt; - va_dcl -#endif { #ifdef BROKEN_SYSLOG int i; @@ -95,11 +92,7 @@ mysyslog(pri, fmt, va_alist) char buf[MAXSYSLOGLEN+1]; va_list ap; -#ifdef __STDC__ va_start(ap, fmt); -#else - va_start(ap); -#endif #ifdef LOG_NFACILITIES openlog("sudo", 0, def_syslog); #else @@ -130,9 +123,7 @@ mysyslog(pri, fmt, va_alist) * message into parts if it is longer than MAXSYSLOGLEN. */ static void -do_syslog(pri, msg) - int pri; - char *msg; +do_syslog(int pri, char *msg) { size_t len, maxlen; char *p, *tmp, save; @@ -186,8 +177,7 @@ do_syslog(pri, msg) } static void -do_logfile(msg) - char *msg; +do_logfile(char *msg) { char *full_line; char *beg, *oldend, *end; @@ -293,9 +283,7 @@ do_logfile(msg) * Log and mail the denial message, optionally informing the user. */ void -log_denial(status, inform_user) - int status; - int inform_user; +log_denial(int status, int inform_user) { char *message; char *logline; @@ -315,23 +303,25 @@ log_denial(status, inform_user) /* Inform the user if they failed to authenticate. */ if (inform_user) { - if (ISSET(status, FLAG_NO_USER)) - (void) fprintf(stderr, "%s is not in the sudoers file. %s", - user_name, "This incident will be reported.\n"); - else if (ISSET(status, FLAG_NO_HOST)) - (void) fprintf(stderr, "%s is not allowed to run sudo on %s. %s", - user_name, user_shost, "This incident will be reported.\n"); - else if (ISSET(status, FLAG_NO_CHECK)) - (void) fprintf(stderr, "Sorry, user %s may not run sudo on %s.\n", + if (ISSET(status, FLAG_NO_USER)) { + sudo_printf(SUDO_CONV_ERROR_MSG, "%s is not in the sudoers file. " + "This incident will be reported.\n", user_name); + } else if (ISSET(status, FLAG_NO_HOST)) { + sudo_printf(SUDO_CONV_ERROR_MSG, "%s is not allowed to run sudo " + "on %s. This incident will be reported.\n", user_name, user_shost); - else - (void) fprintf(stderr, - "Sorry, user %s is not allowed to execute '%s%s%s' as %s%s%s on %s.\n", + } else if (ISSET(status, FLAG_NO_CHECK)) { + sudo_printf(SUDO_CONV_ERROR_MSG, "Sorry, user %s may not run " + "sudo on %s.\n", user_name, user_shost); + } else { + sudo_printf(SUDO_CONV_ERROR_MSG, "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 : runas_pw ? runas_pw->pw_name : user_name, runas_gr ? ":" : "", runas_gr ? runas_gr->gr_name : "", user_host); + } } /* @@ -349,8 +339,7 @@ log_denial(status, inform_user) * Log and potentially mail the allowed command. */ void -log_allowed(status) - int status; +log_allowed(int status) { char *logline; @@ -371,32 +360,21 @@ log_allowed(status) } void -#ifdef __STDC__ log_error(int flags, const char *fmt, ...) -#else -log_error(flags, fmt, va_alist) - int flags; - const char *fmt; - va_dcl -#endif { int serrno = errno; char *message; char *logline; va_list ap; -#ifdef __STDC__ - va_start(ap, fmt); -#else - va_start(ap); -#endif - - /* Become root if we are not already to avoid user interference */ - set_perms(PERM_ROOT|PERM_NOEXIT); /* Expand printf-style format + args. */ + va_start(ap, fmt); evasprintf(&message, fmt, ap); va_end(ap); + /* Become root if we are not already to avoid user interference */ + set_perms(PERM_ROOT|PERM_NOEXIT); + if (ISSET(flags, MSG_ONLY)) logline = message; else @@ -430,9 +408,11 @@ log_error(flags, fmt, va_alist) efree(logline); + restore_perms(); + if (!ISSET(flags, NO_EXIT)) { - cleanup(0); - exit(1); + plugin_cleanup(0); + siglongjmp(error_jmp, 1); } } @@ -442,13 +422,7 @@ log_error(flags, fmt, va_alist) * Send a message to MAILTO user */ static void -#ifdef __STDC__ send_mail(const char *fmt, ...) -#else -send_mail(fmt, va_alist) - const char *fmt; - va_dcl -#endif { FILE *mail; char *p; @@ -495,11 +469,7 @@ send_mail(fmt, va_alist) default: /* Parent. */ do { -#ifdef HAVE_WAITPID rv = waitpid(pid, &status, 0); -#else - rv = wait(&status); -#endif } while (rv == -1 && errno == EINTR); return; } @@ -626,22 +596,14 @@ send_mail(fmt, va_alist) (void) fprintf(mail, "\n\n%s : %s : %s : ", user_host, get_timestr(time(NULL), def_log_year), user_name); -#ifdef __STDC__ va_start(ap, fmt); -#else - va_start(ap); -#endif (void) vfprintf(mail, fmt, ap); va_end(ap); fputs("\n\n", mail); fclose(mail); do { -#ifdef HAVE_WAITPID rv = waitpid(pid, &status, 0); -#else - rv = wait(&status); -#endif } while (rv == -1 && errno == EINTR); _exit(0); } @@ -650,8 +612,7 @@ send_mail(fmt, va_alist) * Determine whether we should send mail based on "status" and defaults options. */ static int -should_mail(status) - int status; +should_mail(int status) { return def_mail_always || ISSET(status, VALIDATE_ERROR) || @@ -668,18 +629,40 @@ should_mail(status) #define LL_CMND_STR "COMMAND=" #define LL_TSID_STR "TSID=" +#define IS_SESSID(s) ( \ + isalnum((unsigned char)(s)[0]) && isalnum((unsigned char)(s)[1]) && \ + (s)[2] == '/' && \ + isalnum((unsigned char)(s)[3]) && isalnum((unsigned char)(s)[4]) && \ + (s)[5] == '/' && \ + isalnum((unsigned char)(s)[6]) && isalnum((unsigned char)(s)[7]) && \ + (s)[8] == '\0') + /* * Allocate and fill in a new logline. */ static char * -new_logline(message, serrno) - const char *message; - int serrno; +new_logline(const char *message, int serrno) { size_t len = 0; - char *evstr = NULL; char *errstr = NULL; - char *line; + char *evstr = NULL; + char *line, sessid[7], *tsid = NULL; + + /* A TSID may be a sudoers-style session ID or a free-form string. */ + if (sudo_user.iolog_file != NULL) { + if (IS_SESSID(sudo_user.iolog_file)) { + sessid[0] = sudo_user.iolog_file[0]; + sessid[1] = sudo_user.iolog_file[1]; + sessid[2] = sudo_user.iolog_file[3]; + sessid[3] = sudo_user.iolog_file[4]; + sessid[4] = sudo_user.iolog_file[6]; + sessid[5] = sudo_user.iolog_file[7]; + sessid[6] = '\0'; + tsid = sessid; + } else { + tsid = sudo_user.iolog_file; + } + } /* * Compute line length @@ -696,27 +679,30 @@ new_logline(message, serrno) 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.sessid[0] != '\0') - len += sizeof(LL_TSID_STR) + 2 + strlen(sudo_user.sessid); + if (tsid != NULL) + len += sizeof(LL_TSID_STR) + 2 + strlen(tsid); if (sudo_user.env_vars != NULL) { size_t evlen = 0; - struct list_member *cur; - for (cur = sudo_user.env_vars; cur != NULL; cur = cur->next) - evlen += strlen(cur->value) + 1; + char * const *ep; + + for (ep = sudo_user.env_vars; *ep != NULL; ep++) + evlen += strlen(*ep) + 1; evstr = emalloc(evlen); evstr[0] = '\0'; - for (cur = sudo_user.env_vars; cur != NULL; cur = cur->next) { - strlcat(evstr, cur->value, evlen); + for (ep = sudo_user.env_vars; *ep != NULL; ep++) { + strlcat(evstr, *ep, evlen); strlcat(evstr, " ", evlen); /* NOTE: last one will fail */ } len += sizeof(LL_ENV_STR) + 2 + evlen; } - /* Note: we log "sudo -l command arg ..." as "list command arg ..." */ - len += sizeof(LL_CMND_STR) - 1 + strlen(user_cmnd); - if (ISSET(sudo_mode, MODE_CHECK)) - len += sizeof("list ") - 1; - if (user_args != NULL) - len += strlen(user_args) + 1; + if (user_cmnd != NULL) { + /* Note: we log "sudo -l command arg ..." as "list command arg ..." */ + len += sizeof(LL_CMND_STR) - 1 + strlen(user_cmnd); + if (ISSET(sudo_mode, MODE_CHECK)) + len += sizeof("list ") - 1; + if (user_args != NULL) + len += strlen(user_args) + 1; + } /* * Allocate and build up the line. @@ -754,9 +740,9 @@ new_logline(message, serrno) strlcat(line, " ; ", len) >= len) goto toobig; } - if (sudo_user.sessid[0] != '\0') { + if (tsid != NULL) { if (strlcat(line, LL_TSID_STR, len) >= len || - strlcat(line, sudo_user.sessid, len) >= len || + strlcat(line, tsid, len) >= len || strlcat(line, " ; ", len) >= len) goto toobig; } @@ -767,16 +753,18 @@ new_logline(message, serrno) goto toobig; efree(evstr); } - if (strlcat(line, LL_CMND_STR, len) >= len) - goto toobig; - if (ISSET(sudo_mode, MODE_CHECK) && strlcat(line, "list ", len) >= len) - goto toobig; - if (strlcat(line, user_cmnd, len) >= len) - goto toobig; - if (user_args != NULL) { - if (strlcat(line, " ", len) >= len || - strlcat(line, user_args, len) >= len) + if (user_cmnd != NULL) { + if (strlcat(line, LL_CMND_STR, len) >= len) + goto toobig; + if (ISSET(sudo_mode, MODE_CHECK) && strlcat(line, "list ", len) >= len) goto toobig; + if (strlcat(line, user_cmnd, len) >= len) + goto toobig; + if (user_args != NULL) { + if (strlcat(line, " ", len) >= len || + strlcat(line, user_args, len) >= len) + goto toobig; + } } return line; diff --git a/logging.h b/plugins/sudoers/logging.h similarity index 82% rename from logging.h rename to plugins/sudoers/logging.h index c95423e..43d5ff0 100644 --- a/logging.h +++ b/plugins/sudoers/logging.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999-2005, 2009 + * Copyright (c) 1999-2005, 2009-2010 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -47,12 +47,11 @@ # define MAXSYSLOGLEN 960 #endif -void audit_success __P((char *[])); -void audit_failure __P((char *[], char const * const, ...)); -void log_allowed __P((int)); -void log_denial __P((int, int)); -void log_error __P((int flags, const char *fmt, ...)) - __printflike(2, 3); -RETSIGTYPE reapchild __P((int)); +void audit_success(char *[]); +void audit_failure(char *[], char const * const, ...); +void log_allowed(int); +void log_denial(int, int); +void log_error(int flags, const char *fmt, ...) __printflike(2, 3); +void reapchild(int); #endif /* _LOGGING_H */ diff --git a/match.c b/plugins/sudoers/match.c similarity index 88% rename from match.c rename to plugins/sudoers/match.c index ba299e1..8e06a4d 100644 --- a/match.c +++ b/plugins/sudoers/match.c @@ -77,27 +77,24 @@ # endif #endif -#include "sudo.h" +#include "sudoers.h" #include "interfaces.h" #include "parse.h" #include #ifndef HAVE_FNMATCH -# include "emul/fnmatch.h" +# include "compat/fnmatch.h" #endif /* HAVE_FNMATCH */ #ifndef HAVE_EXTENDED_GLOB -# include "emul/glob.h" +# include "compat/glob.h" #endif /* HAVE_EXTENDED_GLOB */ -#ifdef USING_NONUNIX_GROUPS -# include "nonunix.h" -#endif /* USING_NONUNIX_GROUPS */ static struct member_list empty; -static int command_matches_dir __P((char *, size_t)); -static int command_matches_glob __P((char *, char *)); -static int command_matches_fnmatch __P((char *, char *)); -static int command_matches_normal __P((char *, char *)); +static int command_matches_dir(char *, size_t); +static int command_matches_glob(char *, char *); +static int command_matches_fnmatch(char *, char *); +static int command_matches_normal(char *, char *); /* * Returns TRUE if string 's' contains meta characters. @@ -109,9 +106,7 @@ static int command_matches_normal __P((char *, char *)); * Returns ALLOW, DENY or UNSPEC. */ static int -_userlist_matches(pw, list) - struct passwd *pw; - struct member_list *list; +_userlist_matches(struct passwd *pw, struct member_list *list) { struct member *m; struct alias *a; @@ -150,9 +145,7 @@ _userlist_matches(pw, list) } int -userlist_matches(pw, list) - struct passwd *pw; - struct member_list *list; +userlist_matches(struct passwd *pw, struct member_list *list) { alias_seqno++; return _userlist_matches(pw, list); @@ -164,9 +157,7 @@ userlist_matches(pw, list) * Returns ALLOW, DENY or UNSPEC. */ static int -_runaslist_matches(user_list, group_list) - struct member_list *user_list; - struct member_list *group_list; +_runaslist_matches(struct member_list *user_list, struct member_list *group_list) { struct member *m; struct alias *a; @@ -246,9 +237,7 @@ _runaslist_matches(user_list, group_list) } int -runaslist_matches(user_list, group_list) - struct member_list *user_list; - struct member_list *group_list; +runaslist_matches(struct member_list *user_list, struct member_list *group_list) { alias_seqno++; return _runaslist_matches(user_list ? user_list : &empty, @@ -260,8 +249,7 @@ runaslist_matches(user_list, group_list) * Returns ALLOW, DENY or UNSPEC. */ static int -_hostlist_matches(list) - struct member_list *list; +_hostlist_matches(struct member_list *list) { struct member *m; struct alias *a; @@ -300,8 +288,7 @@ _hostlist_matches(list) } int -hostlist_matches(list) - struct member_list *list; +hostlist_matches(struct member_list *list) { alias_seqno++; return _hostlist_matches(list); @@ -312,8 +299,7 @@ hostlist_matches(list) * Returns ALLOW, DENY or UNSPEC. */ static int -_cmndlist_matches(list) - struct member_list *list; +_cmndlist_matches(struct member_list *list) { struct member *m; int matched = UNSPEC; @@ -327,8 +313,7 @@ _cmndlist_matches(list) } int -cmndlist_matches(list) - struct member_list *list; +cmndlist_matches(struct member_list *list) { alias_seqno++; return _cmndlist_matches(list); @@ -339,8 +324,7 @@ cmndlist_matches(list) * Returns ALLOW, DENY or UNSPEC. */ int -cmnd_matches(m) - struct member *m; +cmnd_matches(struct member *m) { struct alias *a; struct sudo_command *c; @@ -400,9 +384,7 @@ command_args_match(sudoers_cmnd, sudoers_args) * otherwise, return TRUE if user_cmnd names one of the inodes in path. */ int -command_matches(sudoers_cmnd, sudoers_args) - char *sudoers_cmnd; - char *sudoers_args; +command_matches(char *sudoers_cmnd, char *sudoers_args) { /* Check for pseudo-commands */ if (sudoers_cmnd[0] != '/') { @@ -436,9 +418,7 @@ command_matches(sudoers_cmnd, sudoers_args) } static int -command_matches_fnmatch(sudoers_cmnd, sudoers_args) - char *sudoers_cmnd; - char *sudoers_args; +command_matches_fnmatch(char *sudoers_cmnd, char *sudoers_args) { /* * Return true if fnmatch(3) succeeds AND @@ -459,9 +439,7 @@ command_matches_fnmatch(sudoers_cmnd, sudoers_args) } static int -command_matches_glob(sudoers_cmnd, sudoers_args) - char *sudoers_cmnd; - char *sudoers_args; +command_matches_glob(char *sudoers_cmnd, char *sudoers_args) { struct stat sudoers_stat; size_t dlen; @@ -532,9 +510,7 @@ command_matches_glob(sudoers_cmnd, sudoers_args) } static int -command_matches_normal(sudoers_cmnd, sudoers_args) - char *sudoers_cmnd; - char *sudoers_args; +command_matches_normal(char *sudoers_cmnd, char *sudoers_args) { struct stat sudoers_stat; char *base; @@ -576,9 +552,7 @@ command_matches_normal(sudoers_cmnd, sudoers_args) * Return TRUE if user_cmnd names one of the inodes in dir, else FALSE. */ static int -command_matches_dir(sudoers_dir, dlen) - char *sudoers_dir; - size_t dlen; +command_matches_dir(char *sudoers_dir, size_t dlen) { struct stat sudoers_stat; struct dirent *dent; @@ -620,10 +594,8 @@ command_matches_dir(sudoers_dir, dlen) } static int -addr_matches_if(n) - char *n; +addr_matches_if(char *n) { - int i; union sudo_in_addr_un addr; struct interface *ifp; #ifdef HAVE_IN6_ADDR @@ -641,8 +613,7 @@ addr_matches_if(n) addr.ip4.s_addr = inet_addr(n); } - for (i = 0; i < num_interfaces; i++) { - ifp = &interfaces[i]; + for (ifp = interfaces; ifp != NULL; ifp = ifp->next) { if (ifp->family != family) continue; switch(family) { @@ -671,9 +642,7 @@ addr_matches_if(n) } static int -addr_matches_if_netmask(n, m) - char *n; - char *m; +addr_matches_if_netmask(char *n, char *m) { int i; union sudo_in_addr_un addr, mask; @@ -720,8 +689,7 @@ addr_matches_if_netmask(n, m) } #endif /* HAVE_IN6_ADDR */ - for (i = 0; i < num_interfaces; i++) { - ifp = &interfaces[i]; + for (ifp = interfaces; ifp != NULL; ifp = ifp->next) { if (ifp->family != family) continue; switch(family) { @@ -748,8 +716,7 @@ addr_matches_if_netmask(n, m) * "n" is a network that we are on, else returns FALSE. */ int -addr_matches(n) - char *n; +addr_matches(char *n) { char *m; int retval; @@ -769,10 +736,7 @@ addr_matches(n) * Returns TRUE if the hostname matches the pattern, else FALSE */ int -hostname_matches(shost, lhost, pattern) - char *shost; - char *lhost; - char *pattern; +hostname_matches(char *shost, char *lhost, char *pattern) { if (has_meta(pattern)) { if (strchr(pattern, '.')) @@ -792,10 +756,7 @@ hostname_matches(shost, lhost, pattern) * else returns FALSE. */ int -userpw_matches(sudoers_user, user, pw) - char *sudoers_user; - char *user; - struct passwd *pw; +userpw_matches(char *sudoers_user, char *user, struct passwd *pw) { if (pw != NULL && *sudoers_user == '#') { uid_t uid = (uid_t) atoi(sudoers_user + 1); @@ -810,9 +771,7 @@ userpw_matches(sudoers_user, user, pw) * else returns FALSE. */ int -group_matches(sudoers_group, gr) - char *sudoers_group; - struct group *gr; +group_matches(char *sudoers_group, struct group *gr) { if (*sudoers_group == '#') { gid_t gid = (gid_t) atoi(sudoers_group + 1); @@ -827,10 +786,7 @@ group_matches(sudoers_group, gr) * else returns FALSE. */ int -usergr_matches(group, user, pw) - char *group; - char *user; - struct passwd *pw; +usergr_matches(char *group, char *user, struct passwd *pw) { int matched = FALSE; struct passwd *pw0 = NULL; @@ -839,12 +795,10 @@ usergr_matches(group, user, pw) if (*group++ != '%') goto done; -#ifdef USING_NONUNIX_GROUPS - if (*group == ':') { - matched = sudo_nonunix_groupcheck(++group, user, pw); + if (*group == ':' && def_group_plugin) { + matched = group_plugin_query(user, group + 1, pw); goto done; } -#endif /* USING_NONUNIX_GROUPS */ /* look up user's primary gid in the passwd file */ if (pw == NULL) { @@ -858,14 +812,11 @@ usergr_matches(group, user, pw) goto done; } -#ifdef USING_NONUNIX_GROUPS - /* not a Unix group, could be an AD group */ - if (sudo_nonunix_groupcheck_available() && - sudo_nonunix_groupcheck(group, user, pw)) { + /* not a Unix group, could be an external group */ + if (def_group_plugin && group_plugin_query(user, group, pw)) { matched = TRUE; goto done; } -#endif /* USING_NONUNIX_GROUPS */ done: if (pw0 != NULL) @@ -882,11 +833,7 @@ done: * XXX - swap order of host & shost */ int -netgr_matches(netgr, lhost, shost, user) - char *netgr; - char *lhost; - char *shost; - char *user; +netgr_matches(char *netgr, char *lhost, char *shost, char *user) { static char *domain; #ifdef HAVE_GETDOMAINNAME diff --git a/mkdefaults b/plugins/sudoers/mkdefaults similarity index 97% rename from mkdefaults rename to plugins/sudoers/mkdefaults index 90f3b0c..7befe15 100755 --- a/mkdefaults +++ b/plugins/sudoers/mkdefaults @@ -88,7 +88,7 @@ $records[$count++] = [$var, $type, $desc, $values, $callback] if defined($var); # Print out value arrays for ($i = 0; $i < $count; $i++) { if (defined($records[$i]->[3])) { - die "Values list specified for non-tupple\n" unless + die "Values list specified for non-tuple\n" unless $records[$i]->[1] =~ /^T_TUPLE/; printf CFILE "static struct def_values def_data_%s[] = {\n", $records[$i]->[0]; foreach (@{$records[$i]->[3]}) { @@ -108,7 +108,7 @@ print CFILE "\tNULL, 0, NULL\n }\n};\n"; # Print out def_tuple if (@tuple_values) { - print HEADER "\nenum def_tupple {\n"; + print HEADER "\nenum def_tuple {\n"; for ($i = 0; $i <= $#tuple_values; $i++) { printf HEADER "\t%s%s\n", $tuple_values[$i], $i != $#tuple_values ? "," : ""; diff --git a/parse.c b/plugins/sudoers/parse.c similarity index 89% rename from parse.c rename to plugins/sudoers/parse.c index acf8e5f..985c435 100644 --- a/parse.c +++ b/plugins/sudoers/parse.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2005, 2007-2010 Todd C. Miller + * Copyright (c) 2004-2005, 2007-2011 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -42,7 +42,7 @@ #include #include -#include "sudo.h" +#include "sudoers.h" #include "parse.h" #include "lbuf.h" #include @@ -75,22 +75,20 @@ extern int errorlineno, parse_error; /* * Local prototypes. */ -static void print_member __P((struct lbuf *, char *, int, int, int)); -static int display_bound_defaults __P((int, struct lbuf *)); +static void print_member(struct lbuf *, char *, int, int, int); +static int display_bound_defaults(int, struct lbuf *); int -sudo_file_open(nss) - struct sudo_nss *nss; +sudo_file_open(struct sudo_nss *nss) { if (def_ignore_local_sudoers) return -1; - nss->handle = open_sudoers(_PATH_SUDOERS, FALSE, NULL); + nss->handle = open_sudoers(sudoers_file, FALSE, NULL); return nss->handle ? 0 : -1; } int -sudo_file_close(nss) - struct sudo_nss *nss; +sudo_file_close(struct sudo_nss *nss) { /* Free parser data structures and close sudoers file. */ init_parser(NULL, 0); @@ -106,13 +104,12 @@ sudo_file_close(nss) * Parse the specified sudoers file. */ int -sudo_file_parse(nss) - struct sudo_nss *nss; +sudo_file_parse(struct sudo_nss *nss) { if (nss->handle == NULL) return -1; - init_parser(_PATH_SUDOERS, 0); + init_parser(sudoers_file, 0); yyin = nss->handle; if (yyparse() != 0 || parse_error) { log_error(NO_EXIT, "parse error in %s near line %d", @@ -126,8 +123,7 @@ sudo_file_parse(nss) * Wrapper around update_defaults() for nsswitch code. */ int -sudo_file_setdefs(nss) - struct sudo_nss *nss; +sudo_file_setdefs(struct sudo_nss *nss) { if (nss->handle == NULL) return -1; @@ -142,10 +138,7 @@ sudo_file_setdefs(nss) * allowed to run the specified command on this host as the target user. */ int -sudo_file_lookup(nss, validated, pwflag) - struct sudo_nss *nss; - int validated; - int pwflag; +sudo_file_lookup(struct sudo_nss *nss, int validated, int pwflag) { int match, host_match, runas_match, cmnd_match; struct cmndspec *cs; @@ -163,7 +156,7 @@ sudo_file_lookup(nss, validated, pwflag) */ if (pwflag) { int nopass; - enum def_tupple pwcheck; + enum def_tuple pwcheck; pwcheck = (pwflag == -1) ? never : sudo_defs_table[pwflag].sd_un.tuple; nopass = (pwcheck == all) ? TRUE : FALSE; @@ -258,7 +251,7 @@ sudo_file_lookup(nss, validated, pwflag) SET(validated, VALIDATE_NOT_OK); CLR(validated, VALIDATE_OK); } - set_perms(PERM_ROOT); + restore_perms(); return validated; } @@ -266,10 +259,8 @@ sudo_file_lookup(nss, validated, pwflag) (cs->tags.t != UNSPEC && cs->tags.t != IMPLIED && cs->tags.t != tags->t) static void -sudo_file_append_cmnd(cs, tags, lbuf) - struct cmndspec *cs; - struct cmndtag *tags; - struct lbuf *lbuf; +sudo_file_append_cmnd(struct cmndspec *cs, struct cmndtag *tags, + struct lbuf *lbuf) { struct member *m; @@ -310,10 +301,8 @@ sudo_file_append_cmnd(cs, tags, lbuf) } static int -sudo_file_display_priv_short(pw, us, lbuf) - struct passwd *pw; - struct userspec *us; - struct lbuf *lbuf; +sudo_file_display_priv_short(struct passwd *pw, struct userspec *us, + struct lbuf *lbuf) { struct cmndspec *cs; struct member *m; @@ -365,10 +354,8 @@ sudo_file_display_priv_short(pw, us, lbuf) } static int -sudo_file_display_priv_long(pw, us, lbuf) - struct passwd *pw; - struct userspec *us; - struct lbuf *lbuf; +sudo_file_display_priv_long(struct passwd *pw, struct userspec *us, + struct lbuf *lbuf) { struct cmndspec *cs; struct member *m; @@ -420,10 +407,8 @@ sudo_file_display_priv_long(pw, us, lbuf) } int -sudo_file_display_privs(nss, pw, lbuf) - struct sudo_nss *nss; - struct passwd *pw; - struct lbuf *lbuf; +sudo_file_display_privs(struct sudo_nss *nss, struct passwd *pw, + struct lbuf *lbuf) { struct userspec *us; int nfound = 0; @@ -448,10 +433,8 @@ done: * Display matching Defaults entries for the given user on this host. */ int -sudo_file_display_defaults(nss, pw, lbuf) - struct sudo_nss *nss; - struct passwd *pw; - struct lbuf *lbuf; +sudo_file_display_defaults(struct sudo_nss *nss, struct passwd *pw, + struct lbuf *lbuf) { struct defaults *d; char *prefix; @@ -502,10 +485,8 @@ done: * Display Defaults entries that are per-runas or per-command */ int -sudo_file_display_bound_defaults(nss, pw, lbuf) - struct sudo_nss *nss; - struct passwd *pw; - struct lbuf *lbuf; +sudo_file_display_bound_defaults(struct sudo_nss *nss, struct passwd *pw, + struct lbuf *lbuf) { int nfound = 0; @@ -520,9 +501,7 @@ sudo_file_display_bound_defaults(nss, pw, lbuf) * Display Defaults entries of the given type. */ static int -display_bound_defaults(dtype, lbuf) - int dtype; - struct lbuf *lbuf; +display_bound_defaults(int dtype, struct lbuf *lbuf) { struct defaults *d; struct member *m, *binding = NULL; @@ -553,7 +532,7 @@ display_bound_defaults(dtype, lbuf) default: return -1; } - /* printf("Per-%s Defaults entries:\n", dname); */ + /* sudo_printf(SUDO_CONV_INFO_MSG, "Per-%s Defaults entries:\n", dname); */ tq_foreach_fwd(&defaults, d) { if (d->type != dtype) continue; @@ -583,9 +562,7 @@ display_bound_defaults(dtype, lbuf) } int -sudo_file_display_cmnd(nss, pw) - struct sudo_nss *nss; - struct passwd *pw; +sudo_file_display_cmnd(struct sudo_nss *nss, struct passwd *pw) { struct cmndspec *cs; struct member *match; @@ -621,8 +598,8 @@ sudo_file_display_cmnd(nss, pw) } matched: if (match != NULL && !match->negated) { - printf("%s%s%s\n", safe_cmnd, user_args ? " " : "", - user_args ? user_args : ""); + sudo_printf(SUDO_CONV_INFO_MSG, "%s%s%s\n", + safe_cmnd, user_args ? " " : "", user_args ? user_args : ""); rval = 0; } done: @@ -633,10 +610,8 @@ done: * Print the contents of a struct member to stdout */ static void -_print_member(lbuf, name, type, negated, alias_type) - struct lbuf *lbuf; - char *name; - int type, negated, alias_type; +_print_member(struct lbuf *lbuf, char *name, int type, int negated, + int alias_type) { struct alias *a; struct member *m; @@ -674,10 +649,8 @@ _print_member(lbuf, name, type, negated, alias_type) } static void -print_member(lbuf, name, type, negated, alias_type) - struct lbuf *lbuf; - char *name; - int type, negated, alias_type; +print_member(struct lbuf *lbuf, char *name, int type, int negated, + int alias_type) { alias_seqno++; _print_member(lbuf, name, type, negated, alias_type); diff --git a/parse.h b/plugins/sudoers/parse.h similarity index 80% rename from parse.h rename to plugins/sudoers/parse.h index 90595bf..6976b16 100644 --- a/parse.h +++ b/plugins/sudoers/parse.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 1998-2000, 2004, 2007-2010 + * Copyright (c) 1996, 1998-2000, 2004, 2007-2011 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -165,27 +165,27 @@ extern unsigned int alias_seqno; /* * Prototypes */ -char *alias_add __P((char *, int, struct member *)); -int addr_matches __P((char *)); -int cmnd_matches __P((struct member *)); -int cmndlist_matches __P((struct member_list *)); -int command_matches __P((char *, char *)); -int hostlist_matches __P((struct member_list *)); -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 *, 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 *alias_find __P((char *, int)); -struct alias *alias_remove __P((char *, int)); -void alias_free __P((void *)); -void alias_apply __P((int (*)(void *, void *), void *)); -void init_aliases __P((void)); -void init_lexer __P((void)); -void init_parser __P((char *, int)); -int alias_compare __P((const void *, const void *)); +char *alias_add(char *, int, struct member *); +int addr_matches(char *); +int cmnd_matches(struct member *); +int cmndlist_matches(struct member_list *); +int command_matches(char *, char *); +int hostlist_matches(struct member_list *); +int hostname_matches(char *, char *, char *); +int netgr_matches(char *, char *, char *, char *); +int no_aliases(void); +int runaslist_matches(struct member_list *, struct member_list *); +int userlist_matches(struct passwd *, struct member_list *); +int usergr_matches(char *, char *, struct passwd *); +int userpw_matches(char *, char *, struct passwd *); +int group_matches(char *, struct group *); +struct alias *alias_find(char *, int); +struct alias *alias_remove(char *, int); +void alias_free(void *); +void alias_apply(int (*)(void *, void *), void *); +void init_aliases(void); +void init_lexer(void); +void init_parser(const char *, int); +int alias_compare(const void *, const void *); #endif /* _SUDO_PARSE_H */ diff --git a/plugins/sudoers/plugin_error.c b/plugins/sudoers/plugin_error.c new file mode 100644 index 0000000..2d42871 --- /dev/null +++ b/plugins/sudoers/plugin_error.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2004-2005, 2010 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include + +#include +#include +#include +#include +#include + +#include "missing.h" +#include "alloc.h" +#include "error.h" +#include "sudo_plugin.h" + +static void _warning(int, const char *, va_list); + void plugin_cleanup(int); + +sigjmp_buf error_jmp; + +extern sudo_conv_t sudo_conv; + +void +error(int eval, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + _warning(1, fmt, ap); + va_end(ap); + plugin_cleanup(0); + siglongjmp(error_jmp, eval); +} + +void +errorx(int eval, const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + _warning(0, fmt, ap); + va_end(ap); + plugin_cleanup(0); + siglongjmp(error_jmp, eval); +} + +void +warning(const char *fmt, ...) +{ + va_list ap; + + va_start(ap, fmt); + _warning(1, fmt, ap); + va_end(ap); +} + +void +warningx(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + _warning(0, fmt, ap); + va_end(ap); +} + +static void +_warning(int use_errno, const char *fmt, va_list ap) +{ + struct sudo_conv_message msg[6]; + struct sudo_conv_reply repl[6]; + char *str; + int nmsgs = 4; + + evasprintf(&str, fmt, ap); + + /* Call conversation function */ + memset(&msg, 0, sizeof(msg)); + msg[0].msg_type = SUDO_CONV_ERROR_MSG; + msg[0].msg = getprogname(); + msg[1].msg_type = SUDO_CONV_ERROR_MSG; + msg[1].msg = ": "; + msg[2].msg_type = SUDO_CONV_ERROR_MSG; + msg[2].msg = str; + if (use_errno) { + msg[3].msg_type = SUDO_CONV_ERROR_MSG; + msg[3].msg = ": "; + msg[4].msg_type = SUDO_CONV_ERROR_MSG; + msg[4].msg = strerror(errno); + nmsgs = 6; + } + msg[nmsgs - 1].msg_type = SUDO_CONV_ERROR_MSG; + msg[nmsgs - 1].msg = "\n"; + memset(&repl, 0, sizeof(repl)); + sudo_conv(nmsgs, msg, repl); + efree(str); +} diff --git a/pwutil.c b/plugins/sudoers/pwutil.c similarity index 93% rename from pwutil.c rename to plugins/sudoers/pwutil.c index 548da4d..ac0d34a 100644 --- a/pwutil.c +++ b/plugins/sudoers/pwutil.c @@ -51,7 +51,7 @@ #include #include -#include "sudo.h" +#include "sudoers.h" #include "redblack.h" /* @@ -60,9 +60,9 @@ static struct rbtree *pwcache_byuid, *pwcache_byname; static struct rbtree *grcache_bygid, *grcache_byname; -static int cmp_pwuid __P((const void *, const void *)); -static int cmp_pwnam __P((const void *, const void *)); -static int cmp_grgid __P((const void *, const void *)); +static int cmp_pwuid(const void *, const void *); +static int cmp_pwnam(const void *, const void *); +static int cmp_grgid(const void *, const void *); #define cmp_grnam cmp_pwnam @@ -87,9 +87,7 @@ struct cache_item { * Compare by uid. */ static int -cmp_pwuid(v1, v2) - const void *v1; - const void *v2; +cmp_pwuid(const void *v1, const void *v2) { const struct cache_item *ci1 = (const struct cache_item *) v1; const struct cache_item *ci2 = (const struct cache_item *) v2; @@ -100,9 +98,7 @@ cmp_pwuid(v1, v2) * Compare by user name. */ static int -cmp_pwnam(v1, v2) - const void *v1; - const void *v2; +cmp_pwnam(const void *v1, const void *v2) { const struct cache_item *ci1 = (const struct cache_item *) v1; const struct cache_item *ci2 = (const struct cache_item *) v2; @@ -135,9 +131,7 @@ do { \ * call to the shadow function could overwrite the pw buffer (NIS). */ static struct cache_item * -make_pwitem(pw, name) - const struct passwd *pw; - const char *name; +make_pwitem(const struct passwd *pw, const char *name) { char *cp; const char *pw_shell; @@ -203,15 +197,13 @@ make_pwitem(pw, name) } void -pw_addref(pw) - struct passwd *pw; +pw_addref(struct passwd *pw) { ptr_to_item(pw)->refcnt++; } static void -pw_delref_item(v) - void *v; +pw_delref_item(void *v) { struct cache_item *item = v; @@ -220,8 +212,7 @@ pw_delref_item(v) } void -pw_delref(pw) - struct passwd *pw; +pw_delref(struct passwd *pw) { pw_delref_item(ptr_to_item(pw)); } @@ -231,8 +222,7 @@ pw_delref(pw) * Fills in pw_passwd from shadow file if necessary. */ struct passwd * -sudo_getpwuid(uid) - uid_t uid; +sudo_getpwuid(uid_t uid) { struct cache_item key, *item; struct rbnode *node; @@ -275,8 +265,7 @@ done: * Fills in pw_passwd from shadow file if necessary. */ struct passwd * -sudo_getpwnam(name) - const char *name; +sudo_getpwnam(const char *name) { struct cache_item key, *item; struct rbnode *node; @@ -319,9 +308,7 @@ done: * Take a uid in string form "#123" and return a faked up passwd struct. */ struct passwd * -sudo_fakepwnam(user, gid) - const char *user; - gid_t gid; +sudo_fakepwnam(const char *user, gid_t gid) { struct cache_item *item; struct passwd *pw; @@ -374,7 +361,7 @@ sudo_fakepwnam(user, gid) } void -sudo_setpwent() +sudo_setpwent(void) { setpwent(); if (pwcache_byuid == NULL) @@ -384,7 +371,7 @@ sudo_setpwent() } void -sudo_freepwcache() +sudo_freepwcache(void) { if (pwcache_byuid != NULL) { rbdestroy(pwcache_byuid, pw_delref_item); @@ -397,7 +384,7 @@ sudo_freepwcache() } void -sudo_endpwent() +sudo_endpwent(void) { endpwent(); sudo_freepwcache(); @@ -407,9 +394,7 @@ sudo_endpwent() * Compare by gid. */ static int -cmp_grgid(v1, v2) - const void *v1; - const void *v2; +cmp_grgid(const void *v1, const void *v2) { const struct cache_item *ci1 = (const struct cache_item *) v1; const struct cache_item *ci2 = (const struct cache_item *) v2; @@ -421,10 +406,8 @@ cmp_grgid(v1, v2) * elements. If name is non-NULL it is used as the key, else the * gid is the key. Fills in datum from struct group. */ -static struct cache_item * -make_gritem(gr, name) - const struct group *gr; - const char *name; +struct cache_item * +make_gritem(const struct group *gr, const char *name) { char *cp; size_t nsize, psize, nmem, total, len; @@ -485,15 +468,13 @@ make_gritem(gr, name) } void -gr_addref(gr) - struct group *gr; +gr_addref(struct group *gr) { ptr_to_item(gr)->refcnt++; } static void -gr_delref_item(v) - void *v; +gr_delref_item(void *v) { struct cache_item *item = v; @@ -502,8 +483,7 @@ gr_delref_item(v) } void -gr_delref(gr) - struct group *gr; +gr_delref(struct group *gr) { gr_delref_item(ptr_to_item(gr)); } @@ -512,8 +492,7 @@ gr_delref(gr) * Get a group entry by gid and allocate space for it. */ struct group * -sudo_getgrgid(gid) - gid_t gid; +sudo_getgrgid(gid_t gid) { struct cache_item key, *item; struct rbnode *node; @@ -549,8 +528,7 @@ done: * Get a group entry by name and allocate space for it. */ struct group * -sudo_getgrnam(name) - const char *name; +sudo_getgrnam(const char *name) { struct cache_item key, *item; struct rbnode *node; @@ -587,8 +565,7 @@ done: * Take a gid in string form "#123" and return a faked up group struct. */ struct group * -sudo_fakegrnam(group) - const char *group; +sudo_fakegrnam(const char *group) { struct cache_item *item; struct group *gr; @@ -630,7 +607,7 @@ sudo_fakegrnam(group) } void -sudo_setgrent() +sudo_setgrent(void) { setgrent(); if (grcache_bygid == NULL) @@ -640,7 +617,7 @@ sudo_setgrent() } void -sudo_freegrcache() +sudo_freegrcache(void) { if (grcache_bygid != NULL) { rbdestroy(grcache_bygid, gr_delref_item); @@ -653,16 +630,14 @@ sudo_freegrcache() } void -sudo_endgrent() +sudo_endgrent(void) { endgrent(); sudo_freegrcache(); } int -user_in_group(pw, group) - struct passwd *pw; - const char *group; +user_in_group(struct passwd *pw, const char *group) { #ifdef HAVE_MBR_CHECK_MEMBERSHIP uuid_t gu, uu; diff --git a/redblack.c b/plugins/sudoers/redblack.c similarity index 90% rename from redblack.c rename to plugins/sudoers/redblack.c index fb3611b..23c74d3 100644 --- a/redblack.c +++ b/plugins/sudoers/redblack.c @@ -1,5 +1,6 @@ /* - * Copyright (c) 2004-2005, 2007,2009 Todd C. Miller + * Copyright (c) 2004-2005, 2007, 2009-2011 + * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -54,14 +55,14 @@ # endif #endif /* STDC_HEADERS */ -#include "sudo.h" +#include "missing.h" +#include "alloc.h" #include "redblack.h" -static void rbrepair __P((struct rbtree *, struct rbnode *)); -static void rotate_left __P((struct rbtree *, struct rbnode *)); -static void rotate_right __P((struct rbtree *, struct rbnode *)); -static void _rbdestroy __P((struct rbtree *, struct rbnode *, - void (*)(void *))); +static void rbrepair(struct rbtree *, struct rbnode *); +static void rotate_left(struct rbtree *, struct rbnode *); +static void rotate_right(struct rbtree *, struct rbnode *); +static void _rbdestroy(struct rbtree *, struct rbnode *, void (*)(void *)); /* * Red-Black tree, see http://en.wikipedia.org/wiki/Red-black_tree @@ -86,8 +87,7 @@ static void _rbdestroy __P((struct rbtree *, struct rbnode *, * Allocates and returns the initialized (empty) tree. */ struct rbtree * -rbcreate(compar) - int (*compar)__P((const void *, const void*)); +rbcreate(int (*compar)(const void *, const void*)) { struct rbtree *tree; @@ -117,9 +117,7 @@ rbcreate(compar) * Perform a left rotation starting at node. */ static void -rotate_left(tree, node) - struct rbtree *tree; - struct rbnode *node; +rotate_left(struct rbtree *tree, struct rbnode *node) { struct rbnode *child; @@ -142,9 +140,7 @@ rotate_left(tree, node) * Perform a right rotation starting at node. */ static void -rotate_right(tree, node) - struct rbtree *tree; - struct rbnode *node; +rotate_right(struct rbtree *tree, struct rbnode *node) { struct rbnode *child; @@ -169,9 +165,7 @@ rotate_right(tree, node) * already exists, a pointer to the existant node is returned. */ struct rbnode * -rbinsert(tree, data) - struct rbtree *tree; - void *data; +rbinsert(struct rbtree *tree, void *data) { struct rbnode *node = rbfirst(tree); struct rbnode *parent = rbroot(tree); @@ -263,9 +257,7 @@ rbinsert(tree, data) * Returns a pointer to the node if found, else NULL. */ struct rbnode * -rbfind(tree, key) - struct rbtree *tree; - void *key; +rbfind(struct rbtree *tree, void *key) { struct rbnode *node = rbfirst(tree); int res; @@ -284,12 +276,8 @@ rbfind(tree, key) * error value is returned. Returns 0 on successful traversal. */ int -rbapply_node(tree, node, func, cookie, order) - struct rbtree *tree; - struct rbnode *node; - int (*func)__P((void *, void *)); - void *cookie; - enum rbtraversal order; +rbapply_node(struct rbtree *tree, struct rbnode *node, + int (*func)(void *, void *), void *cookie, enum rbtraversal order) { int error; @@ -315,9 +303,7 @@ rbapply_node(tree, node, func, cookie, order) * Returns the successor of node, or nil if there is none. */ static struct rbnode * -rbsuccessor(tree, node) - struct rbtree *tree; - struct rbnode *node; +rbsuccessor(struct rbtree *tree, struct rbnode *node) { struct rbnode *succ; @@ -338,10 +324,7 @@ rbsuccessor(tree, node) * Recursive portion of rbdestroy(). */ static void -_rbdestroy(tree, node, destroy) - struct rbtree *tree; - struct rbnode *node; - void (*destroy)__P((void *)); +_rbdestroy(struct rbtree *tree, struct rbnode *node, void (*destroy)(void *)) { if (node != rbnil(tree)) { _rbdestroy(tree, node->left, destroy); @@ -357,9 +340,7 @@ _rbdestroy(tree, node, destroy) * for each node and then freeing the tree itself. */ void -rbdestroy(tree, destroy) - struct rbtree *tree; - void (*destroy)__P((void *)); +rbdestroy(struct rbtree *tree, void (*destroy)(void *)) { _rbdestroy(tree, rbfirst(tree), destroy); efree(tree); @@ -368,9 +349,7 @@ rbdestroy(tree, destroy) /* * Delete node 'z' from the tree and return its data pointer. */ -void *rbdelete(tree, z) - struct rbtree *tree; - struct rbnode *z; +void *rbdelete(struct rbtree *tree, struct rbnode *z) { struct rbnode *x, *y; void *data = z->data; @@ -412,9 +391,7 @@ void *rbdelete(tree, z) * colors to restore the 4 properties inherent in red-black trees. */ static void -rbrepair(tree, node) - struct rbtree *tree; - struct rbnode *node; +rbrepair(struct rbtree *tree, struct rbnode *node) { struct rbnode *sibling; diff --git a/redblack.h b/plugins/sudoers/redblack.h similarity index 71% rename from redblack.h rename to plugins/sudoers/redblack.h index b1938ca..eab5e8f 100644 --- a/redblack.h +++ b/plugins/sudoers/redblack.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2007 Todd C. Miller + * Copyright (c) 2004, 2007, 2010 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -35,7 +35,7 @@ struct rbnode { }; struct rbtree { - int (*compar) __P((const void *, const void *)); + int (*compar)(const void *, const void *); struct rbnode root; struct rbnode nil; }; @@ -46,13 +46,12 @@ struct rbtree { #define rbroot(t) (&(t)->root) #define rbnil(t) (&(t)->nil) -void *rbdelete __P((struct rbtree *, struct rbnode *)); -int rbapply_node __P((struct rbtree *, struct rbnode *, - int (*)(void *, void *), void *, - enum rbtraversal)); -struct rbnode *rbfind __P((struct rbtree *, void *)); -struct rbnode *rbinsert __P((struct rbtree *, void *)); -struct rbtree *rbcreate __P((int (*)(const void *, const void *))); -void rbdestroy __P((struct rbtree *, void (*)(void *))); +void *rbdelete(struct rbtree *, struct rbnode *); +int rbapply_node(struct rbtree *, struct rbnode *, + int (*)(void *, void *), void *, enum rbtraversal); +struct rbnode *rbfind(struct rbtree *, void *); +struct rbnode *rbinsert(struct rbtree *, void *); +struct rbtree *rbcreate(int (*)(const void *, const void *)); +void rbdestroy(struct rbtree *, void (*)(void *)); #endif /* _SUDO_REDBLACK_H */ diff --git a/plugins/sudoers/regress/iolog_path/check_iolog_path.c b/plugins/sudoers/regress/iolog_path/check_iolog_path.c new file mode 100644 index 0000000..cef22ff --- /dev/null +++ b/plugins/sudoers/regress/iolog_path/check_iolog_path.c @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2011 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS) +# include +# endif +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#ifdef HAVE_SETLOCALE +# include +#endif +#include +#include +#include + +#define _SUDO_MAIN +#include "sudoers.h" +#include "def_data.c" + +struct sudo_user sudo_user; +struct passwd *list_pw; + +static char sessid[7]; + +static void +usage(void) +{ + fprintf(stderr, "usage: check_iolog_path datafile\n"); + exit(1); +} + +static int +do_check(char *dir_in, char *file_in, char *tdir_out, char *tfile_out) +{ + char *path, *slash; + char dir_out[4096], file_out[4096]; + struct tm *timeptr; + time_t now; + int error = 0; + + /* + * Expand any strftime(3) escapes + * XXX - want to pass timeptr to expand_iolog_path + */ + time(&now); + timeptr = localtime(&now); + strftime(dir_out, sizeof(dir_out), tdir_out, timeptr); + strftime(file_out, sizeof(file_out), tfile_out, timeptr); + + path = expand_iolog_path(NULL, dir_in, file_in, &slash); + *slash = '\0'; + if (strcmp(path, dir_out) != 0) { + warningx("%s: expected %s, got %s", dir_in, dir_out, path); + error = 1; + } + if (strcmp(slash + 1, file_out) != 0) { + warningx("%s: expected %s, got %s", file_in, file_out, slash + 1); + error = 1; + } + + return error; +} + +#define MAX_STATE 12 + +int +main(int argc, char *argv[]) +{ + struct passwd pw, rpw; + size_t len; + FILE *fp; + char line[2048]; + char *file_in = NULL, *file_out = NULL; + char *dir_in = NULL, *dir_out = NULL; + int state = 0; + int errors = 0; + int tests = 0; + + if (argc != 2) + usage(); + + fp = fopen(argv[1], "r"); + if (fp == NULL) + errorx(1, "unable to open %s", argv[1]); + + memset(&pw, 0, sizeof(pw)); + memset(&rpw, 0, sizeof(rpw)); + sudo_user.pw = &pw; + sudo_user._runas_pw = &rpw; + + /* + * Input consists of 12 lines: + * sequence number + * user name + * user gid + * runas user name + * runas gid + * hostname [short form] + * command + * dir [with escapes] + * file [with escapes] + * expanded dir + * expanded file + * empty line + */ + while (fgets(line, sizeof(line), fp) != NULL) { + len = strcspn(line, "\n"); + line[len] = '\0'; + + switch (state) { + case 0: + strlcpy(sessid, line, sizeof(sessid)); + break; + case 1: + if (user_name != NULL) + free(user_name); + user_name = strdup(line); + break; + case 2: + user_gid = atoi(line); + break; + case 3: + if (runas_pw->pw_name != NULL) + free(runas_pw->pw_name); + runas_pw->pw_name = strdup(line); + break; + case 4: + runas_pw->pw_gid = atoi(line); + break; + case 5: + user_shost = strdup(line); + break; + case 6: + user_base = strdup(line); + break; + case 7: + dir_in = strdup(line); + break; + case 8: + file_in = strdup(line); + break; + case 9: + dir_out = strdup(line); + break; + case 10: + file_out = strdup(line); + break; + case 11: + errors += do_check(dir_in, file_in, dir_out, file_out); + tests++; + break; + default: + errorx(1, "internal error, invalid state %d", state); + } + state = (state + 1) % MAX_STATE; + } + + if (tests != 0) { + printf("iolog_path: %d test%s run, %d errors, %d%% success rate\n", + tests, tests == 1 ? "" : "s", errors, + (tests - errors) * 100 / tests); + } + + exit(errors); +} + +void io_nextid(char *iolog_dir, char id[7]) +{ + memcpy(id, sessid, sizeof(sessid)); +} + +void +cleanup(int gotsig) +{ + return; +} diff --git a/plugins/sudoers/regress/iolog_path/data b/plugins/sudoers/regress/iolog_path/data new file mode 100644 index 0000000..e2877b2 --- /dev/null +++ b/plugins/sudoers/regress/iolog_path/data @@ -0,0 +1,72 @@ +000001 +nobody +1 +root +0 +somehost +id +/var/log/sudo-io +%%{bogus} +/var/log/sudo-io +%%{bogus} + +000001 +nobody +1 +root +0 +somehost +id +/var/log/sudo-io +%%{seq} +/var/log/sudo-io +%%{seq} + +000001 +nobody +1 +root +0 +somehost +id +/var/log/sudo-io +%{seq} +/var/log/sudo-io +00/00/01 + +000001 +nobody +1 +root +0 +somehost +id +/var/log/sudo-io/%{user} +%{seq} +/var/log/sudo-io/nobody +00/00/01 + +000001 +nobody +1 +root +0 +somehost +su +/var/log/sudo-io/%{user}/%{runas_user} +%{command}_%Y%m%s_%H%M +/var/log/sudo-io/nobody/root +su_%Y%m%s_%H%M + +000001 +nobody +1 +root +0 +somehost +su +/var/log/sudo-io/ +/%{user}/%{runas_user}/%{command}_%Y%m%s_%H%M +/var/log/sudo-io +nobody/root/su_%Y%m%s_%H%M + diff --git a/plugins/sudoers/regress/parser/check_fill.c b/plugins/sudoers/regress/parser/check_fill.c new file mode 100644 index 0000000..599a202 --- /dev/null +++ b/plugins/sudoers/regress/parser/check_fill.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2011 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#include +#include + +#include "list.h" +#include "parse.h" +#include "toke.h" +#include "gram.h" + +/* + * TODO: test realloc + */ + +YYSTYPE yylval; + +struct fill_test { + const char *input; + const char *output; + int len; + int addspace; +}; + +/* + * In "normal" fill, anything can be escaped and hex chars are expanded. + */ +static struct fill_test txt_data[] = { + { "Embedded\\x20Space", "Embedded Space", 0 }, + { "\\x20Leading", " Leading", 0 }, + { "Trailing\\x20", "Trailing ", 0 }, + { "Multiple\\x20\\x20Spaces", "Multiple Spaces", 0 }, + { "Hexparse\\x200Check", "Hexparse 0Check", 0 }, + { "Escaped\\\\Escape", "Escaped\\Escape", 0 }, + { "LongGroupName", "LongGrou", 8 } +}; + +/* + * The only escaped chars in a command should be [,:= \t#] + * The rest are done by glob() or fnmatch(). + */ +static struct fill_test cmd_data[] = { + { "foo\\,bar", "foo,bar", 0 }, + { "this\\:that", "this:that", 0 }, + { "foo\\=bar", "foo=bar", 0 }, + { "tab\\\tstop", "tab\tstop", 0 }, + { "not a \\#comment", "not a #comment", 0 } +}; + +/* + * No escaped characters in command line args. + * Arguments get appended. + */ +static struct fill_test args_data[] = { + { "/", "/", 0, 0 }, + { "-type", "/ -type", 0, 1 }, + { "f", "/ -type f", 0, 1 }, + { "-exec", "/ -type f -exec", 0, 1 }, + { "ls", "/ -type f -exec ls", 0, 1 }, + { "{}", "/ -type f -exec ls {}", 0, 1 } +}; + +static int +check_fill(const char *input, int len, int addspace, const char *expect, char **resultp) +{ + if (!fill(input, len)) + return -1; + *resultp = yylval.string; + return !strcmp(yylval.string, expect); +} + +static int +check_fill_cmnd(const char *input, int len, int addspace, const char *expect, char **resultp) +{ + if (!fill_cmnd(input, len)) + return -1; + *resultp = yylval.command.cmnd; + return !strcmp(yylval.command.cmnd, expect); +} + +static int +check_fill_args(const char *input, int len, int addspace, const char *expect, char **resultp) +{ + if (!fill_args(input, len, addspace)) + return -1; + *resultp = yylval.command.args; + return !strcmp(yylval.command.args, expect); +} + +static int +do_tests(int (*checker)(const char *, int, int, const char *, char **), + struct fill_test *data, size_t ntests) +{ + int i, len; + int errors = 0; + char *result; + + for (i = 0; i < ntests; i++) { + if (data[i].len == 0) + len = strlen(data[i].input); + else + len = data[i].len; + + switch ((*checker)(data[i].input, len, data[i].addspace, data[i].output, &result)) { + case 0: + /* no match */ + fprintf(stderr, "Failed parsing %.*s: expected [%s], got [%s]\n", + (int)data[i].len, data[i].input, data[i].output, result); + errors++; + break; + case 1: + /* match */ + break; + default: + /* error */ + fprintf(stderr, "Failed parsing %.*s: fill function failure\n", + (int)data[i].len, data[i].input); + errors++; + break; + } + } + + return errors; +} + +int +main(int argc, char *argv[]) +{ + int ntests, errors = 0; + + errors += do_tests(check_fill, txt_data, sizeof(txt_data) / sizeof(txt_data[0])); + errors += do_tests(check_fill_cmnd, cmd_data, sizeof(cmd_data) / sizeof(cmd_data[0])); + errors += do_tests(check_fill_args, args_data, sizeof(args_data) / sizeof(args_data[0])); + + ntests = sizeof(txt_data) / sizeof(txt_data[0]) + + sizeof(cmd_data) / sizeof(cmd_data[0]) + + sizeof(args_data) / sizeof(args_data[0]); + printf("check_fill: %d tests run, %d errors, %d%% success rate\n", + ntests, errors, (ntests - errors) * 100 / ntests); + + exit(errors); +} + +/* STUB */ +void +cleanup(int gotsig) +{ + return; +} + +/* STUB */ +void +yyerror(const char *s) +{ + return; +} diff --git a/plugins/sudoers/regress/sudoers/test1.in b/plugins/sudoers/regress/sudoers/test1.in new file mode 100644 index 0000000..872925c --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test1.in @@ -0,0 +1,8 @@ +# +# Verify that all command tags are parsed OK. +# See http://www.sudo.ws/bugs/show_bug.cgi?id=437 +# +user1 ALL = LOG_INPUT: LOG_OUTPUT: /usr/bin/su -:\ + ALL = NOLOG_INPUT: NOLOG_OUTPUT: /usr/bin/id +user2 ALL = NOPASSWD: NOEXEC: SETENV: /usr/bin/vi:\ + ALL = PASSWD: EXEC: NOSETENV: /usr/bin/echo diff --git a/plugins/sudoers/regress/sudoers/test1.out.ok b/plugins/sudoers/regress/sudoers/test1.out.ok new file mode 100644 index 0000000..44cb652 --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test1.out.ok @@ -0,0 +1,6 @@ +Parses OK. + + + +user1 ALL = /usr/bin/su - : ALL = /usr/bin/id +user2 ALL = NOPASSWD: NOEXEC: /usr/bin/vi : ALL = PASSWD: EXEC: /usr/bin/echo diff --git a/plugins/sudoers/regress/sudoers/test1.toke.ok b/plugins/sudoers/regress/sudoers/test1.toke.ok new file mode 100644 index 0000000..3f3a7ad --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test1.toke.ok @@ -0,0 +1,6 @@ +# +# +# +# +WORD(5) ALL = LOG_INPUT LOG_OUTPUT COMMAND ARG : ALL = NOLOG_INPUT NOLOG_OUTPUT COMMAND +WORD(5) ALL = NOPASSWD NOEXEC SETENV COMMAND : ALL = PASSWD EXEC NOSETENV COMMAND diff --git a/plugins/sudoers/regress/sudoers/test2.in b/plugins/sudoers/regress/sudoers/test2.in new file mode 100644 index 0000000..cfdfaa3 --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test2.in @@ -0,0 +1,60 @@ +# Check quoted user name in User_Alias +User_Alias UA1 = "foo" +User_Alias UA2 = "foo.bar" +User_Alias UA3 = "foo\"" +User_Alias UA4 = "foo:bar" +User_Alias UA5 = "foo:bar\"" + +# Check quoted group name in User_Alias +User_Alias UA6 = "%baz" +User_Alias UA7 = "%baz.biz" + +# Check quoted non-Unix group name in User_Alias +User_Alias UA8 = "%:C/non UNIX 0 c" +User_Alias UA9 = "%:C/non\'UNIX\'1 c" +User_Alias UA10 = "%:C/non\"UNIX\"0 c" +User_Alias UA11 = "%:C/non_UNIX_0 c" +User_Alias UA12 = "%:C/non\'UNIX_3 c" + +# Check quoted user name in Runas_Alias +Runas_Alias RA1 = "foo" +Runas_Alias RA2 = "foo\"" +Runas_Alias RA3 = "foo:bar" +Runas_Alias RA4 = "foo:bar\"" + +# Check quoted host name in Defaults +Defaults@"somehost" set_home +Defaults@"quoted\"" set_home + +# Check quoted user name in Defaults +Defaults:"you" set_home +Defaults:"us\"" set_home +Defaults:"%them" set_home +Defaults:"%: non UNIX 0 c" set_home +Defaults:"+net" set_home + +# Check quoted runas name in Defaults +Defaults>"someone" set_home +Defaults>"some one" set_home + +# Check quoted command in Defaults +# XXX - not currently supported +#Defaults!"/bin/ls -l" set_home +#Defaults!"/bin/ls -l \"foo\"" set_home + +# Check quoted user, runas and host name in Cmnd_Spec +"foo" "hosta" = ("root") ALL +"foo.bar" "hostb" = ("root") ALL +"foo\"" "hostc" = ("root") ALL +"foo:bar" "hostd" = ("root") ALL +"foo:bar\"" "hoste" = ("root") ALL + +# Check quoted group/netgroup name in Cmnd_Spec +"%baz" "hosta" = ("root") ALL +"%baz.biz" "hostb" = ("root") ALL +"%:C/non UNIX 0 c" "hostc" = ("root") ALL +"%:C/non\'UNIX\'1 c" "hostd" = ("root") ALL +"%:C/non\"UNIX\"0 c" "hoste" = ("root") ALL +"%:C/non_UNIX_0 c" "hostf" = ("root") ALL +"%:C/non\'UNIX_3 c" "hostg" = ("root") ALL +"+netgr" "hosth" = ("root") ALL diff --git a/plugins/sudoers/regress/sudoers/test2.out.ok b/plugins/sudoers/regress/sudoers/test2.out.ok new file mode 100644 index 0000000..8f55faf --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test2.out.ok @@ -0,0 +1,42 @@ +Parses OK. + +Defaults@somehost set_home +Defaults@quoted" set_home +Defaults:you set_home +Defaults:us" set_home +Defaults:%them set_home +Defaults:%: non UNIX 0 c set_home +Defaults:+net set_home +Defaults>someone set_home +Defaults>some one set_home + +Runas_Alias RA1 = foo +Runas_Alias RA2 = foo" +Runas_Alias RA3 = foo:bar +Runas_Alias RA4 = foo:bar" +User_Alias UA1 = foo +User_Alias UA10 = %:C/non"UNIX"0 c +User_Alias UA11 = %:C/non_UNIX_0 c +User_Alias UA12 = %:C/non\'UNIX_3 c +User_Alias UA2 = foo.bar +User_Alias UA3 = foo" +User_Alias UA4 = foo:bar +User_Alias UA5 = foo:bar" +User_Alias UA6 = %baz +User_Alias UA7 = %baz.biz +User_Alias UA8 = %:C/non UNIX 0 c +User_Alias UA9 = %:C/non\'UNIX\'1 c + +foo hosta = (root) ALL +foo.bar hostb = (root) ALL +foo" hostc = (root) ALL +foo:bar hostd = (root) ALL +foo:bar" hoste = (root) ALL +%baz hosta = (root) ALL +%baz.biz hostb = (root) ALL +%:C/non UNIX 0 c hostc = (root) ALL +%:C/non\'UNIX\'1 c hostd = (root) ALL +%:C/non"UNIX"0 c hoste = (root) ALL +%:C/non_UNIX_0 c hostf = (root) ALL +%:C/non\'UNIX_3 c hostg = (root) ALL ++netgr hosth = (root) ALL diff --git a/plugins/sudoers/regress/sudoers/test2.toke.ok b/plugins/sudoers/regress/sudoers/test2.toke.ok new file mode 100644 index 0000000..fcd7b73 --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test2.toke.ok @@ -0,0 +1,60 @@ +# +USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR WORD(4) +USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR WORD(4) +USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR WORD(4) +USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR WORD(4) +USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR WORD(4) + +# +USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR USERGROUP +USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR USERGROUP + +# +USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR USERGROUP +USERALIAS ALIAS = BEGINSTR STRBODY BACKSLASH STRBODY BACKSLASH STRBODY ENDSTR USERGROUP +USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR USERGROUP +USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR USERGROUP +USERALIAS ALIAS = BEGINSTR STRBODY BACKSLASH STRBODY ENDSTR USERGROUP + +# +RUNASALIAS ALIAS = BEGINSTR STRBODY ENDSTR WORD(4) +RUNASALIAS ALIAS = BEGINSTR STRBODY ENDSTR WORD(4) +RUNASALIAS ALIAS = BEGINSTR STRBODY ENDSTR WORD(4) +RUNASALIAS ALIAS = BEGINSTR STRBODY ENDSTR WORD(4) + +# +DEFAULTS_HOST BEGINSTR STRBODY ENDSTR WORD(4) DEFVAR +DEFAULTS_HOST BEGINSTR STRBODY ENDSTR WORD(4) DEFVAR + +# +DEFAULTS_USER BEGINSTR STRBODY ENDSTR WORD(4) DEFVAR +DEFAULTS_USER BEGINSTR STRBODY ENDSTR WORD(4) DEFVAR +DEFAULTS_USER BEGINSTR STRBODY ENDSTR WORD(4) DEFVAR +DEFAULTS_USER BEGINSTR STRBODY ENDSTR WORD(4) DEFVAR +DEFAULTS_USER BEGINSTR STRBODY ENDSTR WORD(4) DEFVAR + +# +DEFAULTS_RUNAS BEGINSTR STRBODY ENDSTR WORD(4) DEFVAR +DEFAULTS_RUNAS BEGINSTR STRBODY ENDSTR WORD(4) DEFVAR + +# +# +# +# + +# +BEGINSTR STRBODY ENDSTR WORD(4) BEGINSTR STRBODY ENDSTR WORD(4) = ( BEGINSTR STRBODY ENDSTR WORD(4) ) ALL +BEGINSTR STRBODY ENDSTR WORD(4) BEGINSTR STRBODY ENDSTR WORD(4) = ( BEGINSTR STRBODY ENDSTR WORD(4) ) ALL +BEGINSTR STRBODY ENDSTR WORD(4) BEGINSTR STRBODY ENDSTR WORD(4) = ( BEGINSTR STRBODY ENDSTR WORD(4) ) ALL +BEGINSTR STRBODY ENDSTR WORD(4) BEGINSTR STRBODY ENDSTR WORD(4) = ( BEGINSTR STRBODY ENDSTR WORD(4) ) ALL +BEGINSTR STRBODY ENDSTR WORD(4) BEGINSTR STRBODY ENDSTR WORD(4) = ( BEGINSTR STRBODY ENDSTR WORD(4) ) ALL + +# +BEGINSTR STRBODY ENDSTR USERGROUP BEGINSTR STRBODY ENDSTR WORD(4) = ( BEGINSTR STRBODY ENDSTR WORD(4) ) ALL +BEGINSTR STRBODY ENDSTR USERGROUP BEGINSTR STRBODY ENDSTR WORD(4) = ( BEGINSTR STRBODY ENDSTR WORD(4) ) ALL +BEGINSTR STRBODY ENDSTR USERGROUP BEGINSTR STRBODY ENDSTR WORD(4) = ( BEGINSTR STRBODY ENDSTR WORD(4) ) ALL +BEGINSTR STRBODY BACKSLASH STRBODY BACKSLASH STRBODY ENDSTR USERGROUP BEGINSTR STRBODY ENDSTR WORD(4) = ( BEGINSTR STRBODY ENDSTR WORD(4) ) ALL +BEGINSTR STRBODY ENDSTR USERGROUP BEGINSTR STRBODY ENDSTR WORD(4) = ( BEGINSTR STRBODY ENDSTR WORD(4) ) ALL +BEGINSTR STRBODY ENDSTR USERGROUP BEGINSTR STRBODY ENDSTR WORD(4) = ( BEGINSTR STRBODY ENDSTR WORD(4) ) ALL +BEGINSTR STRBODY BACKSLASH STRBODY ENDSTR USERGROUP BEGINSTR STRBODY ENDSTR WORD(4) = ( BEGINSTR STRBODY ENDSTR WORD(4) ) ALL +BEGINSTR STRBODY ENDSTR NETGROUP BEGINSTR STRBODY ENDSTR WORD(4) = ( BEGINSTR STRBODY ENDSTR WORD(4) ) ALL diff --git a/plugins/sudoers/regress/sudoers/test3.in b/plugins/sudoers/regress/sudoers/test3.in new file mode 100644 index 0000000..82fcd83 --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test3.in @@ -0,0 +1,6 @@ +# Test whitespace in User_List as part of a per-user Defaults entry +User_Alias FOO = foo, bar +Defaults:FOO env_reset +Defaults:foo,bar env_reset +Defaults:foo,\ bar env_reset +Defaults:foo, bar env_reset diff --git a/plugins/sudoers/regress/sudoers/test3.out.ok b/plugins/sudoers/regress/sudoers/test3.out.ok new file mode 100644 index 0000000..af2f402 --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test3.out.ok @@ -0,0 +1,9 @@ +Parses OK. + +Defaults:FOO env_reset +Defaults:foo,bar env_reset +Defaults:foo, bar env_reset +Defaults:foo,bar env_reset + +User_Alias FOO = foo, bar + diff --git a/plugins/sudoers/regress/sudoers/test3.toke.ok b/plugins/sudoers/regress/sudoers/test3.toke.ok new file mode 100644 index 0000000..49f2e51 --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test3.toke.ok @@ -0,0 +1,6 @@ +# +USERALIAS ALIAS = WORD(5) , WORD(5) +DEFAULTS_USER ALIAS DEFVAR +DEFAULTS_USER WORD(5) , WORD(5) DEFVAR +DEFAULTS_USER WORD(5) , WORD(5) DEFVAR +DEFAULTS_USER WORD(5) , WORD(5) DEFVAR diff --git a/plugins/sudoers/regress/sudoers/test4.in b/plugins/sudoers/regress/sudoers/test4.in new file mode 100644 index 0000000..b8df454 --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test4.in @@ -0,0 +1,7 @@ +# Test line continuation with anchored matches +User_Alias FOO = foo \ +: BAR = bar + +# This used to pass for sudo < 1.8.1 (though it should not have) +User_Alias FOO = foo \ +User_Alias BAR = bar diff --git a/plugins/sudoers/regress/sudoers/test4.out.ok b/plugins/sudoers/regress/sudoers/test4.out.ok new file mode 100644 index 0000000..851e644 --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test4.out.ok @@ -0,0 +1,6 @@ +Does not parse. + + +User_Alias BAR = bar +User_Alias FOO = foo + diff --git a/plugins/sudoers/regress/sudoers/test4.toke.ok b/plugins/sudoers/regress/sudoers/test4.toke.ok new file mode 100644 index 0000000..a225792 --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test4.toke.ok @@ -0,0 +1,5 @@ +# +USERALIAS ALIAS = WORD(5) : ALIAS = WORD(5) + +# +USERALIAS ALIAS = WORD(5) ERROR <*> ALIAS = WORD(5) diff --git a/plugins/sudoers/regress/sudoers/test5.in b/plugins/sudoers/regress/sudoers/test5.in new file mode 100644 index 0000000..354f589 --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test5.in @@ -0,0 +1,3 @@ +# Test empty string in User_Alias and Command_Spec +User_Alias FOO = "" +"" ALL = ALL diff --git a/plugins/sudoers/regress/sudoers/test5.out.ok b/plugins/sudoers/regress/sudoers/test5.out.ok new file mode 100644 index 0000000..6b6f261 --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test5.out.ok @@ -0,0 +1,4 @@ +Does not parse. + + + diff --git a/plugins/sudoers/regress/sudoers/test5.toke.ok b/plugins/sudoers/regress/sudoers/test5.toke.ok new file mode 100644 index 0000000..9376455 --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test5.toke.ok @@ -0,0 +1,3 @@ +# +USERALIAS ALIAS = BEGINSTR ENDSTR ERROR <*> +BEGINSTR ENDSTR ERROR <*> ALL = ALL diff --git a/plugins/sudoers/regress/sudoers/test6.in b/plugins/sudoers/regress/sudoers/test6.in new file mode 100644 index 0000000..e804571 --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test6.in @@ -0,0 +1,15 @@ +# Check that uids work in per-user and per-runas Defaults +Defaults:#123 set_home +Defaults>#123 set_home +Defaults:"#123" set_home +Defaults>"#123" set_home + +# Check that uids work in a Command_Spec +#0 ALL = ALL +#0 ALL = (#0 : #0) ALL +"#0" ALL = ALL +"#0" ALL = ("#0" : "#0") ALL + +# Check that gids work in a Command_Spec +%#0 ALL = ALL +"%#0" ALL = ALL diff --git a/plugins/sudoers/regress/sudoers/test6.out.ok b/plugins/sudoers/regress/sudoers/test6.out.ok new file mode 100644 index 0000000..275add6 --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test6.out.ok @@ -0,0 +1,14 @@ +Parses OK. + +Defaults:#123 set_home +Defaults>#123 set_home +Defaults:#123 set_home +Defaults>#123 set_home + + +#0 ALL = ALL +#0 ALL = (#0 : #0) ALL +#0 ALL = ALL +#0 ALL = (#0 : #0) ALL +%#0 ALL = ALL +%#0 ALL = ALL diff --git a/plugins/sudoers/regress/sudoers/test6.toke.ok b/plugins/sudoers/regress/sudoers/test6.toke.ok new file mode 100644 index 0000000..a9c0522 --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test6.toke.ok @@ -0,0 +1,15 @@ +# +DEFAULTS_USER WORD(5) DEFVAR +DEFAULTS_RUNAS WORD(5) DEFVAR +DEFAULTS_USER BEGINSTR STRBODY ENDSTR WORD(4) DEFVAR +DEFAULTS_RUNAS BEGINSTR STRBODY ENDSTR WORD(4) DEFVAR + +# +WORD(5) ALL = ALL +WORD(5) ALL = ( WORD(5) : WORD(5) ) ALL +BEGINSTR STRBODY ENDSTR WORD(4) ALL = ALL +BEGINSTR STRBODY ENDSTR WORD(4) ALL = ( BEGINSTR STRBODY ENDSTR WORD(4) : BEGINSTR STRBODY ENDSTR WORD(4) ) ALL + +# +USERGROUP ALL = ALL +BEGINSTR STRBODY ENDSTR USERGROUP ALL = ALL diff --git a/plugins/sudoers/regress/sudoers/test7.in b/plugins/sudoers/regress/sudoers/test7.in new file mode 100644 index 0000000..7b241d0 --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test7.in @@ -0,0 +1,7 @@ +# These should all be syntax errors +User_Alias FOO1 = "%" +User_Alias FOO2 = "%:" +User_Alias FOO3 = "+" +User_Alias FOO4 = % +User_Alias FOO5 = %: +User_Alias FOO6 = + diff --git a/plugins/sudoers/regress/sudoers/test7.out.ok b/plugins/sudoers/regress/sudoers/test7.out.ok new file mode 100644 index 0000000..6b6f261 --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test7.out.ok @@ -0,0 +1,4 @@ +Does not parse. + + + diff --git a/plugins/sudoers/regress/sudoers/test7.toke.ok b/plugins/sudoers/regress/sudoers/test7.toke.ok new file mode 100644 index 0000000..a5bf018 --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test7.toke.ok @@ -0,0 +1,7 @@ +# +USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR ERROR <*> +USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR ERROR <*> +USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR ERROR <*> +USERALIAS ALIAS = ERROR <*> +USERALIAS ALIAS = ERROR <*> +USERALIAS ALIAS = ERROR <*> diff --git a/plugins/sudoers/regress/sudoers/test8.in b/plugins/sudoers/regress/sudoers/test8.in new file mode 100644 index 0000000..d25e834 --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test8.in @@ -0,0 +1,8 @@ +# Test quoted strings +User_Alias UA1 = "xy" +User_Alias UA2 = "x\ +y" +User_Alias UA3 = x\"y + +# A newline in the middle of a string is an error +User_Alias UA4 = "x diff --git a/plugins/sudoers/regress/sudoers/test8.out.ok b/plugins/sudoers/regress/sudoers/test8.out.ok new file mode 100644 index 0000000..ccea904 --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test8.out.ok @@ -0,0 +1,7 @@ +Does not parse. + + +User_Alias UA1 = xy +User_Alias UA2 = xy +User_Alias UA3 = x"y + diff --git a/plugins/sudoers/regress/sudoers/test8.toke.ok b/plugins/sudoers/regress/sudoers/test8.toke.ok new file mode 100644 index 0000000..0f7e2a9 --- /dev/null +++ b/plugins/sudoers/regress/sudoers/test8.toke.ok @@ -0,0 +1,7 @@ +# +USERALIAS ALIAS = BEGINSTR STRBODY ENDSTR WORD(4) +USERALIAS ALIAS = BEGINSTR STRBODY STRBODY ENDSTR WORD(4) +USERALIAS ALIAS = WORD(5) + +# +USERALIAS ALIAS = BEGINSTR STRBODY ERROR <*> ERROR \ No newline at end of file diff --git a/plugins/sudoers/regress/testsudoers/test1.out.ok b/plugins/sudoers/regress/testsudoers/test1.out.ok new file mode 100644 index 0000000..f980873 --- /dev/null +++ b/plugins/sudoers/regress/testsudoers/test1.out.ok @@ -0,0 +1,8 @@ +Parses OK. + +Entries for user root: + +ALL = ALL + host matched + +Command unmatched diff --git a/plugins/sudoers/regress/testsudoers/test1.sh b/plugins/sudoers/regress/testsudoers/test1.sh new file mode 100755 index 0000000..a6358b3 --- /dev/null +++ b/plugins/sudoers/regress/testsudoers/test1.sh @@ -0,0 +1,10 @@ +#!/bin/sh +# +# Test for NULL dereference with "sudo -g group" when the sudoers rule +# has no runas user or group listed. +# This is RedHat bug Bug 667103. +# + +./testsudoers -g bin root id < + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ + +#include + +#include +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#include +#include +#include + +#include "sudoers.h" + +/* + * Prototypes + */ +static void runas_setgroups(void); + +/* + * We keep track of the current permisstions and use a stack to restore + * the old permissions. A depth of 16 is overkill. + */ +struct perm_state { + uid_t ruid; + uid_t euid; +#ifdef HAVE_SETRESUID + uid_t suid; +#endif + gid_t rgid; + gid_t egid; +#ifdef HAVE_SETRESUID + gid_t sgid; +#endif + GETGROUPS_T *groups; + int ngroups; +}; + +#define PERM_STACK_MAX 16 +static struct perm_state perm_stack[PERM_STACK_MAX]; +static int perm_stack_depth = 0; + +/* XXX - make a runas_user struct? */ +int runas_ngroups = -1; +#ifdef HAVE_GETGROUPS +GETGROUPS_T *runas_groups; +#endif + +#undef ID +#define ID(x) (state->x == ostate->x ? -1 : state->x) +#undef OID +#define OID(x) (ostate->x == state->x ? -1 : ostate->x) + +void +rewind_perms(void) +{ + while (perm_stack_depth > 1) + restore_perms(); +} + +#ifdef HAVE_SETRESUID + +/* + * Set real and effective and saved uids and gids based on perm. + * We always retain a saved uid of 0 unless we are headed for an exec(). + * We only flip the effective gid since it only changes for PERM_SUDOERS. + * This version of set_perms() works fine with the "stay_setuid" option. + */ +int +set_perms(int perm) +{ + struct perm_state *state, *ostate = NULL; + const char *errstr; + int noexit; + + noexit = ISSET(perm, PERM_NOEXIT); + CLR(perm, PERM_MASK); + + if (perm_stack_depth == PERM_STACK_MAX) { + errstr = "perm stack overflow"; + errno = EINVAL; + goto bad; + } + + state = &perm_stack[perm_stack_depth]; + if (perm_stack_depth) + ostate = &perm_stack[perm_stack_depth - 1]; + + if (perm != PERM_INITIAL && memcmp(state, ostate, sizeof(*state)) == 0) + goto done; + + switch (perm) { + case PERM_INITIAL: + /* Stash initial state */ +#ifdef HAVE_GETRESUID + if (getresuid(&state->ruid, &state->euid, &state->suid)) { + errstr = "getresuid"; + goto bad; + + } + if (getresgid(&state->rgid, &state->egid, &state->sgid)) { + errstr = "getresgid"; + goto bad; + } +#else + state->ruid = getuid(); + state->euid = geteuid(); + state->suid = state->euid; /* in case we are setuid */ + + state->rgid = getgid(); + state->egid = getegid(); + state->sgid = state->egid; /* in case we are setgid */ +#endif + state->groups = user_groups; + state->ngroups = user_ngroups; + break; + + case PERM_ROOT: + state->ruid = ROOT_UID; + state->euid = ROOT_UID; + state->suid = ROOT_UID; + if (setresuid(ID(ruid), ID(euid), ID(suid))) { + errstr = "setresuid(ROOT_UID, ROOT_UID, ROOT_UID)"; + goto bad; + } + state->rgid = -1; + state->egid = -1; + state->sgid = -1; + state->groups = NULL; + state->ngroups = -1; + break; + + case PERM_USER: + state->groups = user_groups; + state->ngroups = user_ngroups; + if (state->ngroups != -1 && state->groups != ostate->groups) { + if (setgroups(state->ngroups, state->groups)) { + errstr = "setgroups()"; + goto bad; + } + } + state->rgid = -1; + state->egid = user_gid; + state->sgid = -1; + if (setresgid(-1, ID(egid), -1)) { + errstr = "setresgid(-1, user_gid, -1)"; + goto bad; + } + state->ruid = user_uid; + state->euid = user_uid; + state->suid = ROOT_UID; + if (setresuid(ID(ruid), ID(euid), ID(suid))) { + errstr = "setresuid(user_uid, user_uid, ROOT_UID)"; + goto bad; + } + break; + + case PERM_FULL_USER: + /* headed for exec() */ + state->groups = user_groups; + state->ngroups = user_ngroups; + if (state->ngroups != -1 && state->groups != ostate->groups) { + if (setgroups(state->ngroups, state->groups)) { + errstr = "setgroups()"; + goto bad; + } + } + state->rgid = user_gid; + state->egid = user_gid; + state->sgid = user_gid; + if (setresgid(ID(rgid), ID(egid), ID(sgid))) { + errstr = "setresgid(user_gid, user_gid, user_gid)"; + goto bad; + } + state->ruid = user_uid; + state->euid = user_uid; + state->suid = user_uid; + if (setresuid(ID(ruid), ID(euid), ID(suid))) { + errstr = "setresuid(user_uid, user_uid, user_uid)"; + goto bad; + } + break; + + case PERM_RUNAS: + runas_setgroups(); + state->groups = runas_groups; + state->ngroups = runas_ngroups; + + state->rgid = -1; + state->egid = runas_gr ? runas_gr->gr_gid : runas_pw->pw_gid; + state->sgid = -1; + if (setresgid(-1, ID(egid), -1)) { + errstr = "unable to change to runas gid"; + goto bad; + } + state->ruid = -1; + state->euid = runas_pw ? runas_pw->pw_uid : user_uid; + state->suid = -1; + if (setresuid(-1, ID(euid), -1)) { + errstr = "unable to change to runas uid"; + goto bad; + } + break; + + case PERM_SUDOERS: + state->groups = NULL; + state->ngroups = -1; + + /* assumes euid == ROOT_UID, ruid == user */ + state->rgid = -1; + state->egid = sudoers_gid; + state->sgid = -1; + if (setresgid(-1, ID(egid), -1)) + error(1, "unable to change to sudoers gid"); + + state->ruid = ROOT_UID; + /* + * If sudoers_uid == ROOT_UID and sudoers_mode is group readable + * we use a non-zero uid in order to avoid NFS lossage. + * Using uid 1 is a bit bogus but should work on all OS's. + */ + if (sudoers_uid == ROOT_UID && (sudoers_mode & 040)) + state->euid = 1; + else + state->euid = sudoers_uid; + state->suid = ROOT_UID; + if (setresuid(ID(ruid), ID(euid), ID(suid))) { + errstr = "setresuid(ROOT_UID, SUDOERS_UID, ROOT_UID)"; + goto bad; + } + break; + + case PERM_TIMESTAMP: + state->groups = NULL; + state->ngroups = -1; + state->rgid = -1; + state->egid = -1; + state->sgid = -1; + state->ruid = ROOT_UID; + state->euid = timestamp_uid; + state->suid = ROOT_UID; + if (setresuid(ID(ruid), ID(euid), ID(suid))) { + errstr = "setresuid(ROOT_UID, timestamp_uid, ROOT_UID)"; + goto bad; + } + break; + } + +done: + perm_stack_depth++; + return 1; +bad: + /* XXX - better warnings inline */ + warningx("%s: %s", errstr, + errno == EAGAIN ? "too many processes" : strerror(errno)); + if (noexit) + return 0; + exit(1); +} + +void +restore_perms(void) +{ + struct perm_state *state, *ostate; + + if (perm_stack_depth < 2) + return; + + state = &perm_stack[perm_stack_depth - 1]; + ostate = &perm_stack[perm_stack_depth - 2]; + perm_stack_depth--; + + /* XXX - more cases here where euid != ruid */ + if (OID(euid) == ROOT_UID && state->euid != ROOT_UID) { + if (setresuid(-1, ROOT_UID, -1)) { + warning("setresuid() [%d, %d, %d] -> [%d, %d, %d]", state->ruid, + state->euid, state->suid, -1, ROOT_UID, -1); + goto bad; + } + } + if (setresuid(OID(ruid), OID(euid), OID(suid))) { + warning("setresuid() [%d, %d, %d] -> [%d, %d, %d]", state->ruid, + state->euid, state->suid, OID(ruid), OID(euid), OID(suid)); + goto bad; + } + if (setresgid(OID(rgid), OID(egid), OID(sgid))) { + warning("setresgid() [%d, %d, %d] -> [%d, %d, %d]", state->rgid, + state->egid, state->sgid, OID(rgid), OID(egid), OID(sgid)); + goto bad; + } + if (state->ngroups != -1 && state->groups != ostate->groups) { + if (setgroups(ostate->ngroups, ostate->groups)) { + warning("setgroups()"); + goto bad; + } + } + return; + +bad: + exit(1); +} + +#else +# ifdef HAVE_SETREUID + +/* + * Set real and effective uids and gids based on perm. + * We always retain a real or effective uid of ROOT_UID unless + * we are headed for an exec(). + * This version of set_perms() works fine with the "stay_setuid" option. + */ +int +set_perms(int perm) +{ + struct perm_state *state, *ostate = NULL; + const char *errstr; + int noexit; + + noexit = ISSET(perm, PERM_NOEXIT); + CLR(perm, PERM_MASK); + + if (perm_stack_depth == PERM_STACK_MAX) { + errstr = "perm stack overflow"; + errno = EINVAL; + goto bad; + } + + state = &perm_stack[perm_stack_depth]; + if (perm_stack_depth) + ostate = &perm_stack[perm_stack_depth - 1]; + + if (perm != PERM_INITIAL && memcmp(state, ostate, sizeof(*state)) == 0) + goto done; + + switch (perm) { + case PERM_INITIAL: + /* Stash initial state */ + state->ruid = getuid(); + state->euid = geteuid(); + state->rgid = getgid(); + state->egid = getegid(); + state->groups = user_groups; + state->ngroups = user_ngroups; + break; + + case PERM_ROOT: + /* + * setreuid(0, 0) may fail on some systems + * when the euid is not already 0. + */ + if (setreuid(-1, ROOT_UID)) { + errstr = "setreuid(-1, ROOT_UID)"; + goto bad; + } + if (setuid(ROOT_UID)) { + errstr = "setuid(ROOT_UID)"; + goto bad; + } + state->ruid = ROOT_UID; + state->euid = ROOT_UID; + state->rgid = -1; + state->egid = -1; + state->groups = NULL; + state->ngroups = -1; + break; + + case PERM_USER: + state->groups = user_groups; + state->ngroups = user_ngroups; + if (state->ngroups != -1 && state->groups != ostate->groups) { + if (setgroups(state->ngroups, state->groups)) { + errstr = "setgroups()"; + goto bad; + } + } + state->rgid = -1; + state->egid = user_gid; + if (setregid(-1, ID(egid))) { + errstr = "setregid(-1, user_gid)"; + goto bad; + } + state->ruid = ROOT_UID; + state->euid = user_uid; + if (setreuid(ID(ruid), ID(euid))) { + errstr = "setreuid(ROOT_UID, user_uid)"; + goto bad; + } + break; + + case PERM_FULL_USER: + /* headed for exec() */ + state->groups = user_groups; + state->ngroups = user_ngroups; + if (state->ngroups != -1 && state->groups != ostate->groups) { + if (setgroups(state->ngroups, state->groups)) { + errstr = "setgroups()"; + goto bad; + } + } + state->rgid = user_gid; + state->egid = user_gid; + if (setregid(ID(rgid), ID(egid))) { + errstr = "setregid(user_gid, user_gid)"; + goto bad; + } + state->ruid = user_uid; + state->euid = user_uid; + if (setreuid(ID(ruid), ID(euid))) { + errstr = "setreuid(user_uid, user_uid)"; + goto bad; + } + break; + + case PERM_RUNAS: + runas_setgroups(); + state->groups = runas_groups; + state->ngroups = runas_ngroups; + + state->rgid = -1; + state->egid = runas_gr ? runas_gr->gr_gid : runas_pw->pw_gid; + if (setregid(ID(rgid), ID(egid))) { + errstr = "unable to change to runas gid"; + goto bad; + } + state->ruid = ROOT_UID; + state->euid = runas_pw ? runas_pw->pw_uid : user_uid; + if (setreuid(ID(ruid), ID(euid))) { + errstr = "unable to change to runas uid"; + goto bad; + } + break; + + case PERM_SUDOERS: + state->groups = NULL; + state->ngroups = -1; + + /* assume euid == ROOT_UID, ruid == user */ + state->rgid = -1; + state->egid = sudoers_gid; + if (setregid(-1, ID(egid))) + error(1, "unable to change to sudoers gid"); + + state->ruid = ROOT_UID; + /* + * If sudoers_uid == ROOT_UID and sudoers_mode is group readable + * we use a non-zero uid in order to avoid NFS lossage. + * Using uid 1 is a bit bogus but should work on all OS's. + */ + if (sudoers_uid == ROOT_UID && (sudoers_mode & 040)) + state->euid = 1; + else + state->euid = sudoers_uid; + if (setreuid(ID(ruid), ID(euid))) { + errstr = "setreuid(ROOT_UID, SUDOERS_UID)"; + goto bad; + } + break; + + case PERM_TIMESTAMP: + state->groups = NULL; + state->ngroups = -1; + state->rgid = -1; + state->egid = -1; + state->ruid = ROOT_UID; + state->euid = timestamp_uid; + if (setreuid(ID(ruid), ID(euid))) { + errstr = "setreuid(ROOT_UID, timestamp_uid)"; + goto bad; + } + break; + } + +done: + perm_stack_depth++; + return 1; +bad: + /* XXX - better warnings inline */ + warningx("%s: %s", errstr, + errno == EAGAIN ? "too many processes" : strerror(errno)); + if (noexit) + return 0; + exit(1); +} + +void +restore_perms(void) +{ + struct perm_state *state, *ostate; + + if (perm_stack_depth < 2) + return; + + state = &perm_stack[perm_stack_depth - 1]; + ostate = &perm_stack[perm_stack_depth - 2]; + perm_stack_depth--; + + /* + * When changing euid to ROOT_UID, setreuid() may fail even if + * the ruid is ROOT_UID so call setuid() first. + */ + if (OID(euid) == ROOT_UID) { + /* setuid() may not set the saved ID unless the euid is ROOT_UID */ + if (ID(euid) != ROOT_UID) + (void)setreuid(-1, ROOT_UID); + if (setuid(ROOT_UID)) { + warning("setuid(%d)", ROOT_UID); + goto bad; + } + } + if (setreuid(OID(ruid), OID(euid))) { + warning("setreuid() [%d, %d] -> [%d, %d]", state->ruid, + state->euid, OID(ruid), OID(euid)); + goto bad; + } + if (setregid(OID(rgid), OID(egid))) { + warning("setregid() [%d, %d] -> [%d, %d]", state->rgid, + state->egid, OID(rgid), OID(egid)); + goto bad; + } + if (state->ngroups != -1 && state->groups != ostate->groups) { + if (setgroups(ostate->ngroups, ostate->groups)) { + warning("setgroups()"); + goto bad; + } + } + return; + +bad: + exit(1); +} + +# else /* !HAVE_SETRESUID && !HAVE_SETREUID */ +# ifdef HAVE_SETEUID + +/* + * Set real and effective uids and gids based on perm. + * We always retain a real or effective uid of ROOT_UID unless + * we are headed for an exec(). + * This version of set_perms() works fine with the "stay_setuid" option. + */ +int +set_perms(int perm) +{ + struct perm_state *state, *ostate = NULL; + const char *errstr; + int noexit; + + noexit = ISSET(perm, PERM_NOEXIT); + CLR(perm, PERM_MASK); + + if (perm_stack_depth == PERM_STACK_MAX) { + errstr = "perm stack overflow"; + errno = EINVAL; + goto bad; + } + + state = &perm_stack[perm_stack_depth]; + if (perm_stack_depth) + ostate = &perm_stack[perm_stack_depth - 1]; + + if (perm != PERM_INITIAL && memcmp(state, ostate, sizeof(*state)) == 0) + goto done; + + /* + * Since we only have setuid() and seteuid() and semantics + * for these calls differ on various systems, we set + * real and effective uids to ROOT_UID initially to be safe. + */ + if (perm != PERM_INITIAL) { + if (seteuid(ROOT_UID)) { + errstr = "seteuid(ROOT_UID)"; + goto bad; + } + if (setuid(ROOT_UID)) { + errstr = "setuid(ROOT_UID)"; + goto bad; + } + } + + switch (perm) { + case PERM_INITIAL: + /* Stash initial state */ + state->ruid = getuid(); + state->euid = geteuid(); + state->rgid = getgid(); + state->egid = getegid(); + state->groups = user_groups; + state->ngroups = user_ngroups; + break; + + case PERM_ROOT: + /* We already set ruid/euid above. */ + state->ruid = ROOT_UID; + state->euid = ROOT_UID; + state->rgid = -1; + state->egid = -1; + state->groups = NULL; + state->ngroups = -1; + break; + + case PERM_USER: + state->groups = user_groups; + state->ngroups = user_ngroups; + if (state->ngroups != -1 && state->groups != ostate->groups) { + if (setgroups(state->ngroups, state->groups)) { + errstr = "setgroups()"; + goto bad; + } + } + state->rgid = -1; + state->egid = user_gid; + if (setegid(ID(egid))) { + errstr = "setegid(user_gid)"; + goto bad; + } + state->ruid = ROOT_UID; + state->euid = user_uid; + if (seteuid(ID(euid))) { + errstr = "seteuid(user_uid)"; + goto bad; + } + break; + + case PERM_FULL_USER: + /* headed for exec() */ + state->groups = user_groups; + state->ngroups = user_ngroups; + if (state->ngroups != -1 && state->groups != ostate->groups) { + if (setgroups(state->ngroups, state->groups)) { + errstr = "setgroups()"; + goto bad; + } + } + state->rgid = user_gid; + state->egid = user_gid; + if (setgid(user_gid)) { + errstr = "setgid(user_gid)"; + goto bad; + } + state->ruid = user_uid; + state->euid = user_uid; + if (setuid(user_uid)) { + errstr = "setuid(user_uid)"; + goto bad; + } + break; + + case PERM_RUNAS: + runas_setgroups(); + state->groups = runas_groups; + state->ngroups = runas_ngroups; + + state->rgid = -1; + state->egid = runas_gr ? runas_gr->gr_gid : runas_pw->pw_gid; + if (setegid(ID(egid))) { + errstr = "unable to change to runas gid"; + goto bad; + } + state->ruid = -1; + state->euid = runas_pw ? runas_pw->pw_uid : user_uid; + if (seteuid(ID(euid))) { + errstr = "unable to change to runas uid"; + goto bad; + } + break; + + case PERM_SUDOERS: + state->groups = NULL; + state->ngroups = -1; + + /* assume euid == ROOT_UID, ruid == user */ + state->rgid = -1; + state->egid = sudoers_gid; + if (setegid(ID(egid))) + error(1, "unable to change to sudoers gid"); + + state->ruid = ROOT_UID; + /* + * If sudoers_uid == ROOT_UID and sudoers_mode is group readable + * we use a non-zero uid in order to avoid NFS lossage. + * Using uid 1 is a bit bogus but should work on all OS's. + */ + if (sudoers_uid == ROOT_UID && (sudoers_mode & 040)) + state->euid = 1; + else + state->euid = sudoers_uid; + if (seteuid(ID(euid))) { + errstr = "seteuid(SUDOERS_UID)"; + goto bad; + } + break; + + case PERM_TIMESTAMP: + state->groups = NULL; + state->ngroups = -1; + state->rgid = -1; + state->egid = -1; + state->ruid = ROOT_UID; + state->euid = timestamp_uid; + if (seteuid(ID(euid))) { + errstr = "seteuid(timestamp_uid)"; + goto bad; + } + break; + } + +done: + perm_stack_depth++; + return 1; +bad: + /* XXX - better warnings inline */ + warningx("%s: %s", errstr, + errno == EAGAIN ? "too many processes" : strerror(errno)); + if (noexit) + return 0; + exit(1); +} + +void +restore_perms(void) +{ + struct perm_state *state, *ostate; + + if (perm_stack_depth < 2) + return; + + state = &perm_stack[perm_stack_depth - 1]; + ostate = &perm_stack[perm_stack_depth - 2]; + perm_stack_depth--; + + /* + * Since we only have setuid() and seteuid() and semantics + * for these calls differ on various systems, we set + * real and effective uids to ROOT_UID initially to be safe. + */ + if (seteuid(ROOT_UID)) { + errstr = "seteuid(ROOT_UID)"; + goto bad; + } + if (setuid(ROOT_UID)) { + errstr = "setuid(ROOT_UID)"; + goto bad; + } + + if (setegid(OID(egid))) { + warning("setegid(%d)", OID(egid)); + goto bad; + } + if (state->ngroups != -1 && state->groups != ostate->groups) { + if (setgroups(ostate->ngroups, ostate->groups)) { + warning("setgroups()"); + goto bad; + } + } + if (seteuid(OID(euid))) { + warning("seteuid(%d)", OID(euid)); + goto bad; + } + return; + +bad: + exit(1); +} + +# else /* !HAVE_SETRESUID && !HAVE_SETREUID && !HAVE_SETEUID */ + +/* + * Set uids and gids based on perm via setuid() and setgid(). + * NOTE: does not support the "stay_setuid" or timestampowner options. + * Also, sudoers_uid and sudoers_gid are not used. + */ +int +set_perms(int perm) +{ + struct perm_state *state, *ostate = NULL; + const char *errstr; + int noexit; + + noexit = ISSET(perm, PERM_NOEXIT); + CLR(perm, PERM_MASK); + + if (perm_stack_depth == PERM_STACK_MAX) { + errstr = "perm stack overflow"; + errno = EINVAL; + goto bad; + } + + state = &perm_stack[perm_stack_depth]; + if (perm_stack_depth) + ostate = &perm_stack[perm_stack_depth - 1]; + + if (perm != PERM_INITIAL && memcmp(state, ostate, sizeof(*state)) == 0) + goto done; + + switch (perm) { + case PERM_INITIAL: + /* Stash initial state */ + state->ruid = getuid(); + state->rgid = getgid(); + state->groups = user_groups; + state->ngroups = user_ngroups; + break; + + case PERM_ROOT: + state->ruid = ROOT_UID; + state->rgid = -1; + state->groups = NULL; + state->ngroups = -1; + if (setuid(ROOT_UID)) { + errstr = "setuid(ROOT_UID)"; + goto bad; + } + break; + + case PERM_FULL_USER: + state->groups = user_groups; + state->ngroups = user_ngroups; + if (state->ngroups != -1 && state->groups != ostate->groups) { + if (setgroups(state->ngroups, state->groups)) { + errstr = "setgroups()"; + goto bad; + } + } + state->rgid = user_gid; + (void) setgid(user_gid); + state->ruid = user_uid; + if (setuid(user_uid)) { + errstr = "setuid(user_uid)"; + goto bad; + } + break; + + case PERM_USER: + case PERM_SUDOERS: + case PERM_RUNAS: + case PERM_TIMESTAMP: + /* Unsupported since we can't set euid. */ + break; + } + +done: + perm_stack_depth++; + return 1; +bad: + /* XXX - better warnings inline */ + warningx("%s: %s", errstr, + errno == EAGAIN ? "too many processes" : strerror(errno)); + if (noexit) + return 0; + exit(1); +} + +void +restore_perms(void) +{ + struct perm_state *state, *ostate; + + if (perm_stack_depth < 2) + return; + + state = &perm_stack[perm_stack_depth - 1]; + ostate = &perm_stack[perm_stack_depth - 2]; + perm_stack_depth--; + + if (state->ngroups != -1 && state->groups != ostate->groups) { + if (setgroups(ostate->ngroups, ostate->groups)) { + warning("setgroups()"); + goto bad; + } + } + if (OID(rgid) != -1 && setgid(ostate->rgid)) { + warning("setgid(%d)", ostate->rgid); + goto bad; + } + if (OID(ruid) != -1 && setuid(ostate->ruid)) { + warning("setuid(%d)", ostate->ruid); + goto bad; + } + return; + +bad: + exit(1); +} +# endif /* HAVE_SETEUID */ +# endif /* HAVE_SETREUID */ +#endif /* HAVE_SETRESUID */ + +#ifdef HAVE_INITGROUPS +static void +runas_setgroups() +{ + static struct passwd *pw; + struct passwd *opw = pw; + + if (def_preserve_groups) + return; + + /* + * Use stashed copy of runas groups if available, else initgroups and stash. + */ + pw = runas_pw ? runas_pw : sudo_user.pw; + if (pw != opw) { + pw = runas_pw ? runas_pw : sudo_user.pw; +# ifdef HAVE_SETAUTHDB + aix_setauthdb(pw->pw_name); +# endif + if (initgroups(pw->pw_name, pw->pw_gid) < 0) + log_error(USE_ERRNO|MSG_ONLY, "can't set runas group vector"); +# ifdef HAVE_GETGROUPS + if (runas_groups) { + efree(runas_groups); + runas_groups = NULL; + } + if ((runas_ngroups = getgroups(0, NULL)) > 0) { + runas_groups = emalloc2(runas_ngroups, sizeof(GETGROUPS_T)); + if (getgroups(runas_ngroups, runas_groups) < 0) + log_error(USE_ERRNO|MSG_ONLY, "can't get runas group vector"); + } +# ifdef HAVE_SETAUTHDB + aix_restoreauthdb(); +# endif + } else { + if (setgroups(runas_ngroups, runas_groups) < 0) + log_error(USE_ERRNO|MSG_ONLY, "can't set runas group vector"); +# endif /* HAVE_GETGROUPS */ + } +} + +#else + +static void +runas_setgroups() +{ + /* STUB */ +} + +#endif /* HAVE_INITGROUPS */ diff --git a/sudo_nss.c b/plugins/sudoers/sudo_nss.c similarity index 90% rename from sudo_nss.c rename to plugins/sudoers/sudo_nss.c index 9630320..2f77d89 100644 --- a/sudo_nss.c +++ b/plugins/sudoers/sudo_nss.c @@ -40,7 +40,7 @@ #include #include -#include "sudo.h" +#include "sudoers.h" #include "lbuf.h" extern struct sudo_nss sudo_nss_file; @@ -54,7 +54,7 @@ extern struct sudo_nss sudo_nss_ldap; * Returns a tail queue of matches. */ struct sudo_nss_list * -sudo_read_nss() +sudo_read_nss(void) { FILE *fp; char *cp; @@ -112,7 +112,7 @@ nomatch: * Returns a tail queue of matches. */ struct sudo_nss_list * -sudo_read_nss() +sudo_read_nss(void) { FILE *fp; char *cp, *ep; @@ -188,7 +188,7 @@ nomatch: * Non-nsswitch.conf version with hard-coded order. */ struct sudo_nss_list * -sudo_read_nss() +sudo_read_nss(void) { static struct sudo_nss_list snl; @@ -206,8 +206,7 @@ sudo_read_nss() /* Reset user_groups based on passwd entry. */ static void -reset_groups(pw) - struct passwd *pw; +reset_groups(struct passwd *pw) { #if defined(HAVE_INITGROUPS) && defined(HAVE_GETGROUPS) if (pw != sudo_user.pw) { @@ -227,14 +226,23 @@ reset_groups(pw) aix_restoreauthdb(); # endif } -#endif /* HAVE_INITGROUPS && HAVE_GETGROUPS */ +#endif } static int -output(buf) - const char *buf; +output(const char *buf) { - return fputs(buf, stdout); + struct sudo_conv_message msg; + struct sudo_conv_reply repl; + + /* Call conversation function */ + memset(&msg, 0, sizeof(msg)); + msg.msg_type = SUDO_CONV_INFO_MSG; + msg.msg = buf; + memset(&repl, 0, sizeof(repl)); + if (sudo_conv(1, &msg, &repl) == -1) + return 0; + return (int)strlen(buf); } /* @@ -242,9 +250,7 @@ output(buf) * We only get here if the user is allowed to run something on this host. */ void -display_privs(snl, pw) - struct sudo_nss_list *snl; - struct passwd *pw; +display_privs(struct sudo_nss_list *snl, struct passwd *pw) { struct sudo_nss *nss; struct lbuf defs, privs; @@ -253,8 +259,8 @@ display_privs(snl, pw) /* Reset group vector so group matching works correctly. */ reset_groups(pw); - lbuf_init(&defs, output, 4, NULL); - lbuf_init(&privs, output, 4, NULL); + lbuf_init(&defs, output, 4, NULL, sudo_user.cols); + lbuf_init(&privs, output, 4, NULL, sudo_user.cols); /* Display defaults from all sources. */ lbuf_append(&defs, "Matching Defaults entries for ", pw->pw_name, @@ -303,11 +309,10 @@ display_privs(snl, pw) /* * Check user_cmnd against sudoers and print the matching entry if the * command is allowed. + * Returns TRUE if the command is allowed, else FALSE. */ int -display_cmnd(snl, pw) - struct sudo_nss_list *snl; - struct passwd *pw; +display_cmnd(struct sudo_nss_list *snl, struct passwd *pw) { struct sudo_nss *nss; @@ -316,7 +321,7 @@ display_cmnd(snl, pw) tq_foreach_fwd(snl, nss) { if (nss->display_cmnd(nss, pw) == 0) - return 0; + return TRUE; } - return 1; + return FALSE; } diff --git a/sudo_nss.h b/plugins/sudoers/sudo_nss.h similarity index 57% rename from sudo_nss.h rename to plugins/sudoers/sudo_nss.h index f036add..8d08944 100644 --- a/sudo_nss.h +++ b/plugins/sudoers/sudo_nss.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2009 Todd C. Miller + * Copyright (c) 2007-2011 * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,21 +14,24 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#ifndef _SUDO_NSS_H +#define _SUDO_NSS_H + struct lbuf; struct passwd; struct sudo_nss { struct sudo_nss *prev; struct sudo_nss *next; - int (*open) __P((struct sudo_nss *nss)); - int (*close) __P((struct sudo_nss *nss)); - int (*parse) __P((struct sudo_nss *nss)); - int (*setdefs) __P((struct sudo_nss *nss)); - int (*lookup) __P((struct sudo_nss *nss, int, int)); - int (*display_cmnd) __P((struct sudo_nss *nss, struct passwd *)); - int (*display_defaults) __P((struct sudo_nss *nss, struct passwd *, struct lbuf *)); - int (*display_bound_defaults) __P((struct sudo_nss *nss, struct passwd *, struct lbuf *)); - int (*display_privs) __P((struct sudo_nss *nss, struct passwd *, struct lbuf *)); + int (*open)(struct sudo_nss *nss); + int (*close)(struct sudo_nss *nss); + int (*parse)(struct sudo_nss *nss); + int (*setdefs)(struct sudo_nss *nss); + int (*lookup)(struct sudo_nss *nss, int, int); + int (*display_cmnd)(struct sudo_nss *nss, struct passwd *); + int (*display_defaults)(struct sudo_nss *nss, struct passwd *, struct lbuf *); + int (*display_bound_defaults)(struct sudo_nss *nss, struct passwd *, struct lbuf *); + int (*display_privs)(struct sudo_nss *nss, struct passwd *, struct lbuf *); void *handle; short ret_if_found; short ret_if_notfound; @@ -36,4 +39,6 @@ struct sudo_nss { TQ_DECLARE(sudo_nss) -struct sudo_nss_list *sudo_read_nss __P((void)); +struct sudo_nss_list *sudo_read_nss(void); + +#endif /* _SUDO_NSS_H */ diff --git a/plugins/sudoers/sudoers.c b/plugins/sudoers/sudoers.c new file mode 100644 index 0000000..f533e59 --- /dev/null +++ b/plugins/sudoers/sudoers.c @@ -0,0 +1,1462 @@ +/* + * Copyright (c) 1993-1996, 1998-2011 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + * + * For a brief history of sudo, please see the HISTORY file included + * with this distribution. + */ + +#define _SUDO_MAIN + +#ifdef __TANDEM +# include +#endif + +#include + +#include +#include +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS) +# include +# endif +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#include +#include +#include +#include +#include +#include +#ifdef HAVE_SETLOCALE +# include +#endif +#include +#include +#ifdef HAVE_LOGIN_CAP_H +# include +# ifndef LOGIN_DEFROOTCLASS +# define LOGIN_DEFROOTCLASS "daemon" +# endif +#endif +#ifdef HAVE_SELINUX +# include +#endif +#ifdef HAVE_MBR_CHECK_MEMBERSHIP +# include +#endif +#include +#include + +#include "sudoers.h" +#include "lbuf.h" +#include "interfaces.h" +#include "sudoers_version.h" +#include "auth/sudo_auth.h" + +/* + * Prototypes + */ +static void init_vars(char * const *); +static int set_cmnd(int); +static void set_loginclass(struct passwd *); +static void set_runasgr(char *); +static void set_runaspw(char *); +static int sudoers_policy_version(int verbose); +static int deserialize_info(char * const settings[], char * const user_info[]); +static char *find_editor(int nfiles, char **files, char ***argv_out); +static void create_admin_success_flag(void); + +/* XXX */ +extern int runas_ngroups; +extern GETGROUPS_T *runas_groups; + +/* + * Globals + */ +const char *sudoers_file = _PATH_SUDOERS; +mode_t sudoers_mode = SUDOERS_MODE; +uid_t sudoers_uid = SUDOERS_UID; +gid_t sudoers_gid = SUDOERS_GID; +struct sudo_user sudo_user; +struct passwd *list_pw; +struct interface *interfaces; +int long_list; +int debug_level; +uid_t timestamp_uid; +extern int errorlineno; +extern int parse_error; +extern char *errorfile; +#ifdef HAVE_LOGIN_CAP_H +login_cap_t *lc; +#endif /* HAVE_LOGIN_CAP_H */ +#ifdef HAVE_BSD_AUTH_H +char *login_style; +#endif /* HAVE_BSD_AUTH_H */ +sudo_conv_t sudo_conv; +sudo_printf_t sudo_printf; +int sudo_mode; + +static char *prev_user; +static char *runas_user; +static char *runas_group; +static struct sudo_nss_list *snl; +static const char *interfaces_string; +static sigaction_t saved_sa_int, saved_sa_quit, saved_sa_tstp; + +/* XXX - must be extern for audit bits of sudo_auth.c */ +int NewArgc; +char **NewArgv; + +/* plugin_error.c */ +extern sigjmp_buf error_jmp; + +static int +sudoers_policy_open(unsigned int version, sudo_conv_t conversation, + sudo_printf_t plugin_printf, char * const settings[], + char * const user_info[], char * const envp[]) +{ + volatile int sources = 0; + sigaction_t sa; + struct sudo_nss *nss; + + if (!sudo_conv) + sudo_conv = conversation; + if (!sudo_printf) + sudo_printf = plugin_printf; + + if (sigsetjmp(error_jmp, 1)) { + /* called via error(), errorx() or log_error() */ + rewind_perms(); + return -1; + } + + /* + * Signal setup: + * Ignore keyboard-generated signals so the user cannot interrupt + * us at some point and avoid the logging. + * Install handler to wait for children when they exit. + */ + zero_bytes(&sa, sizeof(sa)); + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + sa.sa_handler = SIG_IGN; + (void) sigaction(SIGINT, &sa, &saved_sa_int); + (void) sigaction(SIGQUIT, &sa, &saved_sa_quit); + (void) sigaction(SIGTSTP, &sa, &saved_sa_tstp); + + sudo_setpwent(); + sudo_setgrent(); + + /* Initialize environment functions (including replacements). */ + env_init(envp); + + /* Setup defaults data structures. */ + init_defaults(); + + /* Parse settings and user_info */ + sudo_mode = deserialize_info(settings, user_info); + + init_vars(envp); /* XXX - move this later? */ + + /* Parse nsswitch.conf for sudoers order. */ + snl = sudo_read_nss(); + + set_perms(PERM_INITIAL); + + /* Open and parse sudoers, set global defaults */ + tq_foreach_fwd(snl, nss) { + if (nss->open(nss) == 0 && nss->parse(nss) == 0) { + sources++; + if (nss->setdefs(nss) != 0) + log_error(NO_STDERR|NO_EXIT, "problem with defaults entries"); + } + } + if (sources == 0) { + warningx("no valid sudoers sources found, quitting"); + return -1; + } + + /* XXX - collect post-sudoers parse settings into a function */ + + /* + * Initialize external group plugin. + */ + if (def_group_plugin) { + switch (group_plugin_load(def_group_plugin)) { + case -1: + return -1; + case FALSE: + def_group_plugin = NULL; + } + } + + /* + * 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. + */ + 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); + + if (!update_defaults(SETDEF_RUNAS)) + log_error(NO_STDERR|NO_EXIT, "problem with defaults entries"); + + if (def_fqdn) + set_fqdn(); /* deferred until after sudoers is parsed */ + + /* Set login class if applicable. */ + set_loginclass(sudo_user.pw); + + restore_perms(); + + return TRUE; +} + +static void +sudoers_policy_close(int exit_status, int error_code) +{ + if (sigsetjmp(error_jmp, 1)) { + /* called via error(), errorx() or log_error() */ + return; + } + + /* We do not currently log the exit status. */ + if (error_code) + warningx("unable to execute %s: %s", safe_cmnd, strerror(error_code)); + + /* Close the session we opened in sudoers_policy_init_session(). */ + if (ISSET(sudo_mode, MODE_RUN|MODE_EDIT)) + (void)auth_end_session(); + + /* Free remaining references to password and group entries. */ + pw_delref(sudo_user.pw); + pw_delref(runas_pw); + if (runas_gr != NULL) + gr_delref(runas_gr); +} + +/* + * The init_session function is called before executing the command + * and before uid/gid changes occur. + */ +static int +sudoers_policy_init_session(struct passwd *pwd) +{ + if (sigsetjmp(error_jmp, 1)) { + /* called via error(), errorx() or log_error() */ + return -1; + } + + return auth_begin_session(pwd); +} + +static int +sudoers_policy_main(int argc, char * const argv[], int pwflag, char *env_add[], + char **command_infop[], char **argv_out[], char **user_env_out[]) +{ + static char *command_info[32]; /* XXX */ + char **edit_argv = NULL; + struct sudo_nss *nss; + int cmnd_status = -1, validated; + volatile int info_len = 0; + volatile int rval = TRUE; + + if (sigsetjmp(error_jmp, 1)) { + /* error recovery via error(), errorx() or log_error() */ + rval = -1; + goto done; + } + + /* Is root even allowed to run sudo? */ + if (user_uid == 0 && !def_root_sudo) { + warningx("sudoers specifies that root is not allowed to sudo"); + goto bad; + } + + /* Check for -C overriding def_closefrom. */ + if (user_closefrom >= 0 && user_closefrom != def_closefrom) { + if (!def_closefrom_override) { + warningx("you are not permitted to use the -C option"); + goto bad; + } + def_closefrom = user_closefrom; + } + + set_perms(PERM_INITIAL); + + /* Environment variables specified on the command line. */ + if (env_add != NULL && env_add[0] != NULL) + sudo_user.env_vars = env_add; + + /* + * Make a local copy of argc/argv, with special handling + * for pseudo-commands and the '-i' option. + */ + if (argc == 0) { + NewArgc = 1; + NewArgv = emalloc2(NewArgc + 1, sizeof(char *)); + NewArgv[0] = user_cmnd; + NewArgv[1] = NULL; + } else { + NewArgc = argc; + NewArgv = emalloc2(NewArgc + 1, sizeof(char *)); + memcpy(NewArgv, argv, argc * sizeof(char *)); + NewArgv[NewArgc] = NULL; + if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) + NewArgv[0] = estrdup(runas_pw->pw_shell); + } + + /* Find command in path */ + cmnd_status = set_cmnd(sudo_mode); + if (cmnd_status == -1) { + rval = -1; + goto done; + } + +#ifdef HAVE_SETLOCALE + if (!setlocale(LC_ALL, def_sudoers_locale)) { + warningx("unable to set locale to \"%s\", using \"C\"", + def_sudoers_locale); + setlocale(LC_ALL, "C"); + } +#endif + + /* + * Check sudoers sources. + */ + validated = FLAG_NO_USER | FLAG_NO_HOST; + tq_foreach_fwd(snl, nss) { + validated = nss->lookup(nss, validated, pwflag); + + if (ISSET(validated, VALIDATE_OK)) { + /* Handle "= auth" in netsvc.conf */ + if (nss->ret_if_found) + break; + } else { + /* Handle [NOTFOUND=return] */ + if (nss->ret_if_notfound) + break; + } + } + + if (safe_cmnd == NULL) + safe_cmnd = estrdup(user_cmnd); + +#ifdef HAVE_SETLOCALE + setlocale(LC_ALL, ""); +#endif + + /* 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. + */ + if (def_timestampowner) { + struct passwd *pw; + + if (*def_timestampowner == '#') + pw = sudo_getpwuid(atoi(def_timestampowner + 1)); + else + pw = sudo_getpwnam(def_timestampowner); + if (!pw) + log_error(0, "timestamp owner (%s): No such user", + def_timestampowner); + timestamp_uid = pw->pw_uid; + pw_delref(pw); + } + + /* If given the -P option, set the "preserve_groups" flag. */ + if (ISSET(sudo_mode, MODE_PRESERVE_GROUPS)) + def_preserve_groups = TRUE; + + /* If no command line args and "shell_noargs" is not set, error out. */ + if (ISSET(sudo_mode, MODE_IMPLIED_SHELL) && !def_shell_noargs) { + rval = -2; /* usage error */ + goto done; + } + + /* Bail if a tty is required and we don't have one. */ + if (def_requiretty) { + int fd = open(_PATH_TTY, O_RDWR|O_NOCTTY); + if (fd == -1) { + audit_failure(NewArgv, "no tty"); + warningx("sorry, you must have a tty to run sudo"); + goto bad; + } else + (void) close(fd); + } + + /* + * We don't reset the environment for sudoedit or if the user + * specified the -E command line flag and they have setenv privs. + */ + if (ISSET(sudo_mode, MODE_EDIT) || + (ISSET(sudo_mode, MODE_PRESERVE_ENV) && def_setenv)) + def_env_reset = FALSE; + + /* Build a new environment that avoids any nasty bits. */ + rebuild_env(); + + /* Require a password if sudoers says so. */ + if (def_authenticate) { + int rc = check_user(validated, sudo_mode); + if (rc != TRUE) { + rval = rc; + goto done; + } + } + + /* If run as root with SUDO_USER set, set sudo_user.pw to that user. */ + /* XXX - causes confusion when root is not listed in sudoers */ + if (sudo_mode & (MODE_RUN | MODE_EDIT) && prev_user != NULL) { + if (user_uid == 0 && strcmp(prev_user, "root") != 0) { + struct passwd *pw; + + if ((pw = sudo_getpwnam(prev_user)) != NULL) { + if (sudo_user.pw != NULL) + pw_delref(sudo_user.pw); + sudo_user.pw = pw; +#ifdef HAVE_MBR_CHECK_MEMBERSHIP + mbr_uid_to_uuid(user_uid, user_uuid); +#endif + } + } + } + + /* If the user was not allowed to run the command we are done. */ + if (!ISSET(validated, VALIDATE_OK)) { + if (ISSET(validated, FLAG_NO_USER | FLAG_NO_HOST)) { + audit_failure(NewArgv, "No user or host"); + log_denial(validated, 1); + } else { + if (def_path_info) { + /* + * We'd like to not leak path info at all here, but that can + * *really* confuse the users. To really close the leak we'd + * have to say "not allowed to run foo" even when the problem + * is just "no foo in path" since the user can trivially set + * their path to just contain a single dir. + */ + log_denial(validated, + !(cmnd_status == NOT_FOUND_DOT || cmnd_status == NOT_FOUND)); + if (cmnd_status == NOT_FOUND) + warningx("%s: command not found", user_cmnd); + else if (cmnd_status == NOT_FOUND_DOT) + warningx("ignoring `%s' found in '.'\nUse `sudo ./%s' if this is the `%s' you wish to run.", user_cmnd, user_cmnd, user_cmnd); + } else { + /* Just tell the user they are not allowed to run foo. */ + log_denial(validated, 1); + } + audit_failure(NewArgv, "validation failure"); + } + goto bad; + } + + /* Create Ubuntu-style dot file to indicate sudo was successful. */ + create_admin_success_flag(); + + /* Finally tell the user if the command did not exist. */ + if (cmnd_status == NOT_FOUND_DOT) { + audit_failure(NewArgv, "command in current directory"); + warningx("ignoring `%s' found in '.'\nUse `sudo ./%s' if this is the `%s' you wish to run.", user_cmnd, user_cmnd, user_cmnd); + goto bad; + } else if (cmnd_status == NOT_FOUND) { + audit_failure(NewArgv, "%s: command not found", user_cmnd); + warningx("%s: command not found", user_cmnd); + goto bad; + } + + /* If user specified env vars make sure sudoers allows it. */ + if (ISSET(sudo_mode, MODE_RUN) && !def_setenv) { + if (ISSET(sudo_mode, MODE_PRESERVE_ENV)) { + warningx("sorry, you are not allowed to preserve the environment"); + goto bad; + } else + validate_env_vars(sudo_user.env_vars); + } + + if (ISSET(sudo_mode, (MODE_RUN | MODE_EDIT)) && (def_log_input || def_log_output)) { + if (def_iolog_file && def_iolog_dir) { + command_info[info_len++] = expand_iolog_path("iolog_path=", + def_iolog_dir, def_iolog_file, &sudo_user.iolog_file); + sudo_user.iolog_file++; + } + if (def_log_input) { + command_info[info_len++] = estrdup("iolog_stdin=true"); + command_info[info_len++] = estrdup("iolog_ttyin=true"); + } + if (def_log_output) { + command_info[info_len++] = estrdup("iolog_stdout=true"); + command_info[info_len++] = estrdup("iolog_stderr=true"); + command_info[info_len++] = estrdup("iolog_ttyout=true"); + } + if (def_compress_io) + command_info[info_len++] = estrdup("iolog_compress=true"); + } + + log_allowed(validated); + if (ISSET(sudo_mode, MODE_CHECK)) + rval = display_cmnd(snl, list_pw ? list_pw : sudo_user.pw); + else if (ISSET(sudo_mode, MODE_LIST)) + display_privs(snl, list_pw ? list_pw : sudo_user.pw); /* XXX - return val */ + + /* Cleanup sudoers sources */ + tq_foreach_fwd(snl, nss) { + nss->close(nss); + } + if (def_group_plugin) + group_plugin_unload(); + + if (ISSET(sudo_mode, (MODE_VALIDATE|MODE_CHECK|MODE_LIST))) { + /* rval already set appropriately */ + goto done; + } + + /* + * Set umask based on sudoers. + * If user's umask is more restrictive, OR in those bits too + * unless umask_override is set. + */ + if (def_umask != 0777) { + mode_t mask = def_umask; + if (!def_umask_override) { + mode_t omask = umask(mask); + mask |= omask; + umask(omask); + } + easprintf(&command_info[info_len++], "umask=0%o", (unsigned int)mask); + } + + if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) { + char *p; + + /* Convert /bin/sh -> -sh so shell knows it is a login shell */ + if ((p = strrchr(NewArgv[0], '/')) == NULL) + p = NewArgv[0]; + *p = '-'; + NewArgv[0] = p; + + /* Set cwd to run user's homedir. */ + command_info[info_len++] = fmt_string("cwd", runas_pw->pw_dir); + +#if defined(__linux__) || defined(_AIX) + /* Insert system-wide environment variables. */ + read_env_file(_PATH_ENVIRONMENT, TRUE); +#endif + } + + /* Insert system-wide environment variables. */ + if (def_env_file) + read_env_file(def_env_file, FALSE); + + /* Insert user-specified environment variables. */ + insert_env_vars(sudo_user.env_vars); + + /* Restore signal handlers before we exec. */ + (void) sigaction(SIGINT, &saved_sa_int, NULL); + (void) sigaction(SIGQUIT, &saved_sa_quit, NULL); + (void) sigaction(SIGTSTP, &saved_sa_tstp, NULL); + + if (ISSET(sudo_mode, MODE_EDIT)) { + char *editor = find_editor(NewArgc - 1, NewArgv + 1, &edit_argv); + if (editor == NULL) + goto bad; + command_info[info_len++] = fmt_string("command", editor); + command_info[info_len++] = estrdup("sudoedit=true"); + } else { + command_info[info_len++] = fmt_string("command", safe_cmnd); + } + if (def_stay_setuid) { + easprintf(&command_info[info_len++], "runas_uid=%u", + (unsigned int)user_uid); + easprintf(&command_info[info_len++], "runas_gid=%u", + (unsigned int)user_gid); + easprintf(&command_info[info_len++], "runas_euid=%u", + (unsigned int)runas_pw->pw_uid); + easprintf(&command_info[info_len++], "runas_egid=%u", + runas_gr ? (unsigned int)runas_gr->gr_gid : + (unsigned int)runas_pw->pw_gid); + } else { + easprintf(&command_info[info_len++], "runas_uid=%u", + (unsigned int)runas_pw->pw_uid); + easprintf(&command_info[info_len++], "runas_gid=%u", + runas_gr ? (unsigned int)runas_gr->gr_gid : + (unsigned int)runas_pw->pw_gid); + } + if (def_preserve_groups) { + command_info[info_len++] = "preserve_groups=true"; + } else if (runas_ngroups != -1) { + int i, len; + size_t glsize; + char *cp, *gid_list; + + glsize = sizeof("runas_groups=") - 1 + (runas_ngroups * (MAX_UID_T_LEN + 1)); + gid_list = emalloc(glsize); + memcpy(gid_list, "runas_groups=", sizeof("runas_groups=") - 1); + cp = gid_list + sizeof("runas_groups=") - 1; + for (i = 0; i < runas_ngroups; i++) { + /* XXX - check rval */ + len = snprintf(cp, glsize - (cp - gid_list), "%s%u", + i ? "," : "", (unsigned int) runas_groups[i]); + cp += len; + } + command_info[info_len++] = gid_list; + } + if (def_closefrom >= 0) + easprintf(&command_info[info_len++], "closefrom=%d", def_closefrom); + if (def_noexec) + command_info[info_len++] = estrdup("noexec=true"); + if (def_noexec_file) + command_info[info_len++] = fmt_string("noexec_file", def_noexec_file); + if (def_set_utmp) + command_info[info_len++] = estrdup("set_utmp=true"); + if (def_utmp_runas) + command_info[info_len++] = fmt_string("utmp_user", runas_pw->pw_name); +#ifdef HAVE_LOGIN_CAP_H + if (lc != NULL) + command_info[info_len++] = fmt_string("login_class", lc->lc_class); +#endif /* HAVE_LOGIN_CAP_H */ +#ifdef HAVE_SELINUX + if (user_role != NULL) + command_info[info_len++] = fmt_string("selinux_role", user_role); + if (user_type != NULL) + command_info[info_len++] = fmt_string("selinux_type", user_type); +#endif /* HAVE_SELINUX */ + + /* Must audit before uid change. */ + audit_success(NewArgv); + + *command_infop = command_info; + + *argv_out = edit_argv ? edit_argv : NewArgv; + *user_env_out = env_get(); /* our private copy */ + + goto done; + +bad: + rval = FALSE; + +done: + rewind_perms(); + + /* Close the password and group files and free up memory. */ + sudo_endpwent(); + sudo_endgrent(); + + return rval; +} + +static int +sudoers_policy_check(int argc, char * const argv[], char *env_add[], + char **command_infop[], char **argv_out[], char **user_env_out[]) +{ + if (!ISSET(sudo_mode, MODE_EDIT)) + SET(sudo_mode, MODE_RUN); + + return sudoers_policy_main(argc, argv, 0, env_add, command_infop, + argv_out, user_env_out); +} + +static int +sudoers_policy_validate(void) +{ + user_cmnd = "validate"; + SET(sudo_mode, MODE_VALIDATE); + + return sudoers_policy_main(0, NULL, I_VERIFYPW, NULL, NULL, NULL, NULL); +} + +static void +sudoers_policy_invalidate(int remove) +{ + user_cmnd = "kill"; + if (sigsetjmp(error_jmp, 1) == 0) { + remove_timestamp(remove); + plugin_cleanup(0); + } +} + +static int +sudoers_policy_list(int argc, char * const argv[], int verbose, + const char *list_user) +{ + int rval; + + user_cmnd = "list"; + if (argc) + SET(sudo_mode, MODE_CHECK); + else + SET(sudo_mode, MODE_LIST); + if (verbose) + long_list = 1; + if (list_user) { + list_pw = sudo_getpwnam(list_user); + if (list_pw == NULL) { + warningx("unknown user: %s", list_user); + return -1; + } + } + rval = sudoers_policy_main(argc, argv, I_LISTPW, NULL, NULL, NULL, NULL); + if (list_user) { + pw_delref(list_pw); + list_pw = NULL; + } + + return rval; +} + +/* + * Initialize timezone, set umask, fill in ``sudo_user'' struct and + * load the ``interfaces'' array. + */ +static void +init_vars(char * const envp[]) +{ + char * const * ep; + +#ifdef HAVE_TZSET + (void) tzset(); /* set the timezone if applicable */ +#endif /* HAVE_TZSET */ + + for (ep = envp; *ep; ep++) { + /* XXX - don't fill in if empty string */ + switch (**ep) { + case 'K': + if (strncmp("KRB5CCNAME=", *ep, 11) == 0) + user_ccname = *ep + 11; + break; + case 'P': + if (strncmp("PATH=", *ep, 5) == 0) + user_path = *ep + 5; + break; + case 'S': + if (!user_prompt && strncmp("SUDO_PROMPT=", *ep, 12) == 0) + user_prompt = *ep + 12; + else if (strncmp("SUDO_USER=", *ep, 10) == 0) + prev_user = *ep + 10; + break; + } + } + + /* + * Get a local copy of the user's struct passwd with the shadow password + * if necessary. It is assumed that euid is 0 at this point so we + * can read the shadow passwd file if necessary. + */ + if ((sudo_user.pw = sudo_getpwnam(user_name)) == NULL) { + struct passwd pw; + + /* Create a fake struct passwd for log_error(). */ + memset(&pw, 0, sizeof(pw)); + pw.pw_uid = getuid(); + pw.pw_name = user_name; + sudo_user.pw = &pw; + + /* + * It is not unusual for users to place "sudo -k" in a .logout + * file which can cause sudo to be run during reboot after the + * YP/NIS/NIS+/LDAP/etc daemon has died. + */ + if (sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE) + errorx(1, "unknown user: %s", user_name); + log_error(0, "unknown user: %s", user_name); + /* NOTREACHED */ + } +#ifdef HAVE_MBR_CHECK_MEMBERSHIP + mbr_uid_to_uuid(user_uid, user_uuid); +#endif + + /* It is now safe to use log_error() and set_perms() */ +} + +/* + * Fill in user_cmnd, user_args, user_base and user_stat variables + * and apply any command-specific defaults entries. + */ +static int +set_cmnd(int sudo_mode) +{ + int rval; + char *path = user_path; + + /* Resolve the path and return. */ + rval = FOUND; + user_stat = emalloc(sizeof(struct stat)); + + /* Default value for cmnd, overridden below. */ + if (user_cmnd == NULL) + user_cmnd = NewArgv[0]; + + if (sudo_mode & (MODE_RUN | MODE_EDIT | MODE_CHECK)) { + if (ISSET(sudo_mode, MODE_RUN | MODE_CHECK)) { + if (def_secure_path && !user_is_exempt()) + path = def_secure_path; + set_perms(PERM_RUNAS); + rval = find_path(NewArgv[0], &user_cmnd, user_stat, path, + def_ignore_dot); + restore_perms(); + if (rval != FOUND) { + /* Failed as root, try as invoking user. */ + set_perms(PERM_USER); + rval = find_path(NewArgv[0], &user_cmnd, user_stat, path, + def_ignore_dot); + restore_perms(); + } + } + + /* set user_args */ + if (NewArgc > 1) { + char *to, **from; + size_t size, n; + + /* Alloc and build up user_args. */ + for (size = 0, from = NewArgv + 1; *from; from++) + size += strlen(*from) + 1; + user_args = emalloc(size); + for (to = user_args, from = NewArgv + 1; *from; from++) { + n = strlcpy(to, *from, size - (to - user_args)); + if (n >= size - (to - user_args)) + errorx(1, "internal error, set_cmnd() overflow"); + to += n; + *to++ = ' '; + } + *--to = '\0'; + } + } + if (strlen(user_cmnd) >= PATH_MAX) + errorx(1, "%s: file name too long", user_cmnd); + + if ((user_base = strrchr(user_cmnd, '/')) != NULL) + user_base++; + else + user_base = user_cmnd; + + if (!update_defaults(SETDEF_CMND)) + log_error(NO_STDERR|NO_EXIT, "problem with defaults entries"); + + if (!runas_user && !runas_group) + set_runaspw(def_runas_default); /* may have been updated above */ + + return rval; +} + +/* + * Open sudoers and sanity check mode/owner/type. + * Returns a handle to the sudoers file or NULL on error. + */ +FILE * +open_sudoers(const char *sudoers, int doedit, int *keepopen) +{ + struct stat statbuf; + FILE *fp = NULL; + int rootstat; + + /* + * Fix the mode and group on sudoers file from old default. + * Only works if file system is readable/writable by root. + */ + if ((rootstat = stat_sudoers(sudoers, &statbuf)) == 0 && + sudoers_uid == statbuf.st_uid && sudoers_mode != 0400 && + (statbuf.st_mode & 0007777) == 0400) { + + if (chmod(sudoers, sudoers_mode) == 0) { + warningx("fixed mode on %s", sudoers); + SET(statbuf.st_mode, sudoers_mode); + if (statbuf.st_gid != sudoers_gid) { + if (chown(sudoers, (uid_t) -1, sudoers_gid) == 0) { + warningx("set group on %s", sudoers); + statbuf.st_gid = sudoers_gid; + } else + warning("unable to set group on %s", sudoers); + } + } else + warning("unable to fix mode on %s", sudoers); + } + + /* + * Sanity checks on sudoers file. Must be done as sudoers + * file owner. We already did a stat as root, so use that + * data if we can't stat as sudoers file owner. + */ + set_perms(PERM_SUDOERS); + + if (rootstat != 0 && stat_sudoers(sudoers, &statbuf) != 0) + log_error(USE_ERRNO|NO_EXIT, "can't stat %s", sudoers); + else if (!S_ISREG(statbuf.st_mode)) + log_error(NO_EXIT, "%s is not a regular file", sudoers); + else if ((statbuf.st_mode & 07577) != sudoers_mode) + log_error(NO_EXIT, "%s is mode 0%o, should be 0%o", sudoers, + (unsigned int) (statbuf.st_mode & 07777), + (unsigned int) sudoers_mode); + else if (statbuf.st_uid != sudoers_uid) + log_error(NO_EXIT, "%s is owned by uid %u, should be %u", sudoers, + (unsigned int) statbuf.st_uid, (unsigned int) sudoers_uid); + else if (statbuf.st_gid != sudoers_gid) + log_error(NO_EXIT, "%s is owned by gid %u, should be %u", sudoers, + (unsigned int) statbuf.st_gid, (unsigned int) sudoers_gid); + else if ((fp = fopen(sudoers, "r")) == NULL) + log_error(USE_ERRNO|NO_EXIT, "can't open %s", sudoers); + else { + /* + * Make sure we can actually read sudoers so we can present the + * user with a reasonable error message (unlike the lexer). + */ + if (statbuf.st_size != 0 && fgetc(fp) == EOF) { + log_error(USE_ERRNO|NO_EXIT, "can't read %s", sudoers); + fclose(fp); + fp = NULL; + } + } + + if (fp != NULL) { + rewind(fp); + (void) fcntl(fileno(fp), F_SETFD, 1); + } + + restore_perms(); /* change back to root */ + return fp; +} + +#ifdef HAVE_LOGIN_CAP_H +static void +set_loginclass(struct passwd *pw) +{ + int errflags; + + /* + * Don't make it a fatal error if the user didn't specify the login + * class themselves. We do this because if login.conf gets + * corrupted we want the admin to be able to use sudo to fix it. + */ + if (login_class) + errflags = NO_MAIL|MSG_ONLY; + else + errflags = NO_MAIL|MSG_ONLY|NO_EXIT; + + if (login_class && strcmp(login_class, "-") != 0) { + 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; + if (!login_class || !*login_class) + login_class = + (pw->pw_uid == 0) ? LOGIN_DEFROOTCLASS : LOGIN_DEFCLASS; + } + + lc = login_getclass(login_class); + if (!lc || !lc->lc_class || strcmp(lc->lc_class, login_class) != 0) { + log_error(errflags, "unknown login class: %s", login_class); + if (!lc) + lc = login_getclass(NULL); /* needed for login_getstyle() later */ + } +} +#else +static void +set_loginclass(struct passwd *pw) +{ +} +#endif /* HAVE_LOGIN_CAP_H */ + +/* + * Look up the fully qualified domain name and set user_host and user_shost. + */ +void +set_fqdn(void) +{ +#ifdef HAVE_GETADDRINFO + struct addrinfo *res0, hint; +#else + struct hostent *hp; +#endif + char *p; + +#ifdef HAVE_GETADDRINFO + zero_bytes(&hint, sizeof(hint)); + hint.ai_family = PF_UNSPEC; + hint.ai_flags = AI_CANONNAME; + if (getaddrinfo(user_host, NULL, &hint, &res0) != 0) { +#else + if (!(hp = gethostbyname(user_host))) { +#endif + log_error(MSG_ONLY|NO_EXIT, + "unable to resolve host %s", user_host); + } else { + if (user_shost != user_host) + efree(user_shost); + efree(user_host); +#ifdef HAVE_GETADDRINFO + user_host = estrdup(res0->ai_canonname); + freeaddrinfo(res0); +#else + user_host = estrdup(hp->h_name); +#endif + } + if ((p = strchr(user_host, '.')) != NULL) + user_shost = estrndup(user_host, (size_t)(p - user_host)); + else + user_shost = user_host; +} + +/* + * Get passwd entry for the user we are going to run commands as + * and store it in runas_pw. By default, commands run as "root". + */ +static void +set_runaspw(char *user) +{ + if (runas_pw != NULL) + pw_delref(runas_pw); + if (*user == '#') { + if ((runas_pw = sudo_getpwuid(atoi(user + 1))) == NULL) + runas_pw = sudo_fakepwnam(user, runas_gr ? runas_gr->gr_gid : 0); + } else { + if ((runas_pw = sudo_getpwnam(user)) == NULL) { + audit_failure(NewArgv, "unknown user: %s", user); + log_error(NO_MAIL|MSG_ONLY, "unknown user: %s", user); + } + } +} + +/* + * Get group entry for the group we are going to run commands as + * and store it in runas_gr. + */ +static void +set_runasgr(char *group) +{ + if (runas_gr != NULL) + gr_delref(runas_gr); + 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); + } +} + +/* + * Cleanup hook for error()/errorx() + */ +void +plugin_cleanup(int gotsignal) +{ + struct sudo_nss *nss; + + if (!gotsignal) { + if (snl != NULL) { + tq_foreach_fwd(snl, nss) + nss->close(nss); + } + if (def_group_plugin) + group_plugin_unload(); + sudo_endpwent(); + sudo_endgrent(); + } +} + +static int +sudoers_policy_version(int verbose) +{ + if (sigsetjmp(error_jmp, 1)) { + /* error recovery via error(), errorx() or log_error() */ + return -1; + } + + sudo_printf(SUDO_CONV_INFO_MSG, "Sudoers policy plugin version %s\n", + PACKAGE_VERSION); + sudo_printf(SUDO_CONV_INFO_MSG, "Sudoers file grammar version %d\n", + SUDOERS_GRAMMAR_VERSION); + + if (verbose) { + sudo_printf(SUDO_CONV_INFO_MSG, "\nSudoers path: %s\n", sudoers_file); +#ifdef HAVE_LDAP +# ifdef _PATH_NSSWITCH_CONF + sudo_printf(SUDO_CONV_INFO_MSG, "nsswitch path: %s\n", _PATH_NSSWITCH_CONF); +# endif + sudo_printf(SUDO_CONV_INFO_MSG, "ldap.conf path: %s\n", _PATH_LDAP_CONF); + sudo_printf(SUDO_CONV_INFO_MSG, "ldap.secret path: %s\n", _PATH_LDAP_SECRET); +#endif + dump_auth_methods(); + dump_defaults(); + sudo_printf(SUDO_CONV_INFO_MSG, "\n"); + dump_interfaces(interfaces_string); + sudo_printf(SUDO_CONV_INFO_MSG, "\n"); + } + return TRUE; +} + +static int +deserialize_info(char * const settings[], char * const user_info[]) +{ + char * const *cur; + const char *p; + int flags = 0; + +#define MATCHES(s, v) (strncmp(s, v, sizeof(v) - 1) == 0) + + /* Parse command line settings. */ + user_closefrom = -1; + for (cur = settings; *cur != NULL; cur++) { + if (MATCHES(*cur, "closefrom=")) { + user_closefrom = atoi(*cur + sizeof("closefrom=") - 1); + continue; + } + if (MATCHES(*cur, "debug_level=")) { + debug_level = atoi(*cur + sizeof("debug_level=") - 1); + continue; + } + if (MATCHES(*cur, "runas_user=")) { + runas_user = *cur + sizeof("runas_user=") - 1; + continue; + } + if (MATCHES(*cur, "runas_group=")) { + runas_group = *cur + sizeof("runas_group=") - 1; + continue; + } + if (MATCHES(*cur, "prompt=")) { + user_prompt = *cur + sizeof("prompt=") - 1; + def_passprompt_override = TRUE; + continue; + } + if (MATCHES(*cur, "set_home=")) { + if (atobool(*cur + sizeof("set_home=") - 1) == TRUE) + SET(flags, MODE_RESET_HOME); + continue; + } + if (MATCHES(*cur, "preserve_environment=")) { + if (atobool(*cur + sizeof("preserve_environment=") - 1) == TRUE) + SET(flags, MODE_PRESERVE_ENV); + continue; + } + if (MATCHES(*cur, "run_shell=")) { + if (atobool(*cur + sizeof("run_shell=") - 1) == TRUE) + SET(flags, MODE_SHELL); + continue; + } + if (MATCHES(*cur, "login_shell=")) { + if (atobool(*cur + sizeof("login_shell=") - 1) == TRUE) { + SET(flags, MODE_LOGIN_SHELL); + def_env_reset = TRUE; + } + continue; + } + if (MATCHES(*cur, "implied_shell=")) { + if (atobool(*cur + sizeof("implied_shell=") - 1) == TRUE) + SET(flags, MODE_IMPLIED_SHELL); + continue; + } + if (MATCHES(*cur, "preserve_groups=")) { + if (atobool(*cur + sizeof("preserve_groups=") - 1) == TRUE) + SET(flags, MODE_PRESERVE_GROUPS); + continue; + } + if (MATCHES(*cur, "ignore_ticket=")) { + if (atobool(*cur + sizeof("ignore_ticket=") - 1) == TRUE) + SET(flags, MODE_IGNORE_TICKET); + continue; + } + if (MATCHES(*cur, "noninteractive=")) { + if (atobool(*cur + sizeof("noninteractive=") - 1) == TRUE) + SET(flags, MODE_NONINTERACTIVE); + continue; + } + if (MATCHES(*cur, "sudoedit=")) { + if (atobool(*cur + sizeof("sudoedit=") - 1) == TRUE) + SET(flags, MODE_EDIT); + continue; + } + if (MATCHES(*cur, "login_class=")) { + login_class = *cur + sizeof("login_class=") - 1; + def_use_loginclass = TRUE; + continue; + } +#ifdef HAVE_SELINUX + if (MATCHES(*cur, "selinux_role=")) { + user_role = *cur + sizeof("selinux_role=") - 1; + continue; + } + if (MATCHES(*cur, "selinux_type=")) { + user_type = *cur + sizeof("selinux_type=") - 1; + continue; + } +#endif /* HAVE_SELINUX */ +#ifdef HAVE_BSD_AUTH_H + if (MATCHES(*cur, "bsdauth_type=")) { + login_style = *cur + sizeof("bsdauth_type=") - 1; + continue; + } +#endif /* HAVE_BSD_AUTH_H */ +#if !defined(HAVE_GETPROGNAME) && !defined(HAVE___PROGNAME) + if (MATCHES(*cur, "progname=")) { + setprogname(*cur + sizeof("progname=") - 1); + continue; + } +#endif + if (MATCHES(*cur, "network_addrs=")) { + interfaces_string = *cur + sizeof("network_addrs=") - 1; + set_interfaces(interfaces_string); + continue; + } + if (MATCHES(*cur, "sudoers_file=")) { + sudoers_file = *cur + sizeof("sudoers_file=") - 1; + continue; + } + if (MATCHES(*cur, "sudoers_uid=")) { + sudoers_uid = (uid_t) atoi(*cur + sizeof("sudoers_uid=") - 1); + continue; + } + if (MATCHES(*cur, "sudoers_gid=")) { + sudoers_gid = (gid_t) atoi(*cur + sizeof("sudoers_gid=") - 1); + continue; + } + if (MATCHES(*cur, "sudoers_mode=")) { + sudoers_mode = (mode_t) strtol(*cur + sizeof("sudoers_mode=") - 1, + NULL, 8); + continue; + } + } + + for (cur = user_info; *cur != NULL; cur++) { + if (MATCHES(*cur, "user=")) { + user_name = estrdup(*cur + sizeof("user=") - 1); + continue; + } + if (MATCHES(*cur, "uid=")) { + user_uid = (uid_t) atoi(*cur + sizeof("uid=") - 1); + continue; + } + if (MATCHES(*cur, "gid=")) { + user_gid = (gid_t) atoi(*cur + sizeof("gid=") - 1); + continue; + } + if (MATCHES(*cur, "groups=")) { + /* Count number of groups */ + const char *val = *cur + sizeof("groups=") - 1; + const char *cp; + if (val[0] != '\0') { + user_ngroups = 1; + for (cp = val; *cp != '\0'; cp++) { + if (*cp == ',') + user_ngroups++; + } + + user_groups = emalloc2(user_ngroups, sizeof(GETGROUPS_T)); + user_ngroups = 0; + cp = val; + for (;;) { + /* XXX - strtol would be better here */ + user_groups[user_ngroups++] = atoi(cp); + cp = strchr(cp, ','); + if (cp == NULL) + break; + cp++; /* skip over comma */ + } + } + continue; + } + if (MATCHES(*cur, "cwd=")) { + user_cwd = estrdup(*cur + sizeof("cwd=") - 1); + continue; + } + if (MATCHES(*cur, "tty=")) { + user_tty = user_ttypath = estrdup(*cur + sizeof("tty=") - 1); + if (strncmp(user_tty, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) + user_tty += sizeof(_PATH_DEV) - 1; + continue; + } + if (MATCHES(*cur, "host=")) { + user_host = user_shost = estrdup(*cur + sizeof("host=") - 1); + if ((p = strchr(user_host, '.'))) + user_shost = estrndup(user_host, (size_t)(p - user_host)); + continue; + } + if (MATCHES(*cur, "lines=")) { + sudo_user.lines = atoi(*cur + sizeof("lines=") - 1); + continue; + } + if (MATCHES(*cur, "cols=")) { + sudo_user.cols = atoi(*cur + sizeof("cols=") - 1); + continue; + } + } + if (user_cwd == NULL) + user_cwd = "unknown"; + if (user_tty == NULL) + user_tty = "unknown"; /* user_ttypath remains NULL */ + +#undef MATCHES + return flags; +} + +static char * +resolve_editor(char *editor, int nfiles, char **files, char ***argv_out) +{ + char *cp, **nargv, *editor_path = NULL; + int ac, i, nargc, wasblank; + + editor = estrdup(editor); /* becomes part of argv_out */ + + /* + * Split editor into an argument vector; editor is reused (do not free). + * The EDITOR and VISUAL environment variables may contain command + * line args so look for those and alloc space for them too. + */ + nargc = 1; + for (wasblank = FALSE, cp = editor; *cp != '\0'; cp++) { + if (isblank((unsigned char) *cp)) + wasblank = TRUE; + else if (wasblank) { + wasblank = FALSE; + nargc++; + } + } + /* If we can't find the editor in the user's PATH, give up. */ + cp = strtok(editor, " \t"); + if (cp == NULL || + find_path(cp, &editor_path, NULL, getenv("PATH"), 0) != FOUND) { + efree(editor); + return NULL; + } + nargv = (char **) emalloc2(nargc + 1 + nfiles + 1, sizeof(char *)); + for (ac = 0; cp != NULL && ac < nargc; ac++) { + nargv[ac] = cp; + cp = strtok(NULL, " \t"); + } + nargv[ac++] = "--"; + for (i = 0; i < nfiles; ) + nargv[ac++] = files[i++]; + nargv[ac] = NULL; + + *argv_out = nargv; + return editor_path; +} + +/* + * Determine which editor to use. We don't need to worry about restricting + * this to a "safe" editor since it runs with the uid of the invoking user, + * not the runas (privileged) user. + */ +static char * +find_editor(int nfiles, char **files, char ***argv_out) +{ + char *cp, *editor, *editor_path = NULL, **ev, *ev0[4]; + + /* + * If any of SUDO_EDITOR, VISUAL or EDITOR are set, choose the first one. + */ + ev0[0] = "SUDO_EDITOR"; + ev0[1] = "VISUAL"; + ev0[2] = "EDITOR"; + ev0[3] = NULL; + for (ev = ev0; *ev != NULL; ev++) { + if ((editor = getenv(*ev)) != NULL && *editor != '\0') { + editor_path = resolve_editor(editor, nfiles, files, argv_out); + if (editor_path != NULL) + break; + } + } + if (editor_path == NULL) { + /* def_editor could be a path, split it up */ + editor = estrdup(def_editor); + cp = strtok(editor, ":"); + while (cp != NULL && editor_path == NULL) { + editor_path = resolve_editor(cp, nfiles, files, argv_out); + cp = strtok(NULL, ":"); + } + if (editor_path) + efree(editor); + } + if (!editor_path) { + audit_failure(NewArgv, "%s: command not found", editor); + warningx("%s: command not found", editor); + } + return editor_path; +} + +#ifdef USE_ADMIN_FLAG +static void +create_admin_success_flag(void) +{ + struct stat statbuf; + char flagfile[PATH_MAX]; + int fd, n; + + /* Check whether the user is in the admin group. */ + if (!user_in_group(sudo_user.pw, "admin")) + return; + + /* Build path to flag file. */ + n = snprintf(flagfile, sizeof(flagfile), "%s/.sudo_as_admin_successful", + user_dir); + if (n <= 0 || n >= sizeof(flagfile)) + return; + + /* Create admin flag file if it doesn't already exist. */ + set_perms(PERM_USER); + if (stat(flagfile, &statbuf) != 0) { + fd = open(flagfile, O_CREAT|O_WRONLY|O_EXCL, 0644); + close(fd); + } + restore_perms(); +} +#else /* !USE_ADMIN_FLAG */ +static void +create_admin_success_flag(void) +{ + /* STUB */ +} +#endif /* USE_ADMIN_FLAG */ + +struct policy_plugin sudoers_policy = { + SUDO_POLICY_PLUGIN, + SUDO_API_VERSION, + sudoers_policy_open, + sudoers_policy_close, + sudoers_policy_version, + sudoers_policy_check, + sudoers_policy_list, + sudoers_policy_validate, + sudoers_policy_invalidate, + sudoers_policy_init_session +}; diff --git a/plugins/sudoers/sudoers.h b/plugins/sudoers/sudoers.h new file mode 100644 index 0000000..7e5d56b --- /dev/null +++ b/plugins/sudoers/sudoers.h @@ -0,0 +1,338 @@ +/* + * Copyright (c) 1993-1996, 1998-2005, 2007-2011 + * Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ + +#ifndef _SUDO_SUDOERS_H +#define _SUDO_SUDOERS_H + +#include + +#include +#include "missing.h" +#include "error.h" +#include "alloc.h" +#include "list.h" +#include "fileops.h" +#include "defaults.h" +#include "logging.h" +#include "sudo_nss.h" +#include "sudo_plugin.h" + +#ifdef HAVE_MBR_CHECK_MEMBERSHIP +# include +#endif + +/* + * Info pertaining to the invoking user. + */ +struct sudo_user { + struct passwd *pw; + struct passwd *_runas_pw; + struct group *_runas_gr; + struct stat *cmnd_stat; + char *name; + char *path; + char *tty; + char *ttypath; + char *host; + char *shost; + char *prompt; + char *cmnd; + char *cmnd_args; + char *cmnd_base; + char *cmnd_safe; + char *class_name; + char *krb5_ccname; + int closefrom; + int ngroups; + uid_t uid; + uid_t gid; + int lines; + int cols; + GETGROUPS_T *groups; + char * const * env_vars; +#ifdef HAVE_SELINUX + char *role; + char *type; +#endif + char *cwd; + char *iolog_file; +#ifdef HAVE_MBR_CHECK_MEMBERSHIP + uuid_t uuid; +#endif +}; + +/* + * Return values for sudoers_lookup(), also used as arguments for log_auth() + * Note: cannot use '0' as a value here. + */ +/* XXX - VALIDATE_SUCCESS and VALIDATE_FAILURE instead? */ +#define VALIDATE_ERROR 0x001 +#define VALIDATE_OK 0x002 +#define VALIDATE_NOT_OK 0x004 +#define FLAG_CHECK_USER 0x010 +#define FLAG_NO_USER 0x020 +#define FLAG_NO_HOST 0x040 +#define FLAG_NO_CHECK 0x080 + +/* + * Pseudo-boolean values + */ +#undef TRUE +#define TRUE 1 +#undef FALSE +#define FALSE 0 + +/* + * find_path()/load_cmnd() return values + */ +#define FOUND 0 +#define NOT_FOUND 1 +#define NOT_FOUND_DOT 2 + +/* + * Various modes sudo can be in (based on arguments) in hex + */ +#define MODE_RUN 0x00000001 +#define MODE_EDIT 0x00000002 +#define MODE_VALIDATE 0x00000004 +#define MODE_INVALIDATE 0x00000008 +#define MODE_KILL 0x00000010 +#define MODE_VERSION 0x00000020 +#define MODE_HELP 0x00000040 +#define MODE_LIST 0x00000080 +#define MODE_CHECK 0x00000100 +#define MODE_LISTDEFS 0x00000200 +#define MODE_MASK 0x0000ffff + +/* Mode flags */ +#define MODE_BACKGROUND 0x00010000 /* XXX - unused */ +#define MODE_SHELL 0x00020000 +#define MODE_LOGIN_SHELL 0x00040000 +#define MODE_IMPLIED_SHELL 0x00080000 +#define MODE_RESET_HOME 0x00100000 +#define MODE_PRESERVE_GROUPS 0x00200000 +#define MODE_PRESERVE_ENV 0x00400000 +#define MODE_NONINTERACTIVE 0x00800000 +#define MODE_IGNORE_TICKET 0x01000000 + +/* + * Used with set_perms() + */ +#define PERM_INITIAL 0x00 +#define PERM_ROOT 0x01 +#define PERM_USER 0x02 +#define PERM_FULL_USER 0x03 +#define PERM_SUDOERS 0x04 +#define PERM_RUNAS 0x05 +#define PERM_TIMESTAMP 0x06 +#define PERM_NOEXIT 0x10 /* flag */ +#define PERM_MASK 0xf0 + +/* + * Shortcuts for sudo_user contents. + */ +#define user_name (sudo_user.name) +#define user_uid (sudo_user.uid) +#define user_gid (sudo_user.gid) +#define user_passwd (sudo_user.pw->pw_passwd) +#define user_uuid (sudo_user.uuid) +#define user_dir (sudo_user.pw->pw_dir) +#define user_ngroups (sudo_user.ngroups) +#define user_groups (sudo_user.groups) +#define user_tty (sudo_user.tty) +#define user_ttypath (sudo_user.ttypath) +#define user_cwd (sudo_user.cwd) +#define user_cmnd (sudo_user.cmnd) +#define user_args (sudo_user.cmnd_args) +#define user_base (sudo_user.cmnd_base) +#define user_stat (sudo_user.cmnd_stat) +#define user_path (sudo_user.path) +#define user_prompt (sudo_user.prompt) +#define user_host (sudo_user.host) +#define user_shost (sudo_user.shost) +#define user_ccname (sudo_user.krb5_ccname) +#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) +#define user_role (sudo_user.role) +#define user_type (sudo_user.type) +#define user_closefrom (sudo_user.closefrom) + +#ifdef __TANDEM +# define ROOT_UID 65535 +#else +# define ROOT_UID 0 +#endif + +/* + * We used to use the system definition of PASS_MAX or _PASSWD_LEN, + * but that caused problems with various alternate authentication + * methods. So, we just define our own and assume that it is >= the + * system max. + */ +#define SUDO_PASS_MAX 256 + +struct lbuf; +struct passwd; +struct stat; +struct timeval; + +/* + * Function prototypes + */ +#define YY_DECL int yylex(void) + +/* goodpath.c */ +char *sudo_goodpath(const char *, struct stat *); + +/* findpath.c */ +int find_path(char *, char **, struct stat *, char *, int); + +/* check.c */ +int check_user(int, int); +void remove_timestamp(int); +int user_is_exempt(void); + +/* sudo_auth.c */ +int verify_user(struct passwd *, char *); +int auth_begin_session(struct passwd *); +int auth_end_session(); + +/* parse.c */ +int sudo_file_open(struct sudo_nss *); +int sudo_file_close(struct sudo_nss *); +int sudo_file_setdefs(struct sudo_nss *); +int sudo_file_lookup(struct sudo_nss *, int, int); +int sudo_file_parse(struct sudo_nss *); +int sudo_file_display_cmnd(struct sudo_nss *, struct passwd *); +int sudo_file_display_defaults(struct sudo_nss *, struct passwd *, struct lbuf *); +int sudo_file_display_bound_defaults(struct sudo_nss *, struct passwd *, struct lbuf *); +int sudo_file_display_privs(struct sudo_nss *, struct passwd *, struct lbuf *); + +/* set_perms.c */ +void rewind_perms(void); +int set_perms(int); +void restore_perms(void); +int pam_prep_user(struct passwd *); + +/* gram.y */ +int yyparse(void); + +/* toke.l */ +YY_DECL; + +/* defaults.c */ +void dump_defaults(void); +void dump_auth_methods(void); + +/* getspwuid.c */ +char *sudo_getepw(const struct passwd *); + +/* zero_bytes.c */ +void zero_bytes(volatile void *, size_t); + +/* sudo_nss.c */ +void display_privs(struct sudo_nss_list *, struct passwd *); +int display_cmnd(struct sudo_nss_list *, struct passwd *); + +/* pwutil.c */ +void sudo_setgrent(void); +void sudo_endgrent(void); +void sudo_setpwent(void); +void sudo_endpwent(void); +void sudo_setspent(void); +void sudo_endspent(void); +struct passwd *sudo_getpwnam(const char *); +struct passwd *sudo_fakepwnam(const char *, gid_t); +struct passwd *sudo_getpwuid(uid_t); +struct group *sudo_getgrnam(const char *); +struct group *sudo_fakegrnam(const char *); +struct group *sudo_getgrgid(gid_t); +void gr_addref(struct group *); +void gr_delref(struct group *); +void pw_addref(struct passwd *); +void pw_delref(struct passwd *); +int user_in_group(struct passwd *, const char *); + +/* timestr.c */ +char *get_timestr(time_t, int); + +/* atobool.c */ +int atobool(const char *str); + +/* boottime.c */ +int get_boottime(struct timeval *); + +/* iolog.c */ +void io_nextid(char *iolog_dir, char sessid[7]); + +/* iolog_path.c */ +char *expand_iolog_path(const char *prefix, const char *dir, const char *file, + char **slashp); + +/* env.c */ +char **env_get(void); +void env_init(char * const envp[]); +void init_envtables(void); +void insert_env_vars(char * const envp[]); +void read_env_file(const char *, int); +void rebuild_env(void); +void validate_env_vars(char * const envp[]); + +/* fmt_string.c */ +char *fmt_string(const char *, const char *); + +/* sudoers.c */ +void plugin_cleanup(int); +void set_fqdn(void); +FILE *open_sudoers(const char *, int, int *); + +/* aix.c */ +void aix_restoreauthdb(void); +void aix_setauthdb(char *user); + +/* group_plugin.c */ +int group_plugin_load(char *plugin_info); +void group_plugin_unload(void); +int group_plugin_query(const char *user, const char *group, + const struct passwd *pwd); + +#ifndef _SUDO_MAIN +extern struct sudo_user sudo_user; +extern struct passwd *list_pw; +extern const char *sudoers_file; +extern mode_t sudoers_mode; +extern uid_t sudoers_uid; +extern gid_t sudoers_gid; +extern int long_list; +extern int sudo_mode; +extern uid_t timestamp_uid; +extern sudo_conv_t sudo_conv; +extern sudo_printf_t sudo_printf; +#endif + +/* Some systems don't declare errno in errno.h */ +#ifndef errno +extern int errno; +#endif + +#endif /* _SUDO_SUDOERS_H */ diff --git a/sudoers.in b/plugins/sudoers/sudoers.in similarity index 100% rename from sudoers.in rename to plugins/sudoers/sudoers.in diff --git a/plugins/sudoers/sudoers.sym b/plugins/sudoers/sudoers.sym new file mode 100644 index 0000000..7f74694 --- /dev/null +++ b/plugins/sudoers/sudoers.sym @@ -0,0 +1,2 @@ +sudoers_policy +sudoers_io diff --git a/sudoers2ldif b/plugins/sudoers/sudoers2ldif similarity index 100% rename from sudoers2ldif rename to plugins/sudoers/sudoers2ldif diff --git a/plugins/sudoers/sudoers_version.h b/plugins/sudoers/sudoers_version.h new file mode 100644 index 0000000..3593d29 --- /dev/null +++ b/plugins/sudoers/sudoers_version.h @@ -0,0 +1,53 @@ +/* + * Major sudoers grammar changes are documented here. + * Note that minor changes such as added Defaults options are not listed here. + * This file placed in the public domain by Todd C. Miller on Apr 5, 2011. + * + * 1 sudo 1.1 + * 2 sudo 1.3, adds support specifying a directory instead of a command. + * 3 sudo 1.3.2, new parser, Aliases have to be upper case + * 4 sudo 1.3.2, adds User_Alias + * 5 sudo 1.3.4, netgroup support + * 6 sudo 1.3.5, support for escaping special chars + * 7 sudo 1.3.7, unix group support + * 8 sudo 1.4.1, wildcard support + * 9 sudo 1.4.2, double quote support in sudoers command line args + * 10 sudo 1.4.3, added NOPASSWD tag + * 11 sudo 1.4.3, added Runas_Spec + * 12 sudo 1.4.3, wildcards may be used in the pathname + * 13 sudo 1.4.3, command args of "" means no args allowed + * 14 sudo 1.4.4, '(' in command args no longer are a syntax error. + * 15 sudo 1.4.4, '!command' works in the presence of runas user or NOPASSWD. + * 16 sudo 1.4.4, all-caps user and host names are now handled properly. + * 17 sudo 1.5.0, usernames may now begin with a digit + * 18 sudo 1.5.3, adds Runas_Alias + * 19 sudo 1.5.7, %group may be used in a Runas_List + * 20 sudo 1.6.0, The runas user and NOPASSWD tags are now persistent across entries in a command list. A PASSWD tag has been added to reverse NOPASSWD + * 21 sudo 1.6.0, The '!' operator can be used in a Runas_Spec or an *_Alias + * 22 sudo 1.6.0, a list of hosts may be used in a Host_Spec + * 23 sudo 1.6.0, a list of users may be used in a User_Spec + * 24 sudo 1.6.0, It is now possible to escape "special" characters in usernames, hostnames, etc with a backslash. + * 25 sudo 1.6.0, Added Defaults run-time settings in sudoers. + * 26 sudo 1.6.0, relaxed the regexp for matching user, host, group names. + * 27 sudo 1.6.1, #uid is now allowed in a Runas_Alias. + * 28 sudo 1.6.2, Wildcards are now allowed in hostnames. + * 29 sudo 1.6.3p7, escaped special characters may be included in pathnames. + * 30 sudo 1.6.8, added NOEXEC and EXEC tags. + * 31 sudo 1.6.9, added SETENV and NOSETENV tags. + * 32 sudo 1.6.9p4, support for IPv6 address matching. + * 33 sudo 1.7.0, #include support. + * 34 sudo 1.7.0, Runas_Group support. + * 35 sudo 1.7.0, uid may now be used anywhere a username is valid. + * 36 sudo 1.7.2, #includedir support. + * 37 sudo 1.7.4, per-command Defaults support. + * 38 sudo 1.7.4, added LOG_INPUT/LOG_OUTPUT and NOLOG_INPUT/NOLOG_OUTPUT tags + * 39 sudo 1.7.6/1.8.1, White space is now permitted within a User_List in a per-user Defaults definition. + * 40 sudo 1.7.6/1.8.1, A group ID is now allowed in a User_List or Runas_List. +*/ + +#ifndef _SUDOERS_VERSION_H +#define _SUDOERS_VERSION_H + +#define SUDOERS_GRAMMAR_VERSION 40 + +#endif /* _SUDOERS_VERSION_H */ diff --git a/sudoreplay.c b/plugins/sudoers/sudoreplay.c similarity index 77% rename from sudoreplay.c rename to plugins/sudoers/sudoreplay.c index 9fdb5bb..e40fcef 100644 --- a/sudoreplay.c +++ b/plugins/sudoers/sudoreplay.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2010 Todd C. Miller + * Copyright (c) 2009-2011 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -53,7 +53,7 @@ # include #endif #ifndef HAVE_TIMESPEC -# include "emul/timespec.h" +# include "compat/timespec.h" #endif #include #include @@ -113,9 +113,6 @@ unsigned int replay_filter = (1 << IOFD_STDOUT) | (1 << IOFD_STDERR) | extern char *optarg; extern int optind; -int Argc; -char **Argv; - union io_fd { FILE *f; #ifdef HAVE_ZLIB_H @@ -188,21 +185,21 @@ static const char *io_fnames[IOFD_MAX] = { "/timing" }; -extern time_t get_date __P((char *)); -extern char *get_timestr __P((time_t, int)); -extern int term_raw __P((int, int)); -extern int term_restore __P((int, int)); -extern void zero_bytes __P((volatile void *, size_t)); -RETSIGTYPE cleanup __P((int)); - -static int list_sessions __P((int, char **, const char *, const char *, const char *)); -static int parse_expr __P((struct search_node **, char **)); -static void check_input __P((int, double *)); -static void delay __P((double)); -static void help __P((void)) __attribute__((__noreturn__)); -static void usage __P((int)); -static void *open_io_fd __P((char *pathbuf, int len, const char *suffix)); -static int parse_timing __P((const char *buf, const char *decimal, int *idx, double *seconds, size_t *nbytes)); +extern time_t get_date(char *); +extern char *get_timestr(time_t, int); +extern int term_raw(int, int); +extern int term_restore(int, int); +extern void zero_bytes(volatile void *, size_t); +void cleanup(int); + +static int list_sessions(int, char **, const char *, const char *, const char *); +static int parse_expr(struct search_node **, char **); +static void check_input(int, double *); +static void delay(double); +static void help(void) __attribute__((__noreturn__)); +static void usage(int); +static void *open_io_fd(char *pathbuf, int len, const char *suffix); +static int parse_timing(const char *buf, const char *decimal, int *idx, double *seconds, size_t *nbytes); #ifdef HAVE_REGCOMP # define REGEX_T regex_t @@ -215,10 +212,17 @@ static int parse_timing __P((const char *buf, const char *decimal, int *idx, dou isalnum((unsigned char)(s)[3]) && isalnum((unsigned char)(s)[4]) && \ isalnum((unsigned char)(s)[5]) && (s)[6] == '\0') +#define IS_IDLOG(s) ( \ + isalnum((unsigned char)(s)[0]) && isalnum((unsigned char)(s)[1]) && \ + (s)[2] == '/' && \ + isalnum((unsigned char)(s)[3]) && isalnum((unsigned char)(s)[4]) && \ + (s)[5] == '/' && \ + isalnum((unsigned char)(s)[6]) && isalnum((unsigned char)(s)[7]) && \ + (s)[8] == '/' && (s)[9] == 'l' && (s)[10] == 'o' && (s)[11] == 'g' && \ + (s)[9] == '\0') + int -main(argc, argv) - int argc; - char *argv[]; +main(int argc, char *argv[]) { int ch, idx, plen, nready, interactive = 0, listonly = 0; const char *id, *user = NULL, *pattern = NULL, *tty = NULL, *decimal = "."; @@ -230,8 +234,9 @@ main(argc, argv) size_t len, nbytes, nread, off; ssize_t nwritten; - Argc = argc; - Argv = argv; +#if !defined(HAVE_GETPROGNAME) && !defined(HAVE___PROGNAME) + setprogname(argc > 0 ? argv[0] : "sudoreplay"); +#endif #ifdef HAVE_SETLOCALE setlocale(LC_ALL, ""); @@ -293,16 +298,21 @@ main(argc, argv) if (argc != 1) usage(1); - /* 6 digit ID in base 36, e.g. 01G712AB */ + /* 6 digit ID in base 36, e.g. 01G712AB or free-form name */ id = argv[0]; - if (!VALID_ID(id)) - errorx(1, "invalid ID %s", id); - - plen = snprintf(path, sizeof(path), "%s/%.2s/%.2s/%.2s/timing", - session_dir, id, &id[2], &id[4]); - if (plen <= 0 || plen >= sizeof(path)) - errorx(1, "%s/%.2s/%.2s/%.2s/%.2s/timing: %s", session_dir, - id, &id[2], &id[4], strerror(ENAMETOOLONG)); + if (VALID_ID(id)) { + plen = snprintf(path, sizeof(path), "%s/%.2s/%.2s/%.2s/timing", + session_dir, id, &id[2], &id[4]); + if (plen <= 0 || plen >= sizeof(path)) + errorx(1, "%s/%.2s/%.2s/%.2s/%.2s/timing: %s", session_dir, + id, &id[2], &id[4], strerror(ENAMETOOLONG)); + } else { + plen = snprintf(path, sizeof(path), "%s/%s/timing", + session_dir, id); + if (plen <= 0 || plen >= sizeof(path)) + errorx(1, "%s/%s/timing: %s", session_dir, + id, strerror(ENAMETOOLONG)); + } plen -= 7; /* Open files for replay, applying replay filter for the -f flag. */ @@ -421,8 +431,7 @@ main(argc, argv) } static void -delay(secs) - double secs; +delay(double secs) { struct timespec ts, rts; int rval; @@ -445,10 +454,7 @@ delay(secs) } static void * -open_io_fd(path, len, suffix) - char *path; - int len; - const char *suffix; +open_io_fd(char *path, int len, const char *suffix) { path[len] = '\0'; strlcat(path, suffix, PATH_MAX); @@ -464,9 +470,7 @@ open_io_fd(path, len, suffix) * Build expression list from search args */ static int -parse_expr(headp, argv) - struct search_node **headp; - char *argv[]; +parse_expr(struct search_node **headp, char *argv[]) { struct search_node *sn, *newsn; char or = 0, not = 0, type, **av; @@ -596,9 +600,7 @@ parse_expr(headp, argv) } static int -match_expr(head, log) - struct search_node *head; - struct log_info *log; +match_expr(struct search_node *head, struct log_info *log) { struct search_node *sn; int matched = 1, rc; @@ -654,132 +656,155 @@ match_expr(head, log) } static int -list_session_dir(pathbuf, re, user, tty) - char *pathbuf; - REGEX_T *re; - const char *user; - const char *tty; +list_session(char *logfile, REGEX_T *re, const char *user, const char *tty) { FILE *fp; - DIR *d; - struct dirent *dp; - char *buf = NULL, *cmd = NULL, *cwd = NULL, idstr[7], *cp; + char *buf = NULL, *cmd = NULL, *cwd = NULL, idbuf[7], *idstr, *cp; struct log_info li; - size_t bufsize = 0, cwdsize = 0, cmdsize = 0, plen; + size_t bufsize = 0, cwdsize = 0, cmdsize = 0; + int rval = -1; - plen = strlen(pathbuf); - d = opendir(pathbuf); - if (d == NULL && errno != ENOTDIR) { - warning("cannot opendir %s", pathbuf); - return -1; + fp = fopen(logfile, "r"); + if (fp == NULL) { + warning("unable to open %s", logfile); + goto done; } - while ((dp = readdir(d)) != NULL) { - if (NAMLEN(dp) != 2 || !isalnum((unsigned char)dp->d_name[0]) || - !isalnum((unsigned char)dp->d_name[1])) - continue; - /* open log file, print id and command */ - pathbuf[plen + 0] = '/'; - pathbuf[plen + 1] = dp->d_name[0]; - pathbuf[plen + 2] = dp->d_name[1]; - pathbuf[plen + 3] = '/'; - pathbuf[plen + 4] = 'l'; - pathbuf[plen + 5] = 'o'; - pathbuf[plen + 6] = 'g'; - pathbuf[plen + 7] = '\0'; - fp = fopen(pathbuf, "r"); - if (fp == NULL) { - warning("unable to open %s", pathbuf); - continue; - } + /* + * ID file has three lines: + * 1) a log info line + * 2) cwd + * 3) command with args + */ + if (getline(&buf, &bufsize, fp) == -1 || + getline(&cwd, &cwdsize, fp) == -1 || + getline(&cmd, &cmdsize, fp) == -1) { + goto done; + } - /* - * ID file has three lines: - * 1) a log info line - * 2) cwd - * 3) command with args - */ - if (getline(&buf, &bufsize, fp) == -1 || - getline(&cwd, &cwdsize, fp) == -1 || - getline(&cmd, &cmdsize, fp) == -1) { - fclose(fp); - continue; - } - fclose(fp); + /* crack the log line: timestamp:user:runas_user:runas_group:tty */ + buf[strcspn(buf, "\n")] = '\0'; + if ((li.tstamp = atoi(buf)) == 0) + goto done; + + if ((cp = strchr(buf, ':')) == NULL) + goto done; + *cp++ = '\0'; + li.user = cp; + + if ((cp = strchr(cp, ':')) == NULL) + goto done; + *cp++ = '\0'; + li.runas_user = cp; + + if ((cp = strchr(cp, ':')) == NULL) + goto done; + *cp++ = '\0'; + li.runas_group = cp; + + if ((cp = strchr(cp, ':')) == NULL) + goto done; + *cp++ = '\0'; + li.tty = cp; + + cwd[strcspn(cwd, "\n")] = '\0'; + li.cwd = cwd; + + cmd[strcspn(cmd, "\n")] = '\0'; + li.cmd = cmd; + + /* Match on search expression if there is one. */ + if (search_expr && !match_expr(search_expr, &li)) + goto done; + + /* Convert from /var/log/sudo-sessions/00/00/01/log to 000001 */ + cp = logfile + strlen(session_dir) + 1; + if (IS_IDLOG(cp)) { + idbuf[0] = cp[7]; + idbuf[1] = cp[6]; + idbuf[2] = cp[4]; + idbuf[3] = cp[3]; + idbuf[4] = cp[1]; + idbuf[5] = cp[0]; + idbuf[6] = '\0'; + idstr = idbuf; + } else { + /* Not an id, just use the iolog_file portion. */ + cp[strlen(cp) - 4] = '\0'; + idstr = cp; + } + printf("%s : %s : TTY=%s ; CWD=%s ; USER=%s ; ", + get_timestr(li.tstamp, 1), li.user, li.tty, li.cwd, li.runas_user); + if (*li.runas_group) + printf("GROUP=%s ; ", li.runas_group); + printf("TSID=%s ; COMMAND=%s\n", idstr, li.cmd); - /* crack the log line: timestamp:user:runas_user:runas_group:tty */ - buf[strcspn(buf, "\n")] = '\0'; - if ((li.tstamp = atoi(buf)) == 0) - continue; + rval = 0; - if ((cp = strchr(buf, ':')) == NULL) - continue; - *cp++ = '\0'; - li.user = cp; +done: + fclose(fp); + return rval; +} - if ((cp = strchr(cp, ':')) == NULL) - continue; - *cp++ = '\0'; - li.runas_user = cp; +static int +find_sessions(const char *dir, REGEX_T *re, const char *user, const char *tty) +{ + DIR *d; + struct dirent *dp; + struct stat sb; + size_t sdlen; + int len; + char pathbuf[PATH_MAX]; - if ((cp = strchr(cp, ':')) == NULL) - continue; - *cp++ = '\0'; - li.runas_group = cp; + d = opendir(dir); + if (d == NULL) + error(1, "unable to open %s", dir); - if ((cp = strchr(cp, ':')) == NULL) + /* XXX - would be faster to chdir and use relative names */ + sdlen = strlcpy(pathbuf, dir, sizeof(pathbuf)); + if (sdlen + 1 >= sizeof(pathbuf)) { + errno = ENAMETOOLONG; + error(1, "%s/", dir); + } + pathbuf[sdlen++] = '/'; + pathbuf[sdlen] = '\0'; + while ((dp = readdir(d)) != NULL) { + /* Skip "." and ".." */ + if (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || + (dp->d_name[1] == '.' && dp->d_name[2] == '\0'))) continue; - *cp++ = '\0'; - li.tty = cp; - cwd[strcspn(cwd, "\n")] = '\0'; - li.cwd = cwd; - - cmd[strcspn(cmd, "\n")] = '\0'; - li.cmd = cmd; - - /* Match on search expression if there is one. */ - if (search_expr && !match_expr(search_expr, &li)) - continue; + len = snprintf(&pathbuf[sdlen], sizeof(pathbuf) - sdlen, + "%s/log", dp->d_name); + if (len <= 0 || len >= sizeof(pathbuf) - sdlen) { + errno = ENAMETOOLONG; + error(1, "%s/%s/log", dir, dp->d_name); + } - /* Convert from /var/log/sudo-sessions/00/00/01 to 000001 */ - idstr[0] = pathbuf[plen - 5]; - idstr[1] = pathbuf[plen - 4]; - idstr[2] = pathbuf[plen - 2]; - idstr[3] = pathbuf[plen - 1]; - idstr[4] = pathbuf[plen + 1]; - idstr[5] = pathbuf[plen + 2]; - idstr[6] = '\0'; - printf("%s : %s : TTY=%s ; CWD=%s ; USER=%s ; ", - get_timestr(li.tstamp, 1), li.user, li.tty, li.cwd, li.runas_user); - if (*li.runas_group) - printf("GROUP=%s ; ", li.runas_group); - printf("TSID=%s ; COMMAND=%s\n", idstr, li.cmd); + /* Check for dir with a log file. */ + if (lstat(pathbuf, &sb) == 0 && S_ISREG(sb.st_mode)) { + list_session(pathbuf, re, user, tty); + } else { + /* Strip off "/log" and recurse if a dir. */ + pathbuf[sdlen + len - 4] = '\0'; + if (lstat(pathbuf, &sb) == 0 && S_ISDIR(sb.st_mode)) + find_sessions(pathbuf, re, user, tty); + } } + closedir(d); + return 0; } static int -list_sessions(argc, argv, pattern, user, tty) - int argc; - char **argv; - const char *pattern; - const char *user; - const char *tty; +list_sessions(int argc, char **argv, const char *pattern, const char *user, + const char *tty) { - DIR *d1, *d2; - struct dirent *dp1, *dp2; REGEX_T rebuf, *re = NULL; - size_t sdlen; - char pathbuf[PATH_MAX]; /* Parse search expression if present */ parse_expr(&search_expr, argv); - d1 = opendir(session_dir); - if (d1 == NULL) - error(1, "unable to open %s", session_dir); - #ifdef HAVE_REGCOMP /* optional regex */ if (pattern) { @@ -791,44 +816,7 @@ list_sessions(argc, argv, pattern, user, tty) re = (char *) pattern; #endif /* HAVE_REGCOMP */ - sdlen = strlcpy(pathbuf, session_dir, sizeof(pathbuf)); - if (sdlen + sizeof("/00/00/00/log") >= sizeof(pathbuf)) { - errno = ENAMETOOLONG; - error(1, "%s/00/00/00/log", session_dir); - } - - /* - * Three levels of directory, e.g. 00/00/00 .. ZZ/ZZ/ZZ - * We do a depth-first traversal. - */ - while ((dp1 = readdir(d1)) != NULL) { - if (NAMLEN(dp1) != 2 || !isalnum((unsigned char)dp1->d_name[0]) || - !isalnum((unsigned char)dp1->d_name[1])) - continue; - - pathbuf[sdlen + 0] = '/'; - pathbuf[sdlen + 1] = dp1->d_name[0]; - pathbuf[sdlen + 2] = dp1->d_name[1]; - pathbuf[sdlen + 3] = '\0'; - d2 = opendir(pathbuf); - if (d2 == NULL) - continue; - - while ((dp2 = readdir(d2)) != NULL) { - if (NAMLEN(dp2) != 2 || !isalnum((unsigned char)dp2->d_name[0]) || - !isalnum((unsigned char)dp2->d_name[1])) - continue; - - pathbuf[sdlen + 3] = '/'; - pathbuf[sdlen + 4] = dp2->d_name[0]; - pathbuf[sdlen + 5] = dp2->d_name[1]; - pathbuf[sdlen + 6] = '\0'; - list_session_dir(pathbuf, re, user, tty); - } - closedir(d2); - } - closedir(d1); - return 0; + return find_sessions(session_dir, re, user, tty); } /* @@ -836,9 +824,7 @@ list_sessions(argc, argv, pattern, user, tty) * pause, slow, fast */ static void -check_input(ttyfd, speed) - int ttyfd; - double *speed; +check_input(int ttyfd, double *speed) { fd_set *fdsr; int nready, paused = 0; @@ -943,11 +929,10 @@ bad: } static void -usage(fatal) - int fatal; +usage(int fatal) { fprintf(fatal ? stderr : stdout, - "usage: %s [-h] [-d directory] [-f filter] [-m max_wait] [-s speed_factor] ID\n", + "usage: %s [-h] [-d directory] [-m max_wait] [-s speed_factor] ID\n", getprogname()); fprintf(fatal ? stderr : stdout, "usage: %s [-h] [-d directory] -l [search expression]\n", @@ -957,7 +942,7 @@ usage(fatal) } static void -help() +help(void) { (void) printf("%s - replay sudo session logs\n\n", getprogname()); usage(0); @@ -975,9 +960,8 @@ help() /* * Cleanup hook for error()/errorx() */ -RETSIGTYPE -cleanup(signo) - int signo; +void +cleanup(int signo) { term_restore(STDIN_FILENO, 0); if (signo) diff --git a/testsudoers.c b/plugins/sudoers/testsudoers.c similarity index 79% rename from testsudoers.c rename to plugins/sudoers/testsudoers.c index 139c7c7..60e338b 100644 --- a/testsudoers.c +++ b/plugins/sudoers/testsudoers.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 1998-2005, 2007-2010 + * Copyright (c) 1996, 1998-2005, 2007-2011 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -54,32 +54,59 @@ # include #endif /* HAVE_NETGROUP_H */ #include -#include -#include +#include #include #include #include #include "tsgetgrpw.h" -#include "sudo.h" +#include "sudoers.h" #include "interfaces.h" #include "parse.h" #include #ifndef HAVE_FNMATCH -# include "emul/fnmatch.h" +# include "compat/fnmatch.h" #endif /* HAVE_FNMATCH */ +/* + * Function Prototypes + */ +int print_alias(void *, void *); +void dump_sudoers(void); +void print_defaults(void); +void print_privilege(struct privilege *); +void print_userspecs(void); +void usage(void) __attribute__((__noreturn__)); +void set_runasgr(char *); +void set_runaspw(char *); +void cleanup(int); +static int testsudoers_printf(int msg_type, const char *fmt, ...); +static int testsudoers_print(const char *msg); + +extern void setgrfile(const char *); +extern void setgrent(void); +extern void endgrent(void); +extern struct group *getgrent(void); +extern struct group *getgrnam(const char *); +extern struct group *getgrgid(gid_t); +extern void setpwfile(const char *); +extern void setpwent(void); +extern void endpwent(void); +extern struct passwd *getpwent(void); +extern struct passwd *getpwnam(const char *); +extern struct passwd *getpwuid(uid_t); + +extern int (*trace_print)(const char *msg); + /* * Globals */ -int Argc, NewArgc; -char **Argv, **NewArgv; -int num_interfaces; struct interface *interfaces; struct sudo_user sudo_user; struct passwd *list_pw; extern int parse_error; +sudo_printf_t sudo_printf = testsudoers_printf; /* For getopt(3) */ extern char *optarg; @@ -92,19 +119,8 @@ extern char *malloc_options; extern int yydebug; #endif -int print_alias __P((void *, void *)); -void dump_sudoers __P((void)); -void print_defaults __P((void)); -void print_privilege __P((struct privilege *)); -void print_userspecs __P((void)); -void usage __P((void)) __attribute__((__noreturn__)); -void set_runasgr __P((char *)); -void set_runaspw __P((char *)); - int -main(argc, argv) - int argc; - char **argv; +main(int argc, char *argv[]) { struct cmndspec *cs; struct privilege *priv; @@ -121,12 +137,13 @@ main(argc, argv) yydebug = 1; #endif - Argv = argv; - Argc = argc; +#if !defined(HAVE_GETPROGNAME) && !defined(HAVE___PROGNAME) + setprogname(argc > 0 ? argv[0] : "testsudoers"); +#endif dflag = 0; grfile = pwfile = runas_group = runas_user = NULL; - while ((ch = getopt(argc, argv, "dg:G:h:p:u:")) != -1) { + while ((ch = getopt(argc, argv, "dg:G:h:p:tu:")) != -1) { switch (ch) { case 'd': dflag = 1; @@ -143,6 +160,9 @@ main(argc, argv) case 'p': pwfile = optarg; break; + case 't': + trace_print = testsudoers_print; + break; case 'u': runas_user = optarg; break; @@ -153,8 +173,6 @@ main(argc, argv) } argc -= optind; argv += optind; - NewArgc = argc; - NewArgv = argv; /* Set group/passwd file and init the cache. */ if (grfile) @@ -167,19 +185,19 @@ main(argc, argv) if (argc < 2) { if (!dflag) usage(); - if ((sudo_user.pw = sudo_getpwnam("root")) == NULL) - errorx(1, "no passwd entry for root!"); + user_name = "root"; user_cmnd = user_base = "true"; } else { - if ((sudo_user.pw = sudo_getpwnam(*argv)) == NULL) - errorx(1, "no passwd entry for %s!", *argv); + user_name = *argv; user_cmnd = *++argv; if ((p = strrchr(user_cmnd, '/')) != NULL) user_base = p + 1; else user_base = user_cmnd; - NewArgc -= 2; + argc -= 2; } + if ((sudo_user.pw = sudo_getpwnam(user_name)) == NULL) + errorx(1, "no passwd entry for %s!", user_name); if (user_host == NULL) { if (gethostname(hbuf, sizeof(hbuf)) != 0) @@ -195,16 +213,16 @@ main(argc, argv) user_shost = user_host; } - /* Fill in user_args from NewArgv. */ - if (NewArgc > 0) { + /* Fill in user_args from argv. */ + if (argc > 0) { char *to, **from; size_t size, n; - for (size = 0, from = NewArgv + 1; *from; from++) + for (size = 0, from = argv + 1; *from; from++) size += strlen(*from) + 1; user_args = (char *) emalloc(size); - for (to = user_args, from = NewArgv + 1; *from; from++) { + for (to = user_args, from = argv + 1; *from; from++) { n = strlcpy(to, *from, size - (to - user_args)); if (n >= size - (to - user_args)) errorx(1, "internal error, init_vars() overflow"); @@ -218,7 +236,8 @@ main(argc, argv) init_defaults(); /* Load ip addr/mask for each interface. */ - load_interfaces(); + if (get_net_ifs(&p) > 0) + set_interfaces(p); /* Allocate space for data structures in the parser. */ init_parser("sudoers", 0); @@ -234,6 +253,9 @@ main(argc, argv) (void) fputs(" (problem with defaults entries)", stdout); puts("."); + if (def_group_plugin && group_plugin_load(def_group_plugin) != TRUE) + def_group_plugin = NULL; + /* * Set runas passwd/group entries based on command line or sudoers. * Note that if runas_group was specified without runas_user we @@ -298,8 +320,7 @@ main(argc, argv) } void -set_runaspw(user) - char *user; +set_runaspw(char *user) { if (*user == '#') { if ((runas_pw = sudo_getpwuid(atoi(user + 1))) == NULL) @@ -311,8 +332,7 @@ set_runaspw(user) } void -set_runasgr(group) - char *group; +set_runasgr(char *group) { if (*group == '#') { if ((runas_gr = sudo_getgrgid(atoi(group + 1))) == NULL) @@ -324,55 +344,48 @@ set_runasgr(group) } void -sudo_setspent() +sudo_setspent(void) { return; } void -sudo_endspent() +sudo_endspent(void) { return; } -char * -sudo_getepw(pw) - const struct passwd *pw; -{ - return pw->pw_passwd; -} - void -set_fqdn() +set_fqdn(void) { return; } FILE * -open_sudoers(path, isdir, keepopen) - const char *path; - int isdir; - int *keepopen; +open_sudoers(const char *path, int isdir, int *keepopen) { return fopen(path, "r"); } void -init_envtables() +init_envtables(void) { return; } int -set_perms(perm) - int perm; +set_perms(int perm) { return 1; } void -cleanup(gotsignal) - int gotsignal; +restore_perms(void) +{ +} + +void +cleanup(int gotsignal) { if (!gotsignal) { sudo_endpwent(); @@ -381,8 +394,7 @@ cleanup(gotsignal) } void -print_member(m) - struct member *m; +print_member(struct member *m) { struct sudo_command *c; @@ -400,7 +412,7 @@ print_member(m) } void -print_defaults() +print_defaults(void) { struct defaults *d; struct member *m; @@ -435,8 +447,7 @@ print_defaults() } int -print_alias(v1, v2) - void *v1, *v2; +print_alias(void *v1, void *v2) { struct alias *a = (struct alias *)v1; struct member *m; @@ -474,8 +485,7 @@ print_alias(v1, v2) } void -print_privilege(priv) - struct privilege *priv; +print_privilege(struct privilege *priv) { struct cmndspec *cs; struct member *m; @@ -535,7 +545,7 @@ print_privilege(priv) } void -print_userspecs() +print_userspecs(void) { struct member *m; struct userspec *us; @@ -552,8 +562,33 @@ print_userspecs() } } +static int +testsudoers_printf(int msg_type, const char *fmt, ...) +{ + va_list ap; + FILE *fp; + + switch (msg_type) { + case SUDO_CONV_INFO_MSG: + fp = stdout; + break; + case SUDO_CONV_ERROR_MSG: + fp = stderr; + break; + default: + errno = EINVAL; + return -1; + } + + va_start(ap, fmt); + vfprintf(fp, fmt, ap); + va_end(ap); + + return 0; +} + void -dump_sudoers() +dump_sudoers(void) { print_defaults(); @@ -564,9 +599,14 @@ dump_sudoers() print_userspecs(); } +static int testsudoers_print(const char *msg) +{ + return fputs(msg, stderr); +} + void -usage() +usage(void) { - (void) fprintf(stderr, "usage: %s [-d] [-G grfile] [-g group] [-h host] [-p pwfile] [-u user] [args]\n", getprogname()); + (void) fprintf(stderr, "usage: %s [-dt] [-G grfile] [-g group] [-h host] [-p pwfile] [-u user] [args]\n", getprogname()); exit(1); } diff --git a/timestr.c b/plugins/sudoers/timestr.c similarity index 90% rename from timestr.c rename to plugins/sudoers/timestr.c index 9369e8c..b2df41b 100644 --- a/timestr.c +++ b/plugins/sudoers/timestr.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2009 Todd C. Miller + * Copyright (c) 1999, 2009-2011 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -30,16 +30,14 @@ #include "missing.h" -char *get_timestr __P((time_t, int)); +char *get_timestr(time_t, int); /* * Return an ascii string with the current date + time * Uses strftime() if available, else falls back to ctime(). */ char * -get_timestr(tstamp, log_year) - time_t tstamp; - int log_year; +get_timestr(time_t tstamp, int log_year) { char *s; #ifdef HAVE_STRFTIME diff --git a/plugins/sudoers/toke.c b/plugins/sudoers/toke.c new file mode 100644 index 0000000..7e84b56 --- /dev/null +++ b/plugins/sudoers/toke.c @@ -0,0 +1,3643 @@ +#include +/* $OpenBSD: flex.skl,v 1.11 2010/08/04 18:24:50 millert Exp $ */ + +/* A lexical scanner generated by flex */ + +/* Scanner skeleton version: + * $Header: /home/cvs/openbsd/src/usr.bin/lex/flex.skl,v 1.11 2010/08/04 18:24:50 millert Exp $ + */ + +#define FLEX_SCANNER +#define YY_FLEX_MAJOR_VERSION 2 +#define YY_FLEX_MINOR_VERSION 5 + +#include +#include + + +/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ +#ifdef c_plusplus +#ifndef __cplusplus +#define __cplusplus +#endif +#endif + + +#ifdef __cplusplus + +#include +#include + +/* Use prototypes in function declarations. */ +#define YY_USE_PROTOS + +/* The "const" storage-class-modifier is valid. */ +#define YY_USE_CONST + +#else /* ! __cplusplus */ + +#ifdef __STDC__ + +#define YY_USE_PROTOS +#define YY_USE_CONST + +#endif /* __STDC__ */ +#endif /* ! __cplusplus */ + +#ifdef __TURBOC__ + #pragma warn -rch + #pragma warn -use +#include +#include +#define YY_USE_CONST +#define YY_USE_PROTOS +#endif + +#ifdef YY_USE_CONST +#define yyconst const +#else +#define yyconst +#endif + + +#ifdef YY_USE_PROTOS +#define YY_PROTO(proto) proto +#else +#define YY_PROTO(proto) () +#endif + +/* Returned upon end-of-file. */ +#define YY_NULL 0 + +/* Promotes a possibly negative, possibly signed char to an unsigned + * integer for use as an array index. If the signed char is negative, + * we want to instead treat it as an 8-bit unsigned char, hence the + * double cast. + */ +#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) + +/* Enter a start condition. This macro really ought to take a parameter, + * but we do it the disgusting crufty way forced on us by the ()-less + * definition of BEGIN. + */ +#define BEGIN yy_start = 1 + 2 * + +/* Translate the current start state into a value that can be later handed + * to BEGIN to return to the state. The YYSTATE alias is for lex + * compatibility. + */ +#define YY_START ((yy_start - 1) / 2) +#define YYSTATE YY_START + +/* Action number for EOF rule of a given start state. */ +#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) + +/* Special action meaning "start processing a new file". */ +#define YY_NEW_FILE yyrestart( yyin ) + +#define YY_END_OF_BUFFER_CHAR 0 + +/* Size of default input buffer. */ +#define YY_BUF_SIZE 16384 + +typedef struct yy_buffer_state *YY_BUFFER_STATE; + +extern int yyleng; +extern FILE *yyin, *yyout; + +#define EOB_ACT_CONTINUE_SCAN 0 +#define EOB_ACT_END_OF_FILE 1 +#define EOB_ACT_LAST_MATCH 2 + +/* The funky do-while in the following #define is used to turn the definition + * int a single C statement (which needs a semi-colon terminator). This + * avoids problems with code like: + * + * if ( condition_holds ) + * yyless( 5 ); + * else + * do_something_else(); + * + * Prior to using the do-while the compiler would get upset at the + * "else" because it interpreted the "if" statement as being all + * done when it reached the ';' after the yyless() call. + */ + +/* Return all but the first 'n' matched characters back to the input stream. */ + +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + *yy_cp = yy_hold_char; \ + YY_RESTORE_YY_MORE_OFFSET \ + yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ + YY_DO_BEFORE_ACTION; /* set up yytext again */ \ + } \ + while ( 0 ) + +#define unput(c) yyunput( c, yytext_ptr ) + +/* The following is because we cannot portably get our hands on size_t + * (without autoconf's help, which isn't available because we want + * flex-generated scanners to compile on their own). + */ +typedef unsigned int yy_size_t; + + +struct yy_buffer_state + { + FILE *yy_input_file; + + char *yy_ch_buf; /* input buffer */ + char *yy_buf_pos; /* current position in input buffer */ + + /* Size of input buffer in bytes, not including room for EOB + * characters. + */ + yy_size_t yy_buf_size; + + /* Number of characters read into yy_ch_buf, not including EOB + * characters. + */ + int yy_n_chars; + + /* Whether we "own" the buffer - i.e., we know we created it, + * and can realloc() it to grow it, and should free() it to + * delete it. + */ + int yy_is_our_buffer; + + /* Whether this is an "interactive" input source; if so, and + * if we're using stdio for input, then we want to use getc() + * instead of fread(), to make sure we stop fetching input after + * each newline. + */ + int yy_is_interactive; + + /* Whether we're considered to be at the beginning of a line. + * If so, '^' rules will be active on the next match, otherwise + * not. + */ + int yy_at_bol; + + /* Whether to try to fill the input buffer when we reach the + * end of it. + */ + int yy_fill_buffer; + + int yy_buffer_status; +#define YY_BUFFER_NEW 0 +#define YY_BUFFER_NORMAL 1 + /* When an EOF's been seen but there's still some text to process + * then we mark the buffer as YY_EOF_PENDING, to indicate that we + * shouldn't try reading from the input source any more. We might + * still have a bunch of tokens to match, though, because of + * possible backing-up. + * + * When we actually see the EOF, we change the status to "new" + * (via yyrestart()), so that the user can continue scanning by + * just pointing yyin at a new input file. + */ +#define YY_BUFFER_EOF_PENDING 2 + }; + +static YY_BUFFER_STATE yy_current_buffer = 0; + +/* We provide macros for accessing buffer states in case in the + * future we want to put the buffer states in a more general + * "scanner state". + */ +#define YY_CURRENT_BUFFER yy_current_buffer + + +/* yy_hold_char holds the character lost when yytext is formed. */ +static char yy_hold_char; + +static int yy_n_chars; /* number of characters read into yy_ch_buf */ + + +int yyleng; + +/* Points to current character in buffer. */ +static char *yy_c_buf_p = (char *) 0; +static int yy_init = 1; /* whether we need to initialize */ +static int yy_start = 0; /* start state number */ + +/* Flag which is used to allow yywrap()'s to do buffer switches + * instead of setting up a fresh yyin. A bit of a hack ... + */ +static int yy_did_buffer_switch_on_eof; + +void yyrestart YY_PROTO(( FILE *input_file )); + +void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); +void yy_load_buffer_state YY_PROTO(( void )); +YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); +void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); +void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); +void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); +#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) + +YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); +YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); +YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); + +static void *yy_flex_alloc YY_PROTO(( yy_size_t )); +static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); +static void yy_flex_free YY_PROTO(( void * )); + +#define yy_new_buffer yy_create_buffer + +#define yy_set_interactive(is_interactive) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_is_interactive = is_interactive; \ + } + +#define yy_set_bol(at_bol) \ + { \ + if ( ! yy_current_buffer ) \ + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ + yy_current_buffer->yy_at_bol = at_bol; \ + } + +#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) + + +#define yywrap() 1 +#define YY_SKIP_YYWRAP +typedef unsigned char YY_CHAR; +FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; +typedef int yy_state_type; +extern char *yytext; +#define yytext_ptr yytext + +static yy_state_type yy_get_previous_state YY_PROTO(( void )); +static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); +static int yy_get_next_buffer YY_PROTO(( void )); +static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); + +/* Done after the current pattern has been matched and before the + * corresponding action - sets up yytext. + */ +#define YY_DO_BEFORE_ACTION \ + yytext_ptr = yy_bp; \ + yyleng = (int) (yy_cp - yy_bp); \ + yy_hold_char = *yy_cp; \ + *yy_cp = '\0'; \ + yy_c_buf_p = yy_cp; + +#define YY_NUM_RULES 59 +#define YY_END_OF_BUFFER 60 +static yyconst short int yy_accept[607] = + { 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 60, 47, 55, 54, 53, 46, 58, 32, + 48, 49, 32, 50, 47, 47, 47, 47, 52, 51, + 58, 42, 42, 42, 42, 42, 42, 42, 42, 42, + 42, 58, 47, 47, 55, 58, 42, 42, 42, 42, + 42, 2, 58, 1, 47, 47, 17, 16, 17, 16, + 16, 58, 58, 58, 3, 9, 8, 9, 4, 9, + 5, 58, 13, 13, 13, 11, 12, 47, 0, 55, + 53, 0, 57, 0, 47, 34, 0, 32, 0, 33, + 0, 45, 45, 0, 47, 47, 0, 47, 47, 47, + + 47, 0, 37, 42, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 47, 56, 47, 55, 0, 0, 0, + 0, 0, 0, 47, 47, 47, 47, 47, 2, 1, + 0, 1, 43, 43, 0, 47, 17, 17, 15, 14, + 15, 0, 0, 3, 9, 0, 6, 7, 9, 9, + 13, 0, 13, 13, 0, 10, 0, 0, 0, 34, + 34, 0, 0, 47, 47, 47, 47, 47, 0, 0, + 37, 37, 42, 39, 42, 42, 42, 42, 42, 42, + 42, 42, 42, 42, 47, 0, 0, 0, 0, 0, + 0, 47, 47, 47, 47, 47, 0, 47, 10, 0, + + 47, 47, 47, 47, 47, 47, 0, 38, 38, 38, + 0, 0, 37, 37, 37, 37, 37, 37, 37, 42, + 42, 42, 42, 42, 42, 42, 42, 40, 42, 41, + 47, 0, 0, 0, 0, 0, 0, 47, 47, 47, + 47, 47, 47, 47, 0, 0, 38, 38, 38, 0, + 37, 37, 0, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 0, 25, 42, 42, 42, 42, + 42, 42, 42, 42, 47, 0, 0, 0, 0, 47, + 47, 47, 47, 47, 47, 47, 47, 0, 38, 0, + 37, 37, 37, 0, 0, 0, 37, 37, 37, 37, + + 37, 37, 37, 37, 37, 37, 37, 37, 37, 42, + 42, 42, 42, 42, 42, 42, 42, 47, 0, 0, + 0, 47, 47, 47, 35, 35, 35, 0, 0, 37, + 37, 37, 37, 37, 37, 37, 0, 0, 0, 0, + 0, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 42, 42, 0, 24, 42, + 42, 42, 42, 0, 23, 0, 26, 47, 0, 0, + 0, 47, 47, 47, 47, 35, 35, 35, 35, 0, + 37, 0, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 0, 0, 0, 37, 37, 37, 37, + + 37, 37, 37, 37, 37, 37, 37, 37, 37, 42, + 42, 42, 42, 42, 42, 44, 0, 0, 0, 47, + 20, 43, 36, 36, 36, 36, 37, 0, 0, 0, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 0, 0, 0, 0, 0, 37, 37, + 37, 37, 37, 37, 37, 37, 42, 42, 42, 42, + 0, 22, 0, 27, 0, 20, 0, 0, 47, 0, + 47, 47, 47, 36, 36, 36, 36, 0, 0, 0, + 0, 0, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + + 37, 37, 0, 30, 42, 42, 42, 0, 0, 0, + 21, 20, 0, 0, 0, 0, 0, 20, 0, 47, + 47, 47, 0, 0, 0, 37, 37, 37, 37, 37, + 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, + 37, 37, 37, 0, 28, 42, 42, 21, 0, 18, + 0, 0, 20, 47, 47, 47, 47, 47, 0, 0, + 0, 0, 0, 37, 37, 37, 37, 37, 37, 37, + 37, 0, 31, 42, 0, 47, 47, 47, 37, 37, + 37, 37, 37, 37, 0, 29, 0, 47, 47, 47, + 47, 47, 37, 37, 37, 37, 37, 0, 19, 35, + + 35, 35, 35, 35, 35, 0 + } ; + +static yyconst int yy_ec[256] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 2, 4, 5, 6, 1, 7, 1, 1, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, + 19, 20, 21, 22, 22, 22, 23, 24, 1, 1, + 25, 26, 10, 27, 28, 29, 30, 31, 32, 29, + 33, 34, 35, 36, 36, 37, 36, 38, 39, 40, + 36, 41, 42, 43, 44, 45, 46, 47, 48, 36, + 10, 49, 10, 1, 50, 1, 51, 52, 53, 54, + + 55, 56, 57, 57, 58, 57, 57, 59, 60, 61, + 62, 57, 57, 63, 64, 65, 66, 57, 57, 57, + 57, 57, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1 + } ; + +static yyconst int yy_meta[67] = + { 0, + 1, 2, 3, 4, 5, 6, 1, 7, 7, 1, + 1, 8, 1, 9, 10, 11, 11, 11, 11, 11, + 11, 11, 11, 12, 13, 7, 1, 11, 11, 11, + 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 14, 15, + 16, 16, 16, 16, 16, 16, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15 + } ; + +static yyconst short int yy_base[671] = + { 0, + 0, 65, 67, 72, 99, 114, 162, 227, 292, 340, + 86, 125, 2840, 2790, 2836, 3665, 2833, 3665, 387, 70, + 3665, 3665, 2771, 3665, 136, 397, 133, 159, 2795, 3665, + 3665, 453, 2781, 33, 504, 2770, 2767, 2777, 2765, 2771, + 2754, 559, 170, 19, 165, 583, 38, 49, 2739, 68, + 2727, 81, 219, 2771, 305, 48, 0, 3665, 2761, 3665, + 0, 250, 639, 119, 0, 2709, 3665, 108, 3665, 112, + 3665, 140, 2699, 98, 121, 3665, 195, 2693, 661, 2739, + 2736, 2736, 3665, 227, 247, 300, 316, 152, 354, 2681, + 686, 373, 2670, 711, 352, 722, 2692, 2669, 375, 414, + + 302, 2656, 57, 763, 0, 2628, 2625, 2614, 505, 2602, + 2606, 2599, 2601, 202, 3665, 153, 546, 2572, 2565, 2549, + 2537, 2524, 200, 110, 244, 28, 111, 252, 171, 2578, + 422, 2577, 565, 2529, 818, 262, 0, 2573, 179, 3665, + 3665, 599, 269, 0, 2513, 453, 3665, 3665, 2512, 548, + 2490, 2533, 206, 253, 323, 2535, 2524, 2513, 607, 615, + 306, 722, 586, 831, 867, 903, 939, 2499, 2456, 980, + 333, 1022, 1063, 0, 2430, 2394, 2363, 2364, 2374, 2369, + 2327, 2330, 2329, 2328, 266, 2289, 2283, 2272, 2274, 2279, + 409, 334, 2279, 145, 335, 83, 672, 278, 2327, 2325, + + 627, 259, 1106, 1142, 741, 210, 2293, 2279, 683, 513, + 2275, 2271, 352, 747, 1178, 780, 788, 1220, 815, 2270, + 400, 325, 2261, 2258, 2248, 2246, 2242, 0, 2240, 0, + 489, 2223, 2213, 2198, 2211, 2198, 420, 407, 529, 490, + 491, 1263, 1299, 1335, 2235, 2234, 839, 2234, 2232, 2228, + 2226, 528, 848, 657, 856, 665, 1371, 0, 877, 1382, + 886, 894, 1424, 913, 570, 3665, 2208, 2197, 2198, 2177, + 2184, 2193, 2190, 2169, 558, 2145, 2098, 2099, 648, 626, + 530, 559, 923, 336, 1467, 1503, 964, 2138, 2137, 2108, + 2086, 1537, 551, 1000, 1041, 1082, 653, 694, 797, 1049, + + 923, 1580, 0, 1116, 1591, 1090, 1008, 1633, 1125, 2069, + 2065, 747, 686, 2046, 2005, 786, 926, 905, 2014, 1982, + 679, 634, 544, 915, 1675, 1710, 1745, 2015, 1978, 1962, + 1150, 1781, 1158, 1133, 1822, 1197, 1166, 1954, 1239, 1273, + 1207, 950, 951, 962, 991, 1247, 1073, 1865, 0, 1283, + 1876, 1307, 1315, 1918, 1323, 1923, 1923, 1188, 3665, 1924, + 1898, 1893, 1873, 1286, 3665, 1336, 3665, 707, 1790, 1783, + 786, 930, 764, 1298, 1358, 1041, 1960, 1995, 1400, 1823, + 1799, 1348, 708, 1406, 1348, 2031, 0, 559, 2042, 1441, + 1449, 2083, 1477, 1487, 1513, 1523, 1230, 1290, 1458, 1548, + + 1557, 1602, 2126, 0, 1613, 2137, 1650, 1565, 1660, 1765, + 1763, 1680, 1675, 1359, 1406, 1626, 1601, 1577, 897, 938, + 1695, 1589, 2180, 2216, 2252, 2288, 1611, 1686, 1720, 1731, + 1563, 1478, 1504, 1694, 1524, 2324, 0, 617, 2335, 1753, + 1761, 2376, 1769, 1798, 1550, 1808, 1841, 1851, 1335, 1358, + 1887, 714, 825, 2419, 0, 926, 1407, 1508, 1506, 1471, + 1547, 3665, 1616, 3665, 1423, 1731, 1907, 1512, 1575, 1910, + 1915, 1935, 1498, 2429, 2465, 1971, 1611, 1977, 1457, 2005, + 2015, 1987, 1408, 1254, 1732, 1782, 2059, 1842, 2501, 0, + 1025, 2512, 2067, 2100, 2553, 2108, 2155, 2164, 2189, 1769, + + 1207, 1189, 1634, 3665, 1699, 1162, 1113, 1074, 1118, 384, + 1040, 2211, 2218, 2238, 2243, 2263, 2288, 2249, 2307, 2596, + 2632, 2668, 2304, 2354, 2395, 1025, 1006, 1889, 2016, 2362, + 2043, 2704, 0, 1224, 2715, 2403, 2437, 2445, 992, 2454, + 2474, 2483, 903, 1921, 3665, 1941, 839, 3665, 843, 3665, + 1306, 2489, 2529, 2537, 1911, 2758, 2794, 2573, 2579, 811, + 2607, 2617, 2642, 640, 629, 2109, 535, 447, 2650, 0, + 1428, 1942, 3665, 2044, 2216, 2830, 2866, 2902, 2676, 2684, + 2692, 337, 0, 333, 2067, 3665, 327, 2733, 1912, 2938, + 2974, 2743, 3665, 2767, 2777, 2658, 3665, 166, 3665, 2805, + + 2813, 2847, 63, 2855, 2881, 3665, 3023, 3039, 3055, 3071, + 3087, 3103, 3119, 3135, 3151, 3157, 3173, 3189, 1498, 3205, + 3221, 3237, 3253, 3269, 3285, 3301, 3307, 3314, 3330, 3346, + 3352, 3359, 3365, 3371, 3377, 3384, 3390, 3396, 3402, 3409, + 3417, 3423, 3429, 3435, 3442, 3450, 3456, 3462, 3469, 3477, + 3483, 3491, 3498, 3506, 3512, 3520, 3527, 3535, 3551, 3567, + 3573, 3581, 3588, 3604, 3610, 3618, 3624, 3632, 1295, 3648 + } ; + +static yyconst short int yy_def[671] = + { 0, + 606, 1, 1, 1, 607, 607, 608, 608, 609, 609, + 610, 610, 606, 611, 606, 606, 606, 606, 612, 613, + 606, 606, 614, 606, 615, 611, 26, 26, 616, 606, + 606, 606, 32, 32, 32, 35, 35, 35, 35, 35, + 35, 611, 26, 611, 606, 612, 32, 32, 35, 35, + 35, 606, 606, 606, 617, 611, 618, 606, 618, 606, + 618, 606, 612, 606, 619, 620, 606, 620, 606, 620, + 606, 621, 622, 622, 622, 606, 606, 611, 611, 606, + 606, 623, 606, 624, 606, 613, 606, 625, 613, 614, + 614, 615, 626, 611, 611, 26, 616, 96, 96, 96, + + 96, 627, 628, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 611, 606, 611, 606, 606, 606, 606, + 606, 606, 623, 611, 96, 611, 611, 611, 606, 606, + 606, 606, 617, 629, 611, 611, 618, 618, 606, 606, + 606, 624, 606, 619, 620, 620, 606, 606, 620, 620, + 622, 606, 622, 622, 606, 606, 623, 630, 606, 606, + 625, 625, 606, 611, 611, 611, 96, 167, 631, 606, + 632, 606, 104, 35, 35, 35, 35, 35, 35, 35, + 35, 35, 35, 35, 611, 606, 606, 606, 606, 606, + 623, 611, 167, 611, 611, 611, 606, 611, 606, 630, + + 611, 611, 611, 611, 611, 611, 633, 634, 634, 209, + 635, 634, 636, 172, 606, 215, 215, 606, 215, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, + 611, 606, 606, 606, 606, 606, 623, 611, 611, 611, + 611, 611, 611, 611, 606, 637, 637, 247, 637, 638, + 639, 640, 606, 641, 218, 641, 641, 257, 641, 606, + 260, 260, 606, 260, 606, 606, 35, 35, 35, 35, + 35, 35, 35, 35, 611, 606, 606, 606, 623, 611, + 611, 611, 611, 611, 611, 611, 611, 642, 642, 643, + 644, 606, 606, 606, 606, 606, 645, 645, 646, 263, + + 646, 646, 302, 646, 606, 305, 305, 606, 305, 35, + 35, 35, 35, 35, 35, 35, 35, 611, 606, 606, + 623, 611, 611, 611, 611, 611, 611, 606, 647, 648, + 292, 606, 332, 332, 606, 332, 606, 606, 606, 606, + 606, 606, 649, 649, 650, 308, 650, 650, 348, 650, + 606, 351, 351, 606, 351, 35, 35, 606, 606, 35, + 35, 35, 35, 606, 606, 606, 606, 611, 606, 606, + 623, 611, 611, 611, 611, 611, 611, 611, 611, 606, + 651, 606, 652, 335, 652, 652, 386, 386, 606, 389, + 389, 606, 389, 606, 606, 606, 606, 653, 653, 654, + + 354, 654, 654, 403, 654, 606, 406, 406, 406, 35, + 35, 35, 35, 35, 35, 611, 606, 606, 623, 611, + 611, 611, 611, 611, 611, 611, 606, 606, 606, 606, + 655, 655, 656, 392, 656, 656, 436, 436, 606, 439, + 439, 606, 439, 606, 606, 606, 606, 606, 606, 657, + 657, 658, 658, 658, 454, 454, 35, 35, 35, 35, + 606, 606, 606, 606, 606, 606, 623, 623, 611, 659, + 660, 611, 611, 611, 611, 611, 611, 606, 606, 606, + 606, 606, 606, 661, 661, 662, 442, 662, 662, 489, + 489, 606, 492, 492, 606, 492, 606, 606, 606, 606, + + 663, 663, 606, 606, 35, 35, 35, 606, 664, 623, + 611, 659, 659, 659, 659, 606, 659, 660, 660, 611, + 611, 611, 606, 606, 606, 606, 665, 665, 666, 495, + 666, 666, 532, 532, 606, 535, 535, 535, 606, 606, + 606, 606, 606, 606, 606, 35, 35, 606, 664, 606, + 623, 606, 606, 611, 611, 611, 611, 611, 606, 606, + 606, 606, 606, 606, 667, 667, 668, 668, 668, 569, + 569, 606, 606, 35, 623, 611, 611, 611, 606, 606, + 606, 606, 669, 669, 606, 606, 670, 611, 611, 611, + 611, 611, 606, 606, 606, 606, 606, 670, 606, 611, + + 611, 611, 611, 611, 611, 0, 606, 606, 606, 606, + 606, 606, 606, 606, 606, 606, 606, 606, 606, 606, + 606, 606, 606, 606, 606, 606, 606, 606, 606, 606, + 606, 606, 606, 606, 606, 606, 606, 606, 606, 606, + 606, 606, 606, 606, 606, 606, 606, 606, 606, 606, + 606, 606, 606, 606, 606, 606, 606, 606, 606, 606, + 606, 606, 606, 606, 606, 606, 606, 606, 606, 606 + } ; + +static yyconst short int yy_nxt[3732] = + { 0, + 14, 15, 16, 17, 18, 19, 20, 21, 22, 14, + 23, 24, 14, 14, 25, 26, 27, 28, 26, 26, + 26, 26, 26, 29, 30, 31, 14, 32, 33, 33, + 33, 34, 35, 35, 35, 35, 36, 37, 35, 38, + 39, 40, 41, 35, 35, 35, 35, 35, 42, 14, + 43, 43, 43, 43, 43, 43, 14, 14, 14, 14, + 14, 14, 14, 44, 14, 14, 45, 79, 52, 105, + 46, 170, 53, 52, 105, 87, 79, 53, 54, 107, + 172, 55, 129, 54, 116, 105, 55, 74, 16, 75, + 76, 194, 130, 88, 47, 48, 79, 124, 49, 153, + + 15, 58, 59, 125, 60, 50, 111, 35, 51, 35, + 60, 79, 35, 136, 35, 15, 58, 59, 89, 60, + 143, 115, 60, 61, 154, 60, 74, 16, 75, 76, + 56, 79, 147, 127, 77, 56, 148, 60, 61, 93, + 93, 150, 115, 93, 93, 238, 152, 62, 99, 99, + 99, 99, 99, 99, 99, 99, 146, 87, 79, 79, + 146, 93, 62, 15, 16, 17, 117, 63, 599, 152, + 192, 195, 129, 77, 100, 100, 100, 100, 100, 101, + 143, 115, 130, 78, 94, 98, 98, 98, 98, 98, + 98, 98, 98, 79, 118, 119, 155, 156, 120, 151, + + 162, 79, 83, 143, 115, 121, 185, 153, 122, 238, + 64, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 15, 16, + 17, 131, 63, 97, 85, 85, 85, 85, 85, 85, + 85, 85, 85, 85, 85, 85, 85, 85, 85, 85, + 79, 139, 115, 140, 152, 141, 154, 78, 79, 140, + 191, 141, 85, 85, 85, 85, 85, 85, 85, 85, + 143, 115, 201, 141, 141, 64, 65, 65, 65, 65, + 65, 65, 65, 65, 65, 65, 65, 65, 65, 65, + 65, 65, 65, 15, 16, 17, 67, 63, 141, 193, + + 79, 152, 68, 69, 70, 606, 196, 79, 134, 134, + 79, 606, 134, 134, 79, 198, 71, 168, 168, 168, + 168, 168, 168, 606, 155, 156, 79, 231, 159, 599, + 134, 160, 160, 160, 160, 160, 160, 160, 160, 241, + 72, 15, 16, 17, 67, 63, 382, 170, 89, 283, + 68, 69, 70, 135, 162, 86, 214, 86, 86, 267, + 530, 86, 86, 268, 71, 86, 170, 164, 165, 166, + 164, 164, 164, 164, 164, 214, 93, 93, 86, 86, + 93, 93, 79, 79, 79, 240, 83, 238, 72, 83, + 168, 168, 168, 168, 168, 168, 168, 168, 93, 84, + + 79, 265, 85, 85, 85, 85, 85, 85, 85, 85, + 95, 83, 96, 96, 96, 96, 96, 96, 96, 96, + 97, 94, 83, 266, 98, 98, 98, 98, 98, 168, + 168, 168, 168, 168, 168, 168, 168, 85, 85, 85, + 85, 85, 85, 85, 85, 79, 551, 98, 98, 98, + 98, 98, 98, 78, 145, 79, 280, 145, 145, 78, + 606, 237, 78, 78, 145, 78, 78, 78, 104, 104, + 104, 104, 104, 104, 104, 104, 97, 145, 279, 78, + 104, 104, 104, 104, 104, 105, 105, 105, 105, 106, + 105, 105, 105, 105, 105, 105, 105, 105, 105, 105, + + 105, 79, 105, 98, 98, 98, 98, 98, 98, 78, + 78, 78, 78, 78, 78, 78, 78, 78, 78, 105, + 105, 105, 105, 105, 105, 105, 105, 606, 249, 249, + 249, 105, 105, 105, 105, 105, 177, 79, 79, 79, + 105, 178, 170, 275, 179, 282, 180, 117, 382, 143, + 115, 214, 97, 238, 78, 78, 78, 78, 78, 78, + 114, 115, 78, 78, 78, 170, 78, 78, 134, 134, + 78, 265, 134, 134, 214, 118, 119, 79, 79, 120, + 431, 431, 78, 78, 78, 83, 121, 93, 323, 122, + 134, 93, 79, 266, 281, 84, 146, 93, 85, 85, + + 85, 85, 85, 85, 85, 85, 79, 79, 373, 93, + 93, 318, 324, 135, 606, 606, 606, 606, 606, 606, + 606, 606, 160, 160, 160, 160, 160, 160, 160, 160, + 160, 160, 160, 160, 160, 160, 160, 160, 484, 484, + 123, 83, 242, 243, 244, 242, 242, 242, 242, 242, + 83, 142, 530, 322, 606, 606, 606, 606, 606, 606, + 606, 606, 78, 487, 78, 78, 78, 170, 78, 78, + 253, 170, 78, 134, 79, 79, 255, 134, 606, 170, + 255, 83, 79, 134, 78, 78, 78, 90, 255, 90, + 90, 90, 372, 90, 90, 134, 134, 90, 247, 247, + + 248, 249, 249, 249, 249, 249, 211, 253, 170, 90, + 90, 90, 92, 321, 78, 78, 92, 255, 78, 78, + 360, 382, 92, 161, 361, 161, 161, 253, 170, 161, + 161, 384, 371, 161, 92, 92, 78, 167, 167, 167, + 167, 167, 167, 167, 167, 161, 161, 161, 358, 167, + 167, 167, 167, 167, 201, 79, 202, 202, 202, 202, + 202, 202, 219, 219, 219, 219, 219, 219, 219, 219, + 359, 416, 167, 167, 167, 167, 167, 167, 173, 173, + 173, 173, 173, 173, 173, 173, 97, 364, 83, 79, + 173, 173, 173, 173, 173, 257, 257, 257, 257, 257, + + 257, 257, 257, 258, 258, 258, 258, 258, 259, 365, + 253, 170, 79, 167, 167, 167, 167, 167, 167, 133, + 300, 78, 78, 133, 559, 78, 78, 421, 606, 133, + 256, 256, 256, 256, 256, 256, 256, 256, 606, 170, + 419, 133, 133, 78, 201, 550, 202, 202, 202, 202, + 202, 202, 202, 202, 289, 289, 289, 289, 289, 289, + 289, 289, 211, 294, 295, 296, 294, 294, 294, 294, + 294, 264, 264, 264, 264, 264, 264, 264, 264, 79, + 201, 574, 203, 203, 203, 203, 203, 203, 203, 203, + 253, 170, 298, 298, 298, 298, 298, 298, 467, 83, + + 255, 302, 302, 302, 302, 302, 302, 302, 302, 303, + 303, 303, 303, 303, 304, 79, 201, 170, 204, 204, + 204, 204, 204, 205, 202, 202, 606, 366, 301, 301, + 301, 301, 301, 301, 301, 301, 606, 170, 325, 326, + 327, 325, 325, 325, 325, 325, 300, 501, 501, 367, + 468, 79, 78, 79, 206, 206, 206, 206, 206, 206, + 206, 206, 368, 79, 170, 170, 206, 206, 206, 206, + 206, 79, 374, 255, 300, 253, 170, 283, 79, 284, + 284, 284, 284, 284, 284, 300, 79, 420, 469, 206, + 206, 206, 206, 206, 206, 208, 209, 210, 210, 210, + + 210, 210, 210, 211, 253, 170, 170, 212, 212, 212, + 212, 212, 79, 337, 346, 338, 338, 338, 338, 338, + 338, 338, 338, 349, 349, 349, 349, 349, 350, 487, + 212, 212, 212, 212, 212, 212, 170, 215, 216, 217, + 215, 215, 215, 215, 215, 218, 527, 527, 434, 219, + 219, 219, 219, 219, 337, 375, 339, 339, 339, 339, + 339, 339, 339, 339, 309, 309, 309, 309, 309, 309, + 309, 309, 219, 219, 219, 219, 219, 219, 220, 220, + 220, 220, 220, 220, 220, 220, 606, 170, 79, 79, + 220, 220, 220, 220, 220, 337, 346, 340, 340, 340, + + 340, 340, 341, 338, 338, 348, 348, 348, 348, 348, + 348, 348, 348, 206, 206, 206, 206, 206, 206, 201, + 550, 202, 202, 202, 202, 202, 202, 202, 202, 253, + 170, 344, 344, 344, 344, 344, 344, 548, 606, 300, + 347, 347, 347, 347, 347, 347, 347, 347, 387, 387, + 387, 387, 387, 388, 79, 201, 547, 202, 202, 202, + 202, 202, 202, 202, 202, 336, 336, 336, 336, 336, + 336, 336, 336, 386, 386, 386, 386, 386, 386, 386, + 386, 394, 395, 396, 394, 394, 394, 394, 394, 358, + 79, 253, 170, 254, 254, 254, 254, 254, 254, 254, + + 254, 255, 253, 170, 546, 256, 256, 256, 256, 256, + 606, 359, 385, 385, 385, 385, 385, 385, 385, 385, + 337, 170, 338, 338, 338, 338, 338, 338, 256, 256, + 256, 256, 256, 256, 170, 260, 261, 262, 260, 260, + 260, 260, 260, 263, 170, 565, 565, 264, 264, 264, + 264, 264, 337, 300, 338, 338, 338, 338, 338, 338, + 338, 338, 355, 355, 355, 355, 355, 355, 355, 355, + 264, 264, 264, 264, 264, 264, 283, 434, 284, 284, + 284, 284, 284, 284, 284, 284, 337, 364, 338, 338, + 338, 338, 338, 338, 338, 338, 253, 170, 399, 399, + + 399, 399, 399, 399, 170, 597, 346, 575, 83, 365, + 597, 79, 283, 346, 285, 285, 285, 285, 285, 285, + 285, 285, 403, 403, 403, 403, 403, 403, 403, 403, + 404, 404, 404, 404, 404, 405, 606, 366, 402, 402, + 402, 402, 402, 402, 402, 402, 79, 79, 283, 170, + 286, 286, 286, 286, 286, 287, 284, 284, 346, 367, + 461, 606, 422, 428, 429, 430, 428, 428, 428, 428, + 428, 384, 170, 423, 424, 425, 426, 423, 423, 423, + 423, 401, 462, 79, 253, 170, 298, 298, 298, 298, + 298, 298, 298, 298, 255, 253, 170, 299, 299, 299, + + 299, 299, 299, 299, 299, 300, 79, 463, 503, 301, + 301, 301, 301, 301, 375, 376, 376, 376, 376, 376, + 376, 393, 393, 393, 393, 393, 393, 393, 393, 464, + 504, 384, 301, 301, 301, 301, 301, 301, 170, 305, + 306, 307, 305, 305, 305, 305, 305, 308, 79, 583, + 583, 309, 309, 309, 309, 309, 436, 436, 436, 436, + 436, 436, 436, 436, 437, 437, 437, 437, 437, 438, + 478, 253, 170, 508, 309, 309, 309, 309, 309, 309, + 283, 346, 284, 284, 284, 284, 284, 284, 284, 284, + 606, 382, 435, 435, 435, 435, 435, 435, 435, 435, + + 444, 384, 445, 445, 445, 445, 445, 445, 445, 445, + 507, 472, 144, 144, 83, 79, 283, 382, 284, 284, + 284, 284, 284, 284, 284, 284, 444, 434, 446, 446, + 446, 446, 446, 446, 446, 446, 444, 606, 447, 447, + 447, 447, 447, 448, 445, 445, 79, 434, 461, 506, + 505, 79, 332, 333, 334, 332, 332, 332, 332, 332, + 335, 253, 170, 444, 336, 336, 336, 336, 336, 510, + 462, 401, 409, 409, 409, 409, 409, 409, 409, 409, + 455, 455, 455, 455, 455, 456, 384, 336, 336, 336, + 336, 336, 336, 253, 170, 344, 344, 344, 344, 344, + + 344, 344, 344, 300, 253, 170, 345, 345, 345, 345, + 345, 345, 345, 345, 346, 606, 170, 463, 347, 347, + 347, 347, 347, 79, 472, 401, 253, 170, 451, 451, + 451, 451, 451, 451, 331, 503, 401, 79, 511, 464, + 466, 347, 347, 347, 347, 347, 347, 170, 351, 352, + 353, 351, 351, 351, 351, 351, 354, 504, 465, 79, + 355, 355, 355, 355, 355, 454, 454, 454, 454, 454, + 454, 454, 454, 606, 79, 453, 453, 453, 453, 453, + 453, 453, 453, 355, 355, 355, 355, 355, 355, 375, + 376, 376, 376, 376, 376, 376, 376, 376, 470, 478, + + 544, 479, 479, 479, 479, 479, 479, 479, 479, 443, + 443, 443, 443, 443, 443, 443, 443, 460, 470, 459, + 470, 471, 545, 79, 375, 377, 377, 377, 377, 377, + 377, 377, 377, 478, 470, 480, 480, 480, 480, 480, + 480, 480, 480, 79, 478, 382, 481, 481, 481, 481, + 481, 482, 479, 479, 470, 434, 470, 470, 79, 375, + 378, 378, 378, 378, 378, 379, 376, 376, 489, 489, + 489, 489, 489, 489, 489, 489, 490, 490, 490, 490, + 490, 491, 606, 170, 488, 488, 488, 488, 488, 488, + 488, 488, 401, 79, 382, 382, 383, 383, 383, 383, + + 383, 383, 383, 383, 384, 487, 458, 457, 385, 385, + 385, 385, 385, 497, 498, 499, 497, 497, 497, 497, + 497, 444, 331, 445, 445, 445, 445, 445, 445, 445, + 445, 385, 385, 385, 385, 385, 385, 389, 390, 391, + 389, 389, 389, 389, 389, 392, 251, 418, 417, 393, + 393, 393, 393, 393, 444, 606, 445, 445, 445, 445, + 445, 445, 445, 445, 444, 487, 445, 445, 445, 445, + 445, 445, 393, 393, 393, 393, 393, 393, 253, 170, + 399, 399, 399, 399, 399, 399, 399, 399, 346, 253, + 170, 400, 400, 400, 400, 400, 400, 400, 400, 401, + + 253, 170, 382, 402, 402, 402, 402, 402, 467, 83, + 401, 513, 487, 514, 515, 516, 513, 415, 514, 515, + 516, 509, 544, 414, 554, 588, 402, 402, 402, 402, + 402, 402, 170, 406, 407, 408, 406, 406, 406, 406, + 406, 413, 572, 572, 545, 409, 409, 409, 409, 409, + 520, 521, 522, 520, 520, 520, 520, 520, 517, 79, + 79, 412, 411, 519, 573, 573, 410, 337, 409, 409, + 409, 409, 409, 409, 375, 376, 376, 376, 376, 376, + 376, 376, 376, 79, 472, 331, 473, 473, 473, 473, + 473, 473, 523, 524, 525, 523, 523, 523, 523, 523, + + 478, 251, 479, 479, 479, 479, 479, 479, 79, 375, + 376, 376, 376, 376, 376, 376, 376, 376, 478, 79, + 479, 479, 479, 479, 479, 479, 479, 479, 478, 382, + 479, 479, 479, 479, 479, 479, 479, 479, 211, 530, + 370, 369, 363, 79, 382, 585, 432, 432, 432, 432, + 432, 432, 432, 432, 384, 382, 606, 433, 433, 433, + 433, 433, 433, 433, 433, 434, 530, 586, 585, 435, + 435, 435, 435, 435, 496, 496, 496, 496, 496, 496, + 496, 496, 532, 532, 532, 532, 532, 532, 532, 532, + 586, 362, 435, 435, 435, 435, 435, 435, 439, 440, + + 441, 439, 439, 439, 439, 439, 442, 357, 356, 331, + 443, 443, 443, 443, 443, 533, 533, 533, 533, 533, + 534, 606, 382, 531, 531, 531, 531, 531, 531, 531, + 531, 251, 530, 443, 443, 443, 443, 443, 443, 253, + 170, 451, 451, 451, 451, 451, 451, 451, 451, 401, + 253, 170, 452, 452, 452, 452, 452, 452, 452, 452, + 211, 211, 276, 320, 453, 453, 453, 453, 453, 170, + 539, 539, 539, 539, 539, 539, 539, 539, 170, 540, + 540, 540, 540, 540, 540, 540, 540, 453, 453, 453, + 453, 453, 453, 472, 319, 473, 473, 473, 473, 473, + + 473, 473, 473, 170, 541, 541, 541, 541, 541, 542, + 539, 539, 606, 317, 606, 606, 606, 575, 83, 513, + 316, 514, 515, 516, 315, 314, 313, 312, 79, 472, + 587, 474, 474, 474, 474, 474, 474, 474, 474, 606, + 311, 514, 515, 516, 606, 310, 606, 606, 516, 292, + 606, 251, 606, 606, 606, 211, 288, 211, 103, 517, + 276, 278, 276, 277, 79, 472, 517, 475, 475, 475, + 475, 475, 476, 477, 477, 552, 276, 274, 553, 553, + 553, 553, 553, 553, 553, 553, 517, 273, 272, 271, + 270, 517, 269, 97, 211, 512, 512, 519, 251, 512, + + 79, 472, 211, 477, 477, 477, 473, 473, 473, 473, + 473, 512, 512, 512, 518, 518, 103, 559, 518, 560, + 560, 560, 560, 560, 560, 560, 560, 83, 199, 239, + 518, 518, 518, 236, 235, 234, 79, 382, 233, 485, + 485, 485, 485, 485, 485, 485, 485, 434, 382, 232, + 486, 486, 486, 486, 486, 486, 486, 486, 487, 230, + 229, 228, 488, 488, 488, 488, 488, 559, 227, 561, + 561, 561, 561, 561, 561, 561, 561, 538, 538, 538, + 538, 538, 538, 538, 538, 488, 488, 488, 488, 488, + 488, 492, 493, 494, 492, 492, 492, 492, 492, 495, + + 226, 225, 224, 496, 496, 496, 496, 496, 559, 223, + 562, 562, 562, 562, 562, 563, 560, 560, 569, 569, + 569, 569, 569, 569, 569, 569, 496, 496, 496, 496, + 496, 496, 253, 170, 502, 502, 502, 502, 502, 502, + 502, 502, 472, 222, 473, 473, 473, 473, 473, 473, + 473, 473, 570, 570, 570, 570, 570, 571, 606, 221, + 568, 568, 568, 568, 568, 568, 568, 568, 170, 539, + 539, 539, 539, 539, 539, 539, 539, 79, 472, 103, + 473, 473, 473, 473, 473, 473, 473, 473, 170, 539, + 539, 539, 539, 539, 539, 539, 539, 170, 539, 539, + + 539, 539, 539, 539, 553, 553, 553, 553, 553, 553, + 553, 553, 95, 79, 382, 83, 528, 528, 528, 528, + 528, 528, 528, 528, 487, 382, 83, 529, 529, 529, + 529, 529, 529, 529, 529, 530, 199, 151, 152, 531, + 531, 531, 531, 531, 553, 553, 553, 553, 553, 553, + 553, 553, 576, 577, 578, 576, 576, 576, 576, 576, + 146, 146, 531, 531, 531, 531, 531, 531, 535, 536, + 537, 535, 535, 535, 535, 535, 138, 197, 132, 132, + 538, 538, 538, 538, 538, 79, 554, 190, 555, 555, + 555, 555, 555, 555, 579, 580, 581, 579, 579, 579, + + 579, 579, 189, 538, 538, 538, 538, 538, 538, 554, + 188, 555, 555, 555, 555, 555, 555, 555, 555, 187, + 559, 79, 560, 560, 560, 560, 560, 560, 560, 560, + 559, 186, 560, 560, 560, 560, 560, 560, 560, 560, + 184, 183, 182, 181, 79, 554, 176, 556, 556, 556, + 556, 556, 556, 556, 556, 559, 175, 560, 560, 560, + 560, 560, 560, 382, 174, 584, 584, 584, 584, 584, + 584, 584, 584, 593, 593, 593, 593, 593, 593, 103, + 79, 554, 78, 557, 557, 557, 557, 557, 558, 555, + 555, 593, 593, 593, 593, 593, 593, 593, 593, 594, + + 594, 594, 594, 594, 594, 594, 594, 595, 595, 595, + 595, 595, 596, 593, 593, 103, 79, 382, 163, 566, + 566, 566, 566, 566, 566, 566, 566, 530, 382, 91, + 567, 567, 567, 567, 567, 567, 567, 567, 83, 81, + 80, 79, 568, 568, 568, 568, 568, 152, 600, 601, + 602, 600, 600, 600, 600, 600, 588, 146, 589, 589, + 589, 589, 589, 589, 138, 568, 568, 568, 568, 568, + 568, 554, 132, 555, 555, 555, 555, 555, 555, 555, + 555, 79, 593, 593, 593, 593, 593, 593, 593, 593, + 128, 79, 593, 593, 593, 593, 593, 593, 593, 593, + + 126, 113, 112, 111, 110, 109, 79, 554, 108, 555, + 555, 555, 555, 555, 555, 555, 555, 105, 103, 91, + 603, 603, 603, 603, 603, 603, 603, 603, 600, 600, + 600, 600, 600, 600, 600, 600, 81, 80, 79, 606, + 606, 606, 79, 588, 606, 589, 589, 589, 589, 589, + 589, 589, 589, 79, 606, 606, 606, 606, 606, 606, + 606, 79, 604, 604, 604, 604, 604, 605, 603, 603, + 603, 603, 603, 603, 603, 603, 603, 603, 79, 588, + 606, 590, 590, 590, 590, 590, 590, 590, 590, 606, + 606, 606, 606, 606, 606, 79, 603, 603, 603, 603, + + 603, 603, 606, 79, 606, 606, 606, 606, 606, 606, + 606, 606, 606, 606, 79, 588, 606, 591, 591, 591, + 591, 591, 592, 589, 589, 606, 606, 606, 606, 79, + 606, 606, 606, 606, 606, 606, 606, 606, 606, 606, + 606, 606, 606, 606, 606, 606, 606, 606, 606, 606, + 79, 588, 606, 589, 589, 589, 589, 589, 589, 589, + 589, 606, 606, 606, 606, 606, 606, 606, 606, 606, + 606, 606, 606, 606, 606, 606, 606, 606, 606, 606, + 606, 606, 606, 606, 606, 606, 79, 588, 606, 589, + 589, 589, 589, 589, 589, 589, 589, 606, 606, 606, + + 606, 606, 606, 606, 606, 606, 606, 606, 606, 606, + 606, 606, 606, 606, 606, 606, 606, 606, 606, 606, + 606, 606, 79, 57, 57, 57, 57, 57, 57, 57, + 57, 57, 57, 57, 57, 57, 57, 57, 57, 31, + 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, + 31, 31, 31, 31, 31, 66, 66, 66, 66, 66, + 66, 66, 66, 66, 66, 66, 66, 66, 66, 66, + 66, 73, 73, 73, 73, 73, 73, 73, 73, 73, + 73, 73, 73, 73, 73, 73, 73, 78, 606, 606, + 606, 606, 606, 606, 606, 78, 78, 78, 606, 606, + + 78, 78, 78, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 86, + 606, 606, 606, 606, 86, 606, 606, 86, 86, 86, + 86, 606, 86, 86, 86, 90, 606, 606, 606, 606, + 606, 606, 606, 90, 90, 90, 606, 606, 90, 90, + 90, 92, 606, 606, 92, 92, 606, 92, 606, 92, + 92, 92, 606, 606, 92, 92, 92, 102, 102, 606, + 606, 606, 102, 133, 606, 606, 133, 133, 606, 133, + 606, 133, 133, 133, 606, 606, 133, 133, 133, 137, + 606, 606, 137, 137, 606, 137, 606, 137, 137, 137, + + 606, 137, 606, 137, 137, 145, 606, 606, 145, 606, + 606, 145, 606, 145, 145, 145, 145, 606, 145, 145, + 145, 149, 149, 149, 149, 149, 149, 149, 149, 149, + 149, 149, 149, 149, 149, 149, 149, 151, 151, 606, + 151, 606, 151, 151, 151, 151, 151, 151, 151, 151, + 151, 151, 151, 157, 157, 157, 157, 157, 157, 157, + 157, 157, 157, 157, 157, 157, 157, 157, 157, 158, + 158, 606, 158, 158, 158, 158, 158, 158, 158, 158, + 158, 158, 158, 158, 158, 161, 606, 606, 606, 606, + 161, 606, 606, 161, 161, 161, 606, 606, 161, 161, + + 161, 93, 606, 606, 93, 93, 606, 93, 606, 93, + 93, 93, 606, 606, 93, 93, 93, 169, 169, 606, + 606, 606, 169, 171, 171, 171, 606, 606, 606, 171, + 134, 606, 606, 134, 134, 606, 134, 606, 134, 134, + 134, 606, 606, 134, 134, 134, 200, 200, 200, 200, + 200, 200, 200, 200, 200, 200, 200, 200, 200, 200, + 200, 200, 207, 207, 606, 606, 606, 207, 213, 213, + 213, 606, 606, 606, 213, 245, 245, 606, 606, 606, + 245, 246, 246, 606, 606, 606, 246, 250, 250, 606, + 606, 606, 250, 252, 252, 252, 606, 606, 606, 252, + + 288, 288, 606, 606, 606, 288, 290, 290, 606, 606, + 606, 290, 291, 291, 606, 606, 606, 291, 293, 293, + 293, 606, 606, 606, 293, 297, 297, 297, 297, 606, + 606, 606, 297, 328, 328, 606, 606, 606, 328, 329, + 329, 606, 606, 606, 329, 330, 330, 606, 606, 606, + 330, 342, 342, 342, 606, 606, 606, 342, 343, 343, + 343, 343, 606, 606, 606, 343, 380, 380, 606, 606, + 606, 380, 381, 381, 606, 606, 606, 381, 397, 397, + 397, 606, 606, 606, 397, 398, 398, 398, 398, 606, + 606, 606, 398, 427, 427, 606, 606, 606, 427, 431, + + 606, 431, 431, 606, 606, 606, 431, 449, 449, 449, + 606, 606, 606, 449, 450, 450, 450, 450, 606, 606, + 606, 450, 483, 483, 606, 606, 606, 483, 484, 606, + 484, 484, 606, 606, 606, 484, 500, 500, 500, 606, + 606, 606, 500, 501, 501, 501, 606, 606, 606, 606, + 501, 512, 512, 606, 512, 512, 512, 606, 606, 512, + 512, 512, 606, 606, 512, 512, 512, 518, 518, 606, + 518, 518, 518, 606, 606, 518, 518, 518, 606, 606, + 518, 518, 518, 526, 526, 606, 606, 606, 526, 527, + 606, 527, 527, 606, 606, 606, 527, 543, 543, 606, + + 606, 606, 606, 543, 549, 549, 549, 549, 549, 549, + 549, 549, 549, 549, 549, 549, 549, 549, 549, 549, + 564, 564, 606, 606, 606, 564, 565, 606, 565, 565, + 606, 606, 606, 565, 582, 582, 606, 606, 606, 582, + 583, 606, 583, 606, 606, 606, 606, 583, 598, 598, + 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, + 598, 598, 598, 598, 13, 606, 606, 606, 606, 606, + 606, 606, 606, 606, 606, 606, 606, 606, 606, 606, + 606, 606, 606, 606, 606, 606, 606, 606, 606, 606, + 606, 606, 606, 606, 606, 606, 606, 606, 606, 606, + + 606, 606, 606, 606, 606, 606, 606, 606, 606, 606, + 606, 606, 606, 606, 606, 606, 606, 606, 606, 606, + 606, 606, 606, 606, 606, 606, 606, 606, 606, 606, + 606 + } ; + +static yyconst short int yy_chk[3732] = + { 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 2, 44, 3, 34, + 2, 103, 3, 4, 47, 20, 126, 4, 3, 34, + 103, 3, 52, 4, 44, 48, 4, 11, 11, 11, + 11, 126, 52, 20, 2, 2, 56, 47, 2, 74, + + 5, 5, 5, 48, 5, 2, 50, 3, 2, 3, + 5, 603, 4, 56, 4, 6, 6, 6, 20, 6, + 64, 64, 5, 5, 75, 6, 12, 12, 12, 12, + 3, 196, 68, 50, 11, 4, 70, 6, 6, 25, + 25, 72, 72, 25, 25, 196, 74, 5, 27, 27, + 27, 27, 27, 27, 27, 27, 68, 88, 124, 127, + 70, 25, 6, 7, 7, 7, 45, 7, 598, 75, + 124, 127, 129, 12, 28, 28, 28, 28, 28, 28, + 139, 139, 129, 43, 25, 43, 43, 43, 43, 43, + 43, 43, 43, 194, 45, 45, 77, 77, 45, 77, + + 88, 116, 123, 114, 114, 45, 116, 153, 45, 194, + 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, + 7, 7, 7, 7, 7, 7, 7, 7, 8, 8, + 8, 53, 8, 206, 53, 53, 53, 53, 53, 53, + 53, 53, 84, 84, 84, 84, 84, 84, 84, 84, + 114, 62, 62, 62, 153, 62, 154, 125, 206, 62, + 123, 62, 85, 85, 85, 85, 85, 85, 85, 85, + 143, 143, 202, 62, 62, 8, 8, 8, 8, 8, + 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, + 8, 8, 8, 9, 9, 9, 9, 9, 62, 125, + + 128, 154, 9, 9, 9, 86, 128, 202, 55, 55, + 136, 161, 55, 55, 185, 136, 9, 101, 101, 101, + 101, 101, 101, 86, 155, 155, 198, 185, 87, 587, + 55, 87, 87, 87, 87, 87, 87, 87, 87, 198, + 9, 10, 10, 10, 10, 10, 584, 171, 86, 284, + 10, 10, 10, 55, 161, 89, 171, 89, 89, 222, + 582, 89, 89, 222, 10, 89, 213, 95, 95, 95, + 95, 95, 95, 95, 95, 213, 92, 92, 89, 89, + 92, 92, 192, 195, 284, 195, 510, 192, 10, 19, + 99, 99, 99, 99, 99, 99, 99, 99, 92, 19, + + 95, 221, 19, 19, 19, 19, 19, 19, 19, 19, + 26, 191, 26, 26, 26, 26, 26, 26, 26, 26, + 26, 92, 237, 221, 26, 26, 26, 26, 26, 100, + 100, 100, 100, 100, 100, 100, 100, 131, 131, 131, + 131, 131, 131, 131, 131, 26, 510, 26, 26, 26, + 26, 26, 26, 32, 146, 238, 238, 146, 146, 32, + 568, 191, 32, 32, 146, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 146, 237, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 35, + 35, 35, 35, 35, 35, 35, 35, 35, 210, 210, + 210, 35, 35, 35, 35, 35, 109, 231, 240, 241, + 35, 109, 252, 231, 109, 241, 109, 117, 567, 150, + 150, 252, 239, 240, 35, 35, 35, 35, 35, 35, + 42, 42, 42, 42, 42, 293, 42, 42, 133, 133, + 42, 265, 133, 133, 293, 117, 117, 239, 281, 117, + 388, 388, 42, 42, 42, 46, 117, 163, 281, 117, + 133, 163, 323, 265, 239, 46, 150, 163, 46, 46, + + 46, 46, 46, 46, 46, 46, 275, 282, 323, 163, + 163, 275, 282, 133, 142, 142, 142, 142, 142, 142, + 142, 142, 159, 159, 159, 159, 159, 159, 159, 159, + 160, 160, 160, 160, 160, 160, 160, 160, 438, 438, + 46, 63, 201, 201, 201, 201, 201, 201, 201, 201, + 279, 63, 565, 280, 63, 63, 63, 63, 63, 63, + 63, 63, 79, 564, 79, 79, 79, 297, 79, 79, + 254, 254, 79, 197, 280, 201, 297, 197, 256, 256, + 254, 321, 322, 197, 79, 79, 79, 91, 256, 91, + 91, 91, 322, 91, 91, 197, 197, 91, 209, 209, + + 209, 209, 209, 209, 209, 209, 209, 298, 298, 91, + 91, 91, 94, 279, 94, 94, 94, 298, 94, 94, + 313, 383, 94, 162, 313, 162, 162, 452, 452, 162, + 162, 383, 321, 162, 94, 94, 94, 96, 96, 96, + 96, 96, 96, 96, 96, 162, 162, 162, 312, 96, + 96, 96, 96, 96, 205, 368, 205, 205, 205, 205, + 205, 205, 214, 214, 214, 214, 214, 214, 214, 214, + 312, 368, 96, 96, 96, 96, 96, 96, 104, 104, + 104, 104, 104, 104, 104, 104, 104, 316, 371, 205, + 104, 104, 104, 104, 104, 216, 216, 216, 216, 216, + + 216, 216, 216, 217, 217, 217, 217, 217, 217, 316, + 299, 299, 373, 104, 104, 104, 104, 104, 104, 135, + 299, 135, 135, 135, 560, 135, 135, 373, 219, 135, + 219, 219, 219, 219, 219, 219, 219, 219, 453, 453, + 371, 135, 135, 135, 164, 549, 164, 164, 164, 164, + 164, 164, 164, 164, 247, 247, 247, 247, 247, 247, + 247, 247, 247, 253, 253, 253, 253, 253, 253, 253, + 253, 255, 255, 255, 255, 255, 255, 255, 255, 164, + 165, 547, 165, 165, 165, 165, 165, 165, 165, 165, + 259, 259, 259, 259, 259, 259, 259, 259, 419, 419, + + 259, 261, 261, 261, 261, 261, 261, 261, 261, 262, + 262, 262, 262, 262, 262, 165, 166, 543, 166, 166, + 166, 166, 166, 166, 166, 166, 264, 317, 264, 264, + 264, 264, 264, 264, 264, 264, 301, 301, 283, 283, + 283, 283, 283, 283, 283, 283, 301, 456, 456, 317, + 419, 166, 167, 318, 167, 167, 167, 167, 167, 167, + 167, 167, 318, 324, 342, 343, 167, 167, 167, 167, + 167, 283, 324, 342, 343, 344, 344, 287, 372, 287, + 287, 287, 287, 287, 287, 344, 420, 372, 420, 167, + 167, 167, 167, 167, 167, 170, 170, 170, 170, 170, + + 170, 170, 170, 170, 345, 345, 539, 170, 170, 170, + 170, 170, 287, 294, 345, 294, 294, 294, 294, 294, + 294, 294, 294, 307, 307, 307, 307, 307, 307, 527, + 170, 170, 170, 170, 170, 170, 172, 172, 172, 172, + 172, 172, 172, 172, 172, 172, 491, 491, 526, 172, + 172, 172, 172, 172, 295, 376, 295, 295, 295, 295, + 295, 295, 295, 295, 300, 300, 300, 300, 300, 300, + 300, 300, 172, 172, 172, 172, 172, 172, 173, 173, + 173, 173, 173, 173, 173, 173, 347, 347, 511, 376, + 173, 173, 173, 173, 173, 296, 347, 296, 296, 296, + + 296, 296, 296, 296, 296, 306, 306, 306, 306, 306, + 306, 306, 306, 173, 173, 173, 173, 173, 173, 203, + 509, 203, 203, 203, 203, 203, 203, 203, 203, 304, + 304, 304, 304, 304, 304, 304, 304, 508, 309, 304, + 309, 309, 309, 309, 309, 309, 309, 309, 334, 334, + 334, 334, 334, 334, 203, 204, 507, 204, 204, 204, + 204, 204, 204, 204, 204, 331, 331, 331, 331, 331, + 331, 331, 331, 333, 333, 333, 333, 333, 333, 333, + 333, 337, 337, 337, 337, 337, 337, 337, 337, 358, + 204, 215, 215, 215, 215, 215, 215, 215, 215, 215, + + 215, 215, 502, 502, 506, 215, 215, 215, 215, 215, + 336, 358, 336, 336, 336, 336, 336, 336, 336, 336, + 341, 501, 341, 341, 341, 341, 341, 341, 215, 215, + 215, 215, 215, 215, 218, 218, 218, 218, 218, 218, + 218, 218, 218, 218, 397, 534, 534, 218, 218, 218, + 218, 218, 339, 397, 339, 339, 339, 339, 339, 339, + 339, 339, 346, 346, 346, 346, 346, 346, 346, 346, + 218, 218, 218, 218, 218, 218, 242, 484, 242, 242, + 242, 242, 242, 242, 242, 242, 340, 364, 340, 340, + 340, 340, 340, 340, 340, 340, 350, 350, 350, 350, + + 350, 350, 350, 350, 398, 669, 350, 551, 551, 364, + 669, 242, 243, 398, 243, 243, 243, 243, 243, 243, + 243, 243, 352, 352, 352, 352, 352, 352, 352, 352, + 353, 353, 353, 353, 353, 353, 355, 366, 355, 355, + 355, 355, 355, 355, 355, 355, 374, 243, 244, 449, + 244, 244, 244, 244, 244, 244, 244, 244, 449, 366, + 414, 385, 374, 382, 382, 382, 382, 382, 382, 382, + 382, 385, 450, 375, 375, 375, 375, 375, 375, 375, + 375, 450, 414, 244, 257, 257, 257, 257, 257, 257, + 257, 257, 257, 257, 257, 260, 260, 260, 260, 260, + + 260, 260, 260, 260, 260, 260, 375, 415, 457, 260, + 260, 260, 260, 260, 379, 379, 379, 379, 379, 379, + 379, 384, 384, 384, 384, 384, 384, 384, 384, 415, + 457, 483, 260, 260, 260, 260, 260, 260, 263, 263, + 263, 263, 263, 263, 263, 263, 263, 263, 379, 571, + 571, 263, 263, 263, 263, 263, 390, 390, 390, 390, + 390, 390, 390, 390, 391, 391, 391, 391, 391, 391, + 479, 399, 399, 465, 263, 263, 263, 263, 263, 263, + 285, 399, 285, 285, 285, 285, 285, 285, 285, 285, + 393, 432, 393, 393, 393, 393, 393, 393, 393, 393, + + 394, 432, 394, 394, 394, 394, 394, 394, 394, 394, + 460, 473, 619, 619, 468, 285, 286, 433, 286, 286, + 286, 286, 286, 286, 286, 286, 395, 433, 395, 395, + 395, 395, 395, 395, 395, 395, 396, 435, 396, 396, + 396, 396, 396, 396, 396, 396, 473, 435, 461, 459, + 458, 286, 292, 292, 292, 292, 292, 292, 292, 292, + 292, 400, 400, 445, 292, 292, 292, 292, 292, 468, + 461, 400, 401, 401, 401, 401, 401, 401, 401, 401, + 408, 408, 408, 408, 408, 408, 431, 292, 292, 292, + 292, 292, 292, 302, 302, 302, 302, 302, 302, 302, + + 302, 302, 302, 302, 305, 305, 305, 305, 305, 305, + 305, 305, 305, 305, 305, 402, 402, 463, 305, 305, + 305, 305, 305, 469, 477, 402, 405, 405, 405, 405, + 405, 405, 405, 405, 427, 503, 405, 422, 469, 463, + 418, 305, 305, 305, 305, 305, 305, 308, 308, 308, + 308, 308, 308, 308, 308, 308, 308, 503, 417, 477, + 308, 308, 308, 308, 308, 407, 407, 407, 407, 407, + 407, 407, 407, 409, 416, 409, 409, 409, 409, 409, + 409, 409, 409, 308, 308, 308, 308, 308, 308, 325, + 325, 325, 325, 325, 325, 325, 325, 325, 421, 428, + + 505, 428, 428, 428, 428, 428, 428, 428, 428, 434, + 434, 434, 434, 434, 434, 434, 434, 413, 421, 412, + 421, 421, 505, 325, 326, 326, 326, 326, 326, 326, + 326, 326, 326, 429, 466, 429, 429, 429, 429, 429, + 429, 429, 429, 421, 430, 485, 430, 430, 430, 430, + 430, 430, 430, 430, 466, 485, 466, 466, 326, 327, + 327, 327, 327, 327, 327, 327, 327, 327, 440, 440, + 440, 440, 440, 440, 440, 440, 441, 441, 441, 441, + 441, 441, 443, 500, 443, 443, 443, 443, 443, 443, + 443, 443, 500, 327, 332, 486, 332, 332, 332, 332, + + 332, 332, 332, 332, 332, 486, 411, 410, 332, 332, + 332, 332, 332, 444, 444, 444, 444, 444, 444, 444, + 444, 446, 381, 446, 446, 446, 446, 446, 446, 446, + 446, 332, 332, 332, 332, 332, 332, 335, 335, 335, + 335, 335, 335, 335, 335, 335, 380, 370, 369, 335, + 335, 335, 335, 335, 447, 488, 447, 447, 447, 447, + 447, 447, 447, 447, 448, 488, 448, 448, 448, 448, + 448, 448, 335, 335, 335, 335, 335, 335, 348, 348, + 348, 348, 348, 348, 348, 348, 348, 348, 348, 351, + 351, 351, 351, 351, 351, 351, 351, 351, 351, 351, + + 451, 451, 528, 351, 351, 351, 351, 351, 467, 467, + 451, 470, 528, 470, 470, 470, 471, 363, 471, 471, + 471, 467, 544, 362, 555, 589, 351, 351, 351, 351, + 351, 351, 354, 354, 354, 354, 354, 354, 354, 354, + 354, 361, 546, 572, 544, 354, 354, 354, 354, 354, + 472, 472, 472, 472, 472, 472, 472, 472, 470, 555, + 589, 360, 357, 471, 546, 572, 356, 338, 354, 354, + 354, 354, 354, 354, 377, 377, 377, 377, 377, 377, + 377, 377, 377, 472, 476, 330, 476, 476, 476, 476, + 476, 476, 478, 478, 478, 478, 478, 478, 478, 478, + + 482, 329, 482, 482, 482, 482, 482, 482, 377, 378, + 378, 378, 378, 378, 378, 378, 378, 378, 480, 476, + 480, 480, 480, 480, 480, 480, 480, 480, 481, 529, + 481, 481, 481, 481, 481, 481, 481, 481, 328, 529, + 320, 319, 315, 378, 386, 574, 386, 386, 386, 386, + 386, 386, 386, 386, 386, 389, 531, 389, 389, 389, + 389, 389, 389, 389, 389, 389, 531, 574, 585, 389, + 389, 389, 389, 389, 487, 487, 487, 487, 487, 487, + 487, 487, 493, 493, 493, 493, 493, 493, 493, 493, + 585, 314, 389, 389, 389, 389, 389, 389, 392, 392, + + 392, 392, 392, 392, 392, 392, 392, 311, 310, 291, + 392, 392, 392, 392, 392, 494, 494, 494, 494, 494, + 494, 496, 566, 496, 496, 496, 496, 496, 496, 496, + 496, 290, 566, 392, 392, 392, 392, 392, 392, 403, + 403, 403, 403, 403, 403, 403, 403, 403, 403, 403, + 406, 406, 406, 406, 406, 406, 406, 406, 406, 406, + 289, 288, 278, 277, 406, 406, 406, 406, 406, 497, + 497, 497, 497, 497, 497, 497, 497, 497, 498, 498, + 498, 498, 498, 498, 498, 498, 498, 406, 406, 406, + 406, 406, 406, 423, 276, 423, 423, 423, 423, 423, + + 423, 423, 423, 499, 499, 499, 499, 499, 499, 499, + 499, 499, 512, 274, 512, 512, 512, 575, 575, 513, + 273, 513, 513, 513, 272, 271, 270, 269, 423, 424, + 575, 424, 424, 424, 424, 424, 424, 424, 424, 514, + 268, 514, 514, 514, 515, 267, 515, 515, 515, 251, + 518, 250, 518, 518, 518, 249, 248, 246, 245, 512, + 236, 235, 234, 233, 424, 425, 513, 425, 425, 425, + 425, 425, 425, 425, 425, 516, 232, 229, 516, 516, + 516, 516, 516, 516, 516, 516, 514, 227, 226, 225, + 224, 515, 223, 220, 212, 517, 517, 518, 211, 517, + + 425, 426, 208, 426, 426, 426, 426, 426, 426, 426, + 426, 517, 517, 517, 519, 519, 207, 523, 519, 523, + 523, 523, 523, 523, 523, 523, 523, 200, 199, 193, + 519, 519, 519, 190, 189, 188, 426, 436, 187, 436, + 436, 436, 436, 436, 436, 436, 436, 436, 439, 186, + 439, 439, 439, 439, 439, 439, 439, 439, 439, 184, + 183, 182, 439, 439, 439, 439, 439, 524, 181, 524, + 524, 524, 524, 524, 524, 524, 524, 530, 530, 530, + 530, 530, 530, 530, 530, 439, 439, 439, 439, 439, + 439, 442, 442, 442, 442, 442, 442, 442, 442, 442, + + 180, 179, 178, 442, 442, 442, 442, 442, 525, 177, + 525, 525, 525, 525, 525, 525, 525, 525, 536, 536, + 536, 536, 536, 536, 536, 536, 442, 442, 442, 442, + 442, 442, 454, 454, 454, 454, 454, 454, 454, 454, + 454, 454, 474, 176, 474, 474, 474, 474, 474, 474, + 474, 474, 537, 537, 537, 537, 537, 537, 538, 175, + 538, 538, 538, 538, 538, 538, 538, 538, 540, 540, + 540, 540, 540, 540, 540, 540, 540, 474, 475, 169, + 475, 475, 475, 475, 475, 475, 475, 475, 541, 541, + 541, 541, 541, 541, 541, 541, 541, 542, 542, 542, + + 542, 542, 542, 542, 552, 552, 552, 552, 552, 552, + 552, 552, 168, 475, 489, 158, 489, 489, 489, 489, + 489, 489, 489, 489, 489, 492, 157, 492, 492, 492, + 492, 492, 492, 492, 492, 492, 156, 152, 151, 492, + 492, 492, 492, 492, 553, 553, 553, 553, 553, 553, + 553, 553, 554, 554, 554, 554, 554, 554, 554, 554, + 149, 145, 492, 492, 492, 492, 492, 492, 495, 495, + 495, 495, 495, 495, 495, 495, 138, 134, 132, 130, + 495, 495, 495, 495, 495, 554, 558, 122, 558, 558, + 558, 558, 558, 558, 559, 559, 559, 559, 559, 559, + + 559, 559, 121, 495, 495, 495, 495, 495, 495, 520, + 120, 520, 520, 520, 520, 520, 520, 520, 520, 119, + 561, 558, 561, 561, 561, 561, 561, 561, 561, 561, + 562, 118, 562, 562, 562, 562, 562, 562, 562, 562, + 113, 112, 111, 110, 520, 521, 108, 521, 521, 521, + 521, 521, 521, 521, 521, 563, 107, 563, 563, 563, + 563, 563, 563, 569, 106, 569, 569, 569, 569, 569, + 569, 569, 569, 596, 596, 596, 596, 596, 596, 102, + 521, 522, 98, 522, 522, 522, 522, 522, 522, 522, + 522, 579, 579, 579, 579, 579, 579, 579, 579, 580, + + 580, 580, 580, 580, 580, 580, 580, 581, 581, 581, + 581, 581, 581, 581, 581, 97, 522, 532, 93, 532, + 532, 532, 532, 532, 532, 532, 532, 532, 535, 90, + 535, 535, 535, 535, 535, 535, 535, 535, 82, 81, + 80, 78, 535, 535, 535, 535, 535, 73, 588, 588, + 588, 588, 588, 588, 588, 588, 592, 66, 592, 592, + 592, 592, 592, 592, 59, 535, 535, 535, 535, 535, + 535, 556, 54, 556, 556, 556, 556, 556, 556, 556, + 556, 588, 594, 594, 594, 594, 594, 594, 594, 594, + 51, 592, 595, 595, 595, 595, 595, 595, 595, 595, + + 49, 41, 40, 39, 38, 37, 556, 557, 36, 557, + 557, 557, 557, 557, 557, 557, 557, 33, 29, 23, + 600, 600, 600, 600, 600, 600, 600, 600, 601, 601, + 601, 601, 601, 601, 601, 601, 17, 15, 14, 13, + 0, 0, 557, 576, 0, 576, 576, 576, 576, 576, + 576, 576, 576, 600, 0, 0, 0, 0, 0, 0, + 0, 601, 602, 602, 602, 602, 602, 602, 602, 602, + 604, 604, 604, 604, 604, 604, 604, 604, 576, 577, + 0, 577, 577, 577, 577, 577, 577, 577, 577, 0, + 0, 0, 0, 0, 0, 602, 605, 605, 605, 605, + + 605, 605, 0, 604, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 577, 578, 0, 578, 578, 578, + 578, 578, 578, 578, 578, 0, 0, 0, 0, 605, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 578, 590, 0, 590, 590, 590, 590, 590, 590, 590, + 590, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 590, 591, 0, 591, + 591, 591, 591, 591, 591, 591, 591, 0, 0, 0, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 591, 607, 607, 607, 607, 607, 607, 607, + 607, 607, 607, 607, 607, 607, 607, 607, 607, 608, + 608, 608, 608, 608, 608, 608, 608, 608, 608, 608, + 608, 608, 608, 608, 608, 609, 609, 609, 609, 609, + 609, 609, 609, 609, 609, 609, 609, 609, 609, 609, + 609, 610, 610, 610, 610, 610, 610, 610, 610, 610, + 610, 610, 610, 610, 610, 610, 610, 611, 0, 0, + 0, 0, 0, 0, 0, 611, 611, 611, 0, 0, + + 611, 611, 611, 612, 612, 612, 612, 612, 612, 612, + 612, 612, 612, 612, 612, 612, 612, 612, 612, 613, + 0, 0, 0, 0, 613, 0, 0, 613, 613, 613, + 613, 0, 613, 613, 613, 614, 0, 0, 0, 0, + 0, 0, 0, 614, 614, 614, 0, 0, 614, 614, + 614, 615, 0, 0, 615, 615, 0, 615, 0, 615, + 615, 615, 0, 0, 615, 615, 615, 616, 616, 0, + 0, 0, 616, 617, 0, 0, 617, 617, 0, 617, + 0, 617, 617, 617, 0, 0, 617, 617, 617, 618, + 0, 0, 618, 618, 0, 618, 0, 618, 618, 618, + + 0, 618, 0, 618, 618, 620, 0, 0, 620, 0, + 0, 620, 0, 620, 620, 620, 620, 0, 620, 620, + 620, 621, 621, 621, 621, 621, 621, 621, 621, 621, + 621, 621, 621, 621, 621, 621, 621, 622, 622, 0, + 622, 0, 622, 622, 622, 622, 622, 622, 622, 622, + 622, 622, 622, 623, 623, 623, 623, 623, 623, 623, + 623, 623, 623, 623, 623, 623, 623, 623, 623, 624, + 624, 0, 624, 624, 624, 624, 624, 624, 624, 624, + 624, 624, 624, 624, 624, 625, 0, 0, 0, 0, + 625, 0, 0, 625, 625, 625, 0, 0, 625, 625, + + 625, 626, 0, 0, 626, 626, 0, 626, 0, 626, + 626, 626, 0, 0, 626, 626, 626, 627, 627, 0, + 0, 0, 627, 628, 628, 628, 0, 0, 0, 628, + 629, 0, 0, 629, 629, 0, 629, 0, 629, 629, + 629, 0, 0, 629, 629, 629, 630, 630, 630, 630, + 630, 630, 630, 630, 630, 630, 630, 630, 630, 630, + 630, 630, 631, 631, 0, 0, 0, 631, 632, 632, + 632, 0, 0, 0, 632, 633, 633, 0, 0, 0, + 633, 634, 634, 0, 0, 0, 634, 635, 635, 0, + 0, 0, 635, 636, 636, 636, 0, 0, 0, 636, + + 637, 637, 0, 0, 0, 637, 638, 638, 0, 0, + 0, 638, 639, 639, 0, 0, 0, 639, 640, 640, + 640, 0, 0, 0, 640, 641, 641, 641, 641, 0, + 0, 0, 641, 642, 642, 0, 0, 0, 642, 643, + 643, 0, 0, 0, 643, 644, 644, 0, 0, 0, + 644, 645, 645, 645, 0, 0, 0, 645, 646, 646, + 646, 646, 0, 0, 0, 646, 647, 647, 0, 0, + 0, 647, 648, 648, 0, 0, 0, 648, 649, 649, + 649, 0, 0, 0, 649, 650, 650, 650, 650, 0, + 0, 0, 650, 651, 651, 0, 0, 0, 651, 652, + + 0, 652, 652, 0, 0, 0, 652, 653, 653, 653, + 0, 0, 0, 653, 654, 654, 654, 654, 0, 0, + 0, 654, 655, 655, 0, 0, 0, 655, 656, 0, + 656, 656, 0, 0, 0, 656, 657, 657, 657, 0, + 0, 0, 657, 658, 658, 658, 0, 0, 0, 0, + 658, 659, 659, 0, 659, 659, 659, 0, 0, 659, + 659, 659, 0, 0, 659, 659, 659, 660, 660, 0, + 660, 660, 660, 0, 0, 660, 660, 660, 0, 0, + 660, 660, 660, 661, 661, 0, 0, 0, 661, 662, + 0, 662, 662, 0, 0, 0, 662, 663, 663, 0, + + 0, 0, 0, 663, 664, 664, 664, 664, 664, 664, + 664, 664, 664, 664, 664, 664, 664, 664, 664, 664, + 665, 665, 0, 0, 0, 665, 666, 0, 666, 666, + 0, 0, 0, 666, 667, 667, 0, 0, 0, 667, + 668, 0, 668, 0, 0, 0, 0, 668, 670, 670, + 670, 670, 670, 670, 670, 670, 670, 670, 670, 670, + 670, 670, 670, 670, 606, 606, 606, 606, 606, 606, + 606, 606, 606, 606, 606, 606, 606, 606, 606, 606, + 606, 606, 606, 606, 606, 606, 606, 606, 606, 606, + 606, 606, 606, 606, 606, 606, 606, 606, 606, 606, + + 606, 606, 606, 606, 606, 606, 606, 606, 606, 606, + 606, 606, 606, 606, 606, 606, 606, 606, 606, 606, + 606, 606, 606, 606, 606, 606, 606, 606, 606, 606, + 606 + } ; + +static yy_state_type yy_last_accepting_state; +static char *yy_last_accepting_cpos; + +/* The intent behind this definition is that it'll catch + * any uses of REJECT which flex missed. + */ +#define REJECT reject_used_but_not_detected +#define yymore() yymore_used_but_not_detected +#define YY_MORE_ADJ 0 +#define YY_RESTORE_YY_MORE_OFFSET +char *yytext; +#line 1 "toke.l" +#define INITIAL 0 +#line 2 "toke.l" +/* + * Copyright (c) 1996, 1998-2005, 2007-2011 + * Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ + +#include + +#include +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS) +# include +#endif /* HAVE_MALLOC_H && !STDC_HEADERS */ +#ifdef HAVE_DIRENT_H +# include +# define NAMLEN(dirent) strlen((dirent)->d_name) +#else +# define dirent direct +# define NAMLEN(dirent) (dirent)->d_namlen +# ifdef HAVE_SYS_NDIR_H +# include +# endif +# ifdef HAVE_SYS_DIR_H +# include +# endif +# ifdef HAVE_NDIR_H +# include +# endif +#endif +#include +#include +#include "sudoers.h" +#include "parse.h" +#include "toke.h" +#include + +extern YYSTYPE yylval; +extern int parse_error; +int sudolineno; +char *sudoers; + +static int continued, prev_state, sawspace; + +static int _push_include(char *, int); +static int pop_include(void); +static char *parse_include(char *); + +#ifdef TRACELEXER +static int sudoers_trace_print(const char *msg); +#else +# define sudoers_trace_print NULL +#endif +int (*trace_print)(const char *msg) = sudoers_trace_print; + +#define push_include(_p) (_push_include((_p), FALSE)) +#define push_includedir(_p) (_push_include((_p), TRUE)) +#define YY_NO_INPUT 1 +#define YY_NO_UNPUT 1 +#define GOTDEFS 1 + +#define GOTCMND 2 + +#define STARTDEFS 3 + +#define INDEFS 4 + +#define INSTR 5 + +#line 1511 "lex.yy.c" + +/* Macros after this point can all be overridden by user definitions in + * section 1. + */ + +#ifndef YY_SKIP_YYWRAP +#ifdef __cplusplus +extern "C" int yywrap YY_PROTO(( void )); +#else +extern int yywrap YY_PROTO(( void )); +#endif +#endif + +#ifndef YY_NO_UNPUT +static void yyunput YY_PROTO(( int c, char *buf_ptr )); +#endif + +#ifndef yytext_ptr +static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); +#endif + +#ifdef YY_NEED_STRLEN +static int yy_flex_strlen YY_PROTO(( yyconst char * )); +#endif + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput YY_PROTO(( void )); +#else +static int input YY_PROTO(( void )); +#endif +#endif + +#if defined(YY_STACK_USED) && YY_STACK_USED +static int yy_start_stack_ptr = 0; +static int yy_start_stack_depth = 0; +static int *yy_start_stack = 0; +#ifndef YY_NO_PUSH_STATE +static void yy_push_state YY_PROTO(( int new_state )); +#endif +#ifndef YY_NO_POP_STATE +static void yy_pop_state YY_PROTO(( void )); +#endif +#ifndef YY_NO_TOP_STATE +static int yy_top_state YY_PROTO(( void )); +#endif + +#else +#define YY_NO_PUSH_STATE 1 +#define YY_NO_POP_STATE 1 +#define YY_NO_TOP_STATE 1 +#endif + +#ifdef YY_MALLOC_DECL +YY_MALLOC_DECL +#else +#ifdef __STDC__ +#ifndef __cplusplus +#include +#endif +#else +/* Just try to get by without declaring the routines. This will fail + * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) + * or sizeof(void*) != sizeof(int). + */ +#endif +#endif + +/* Amount of stuff to slurp up with each read. */ +#ifndef YY_READ_BUF_SIZE +#define YY_READ_BUF_SIZE 8192 +#endif + +/* Copy whatever the last rule matched to the standard output. */ + +#ifndef ECHO +/* This used to be an fputs(), but since the string might contain NUL's, + * we now use fwrite(). + */ +#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) +#endif + +/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, + * is returned in "result". + */ +#ifndef YY_INPUT +#define YY_INPUT(buf,result,max_size) \ + if ( yy_current_buffer->yy_is_interactive ) \ + { \ + int c = '*', n; \ + for ( n = 0; n < max_size && \ + (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ + buf[n] = (char) c; \ + if ( c == '\n' ) \ + buf[n++] = (char) c; \ + if ( c == EOF && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); \ + result = n; \ + } \ + else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ + && ferror( yyin ) ) \ + YY_FATAL_ERROR( "input in flex scanner failed" ); +#endif + +/* No semi-colon after return; correct usage is to write "yyterminate();" - + * we don't want an extra ';' after the "return" because that will cause + * some compilers to complain about unreachable statements. + */ +#ifndef yyterminate +#define yyterminate() return YY_NULL +#endif + +/* Number of entries by which start-condition stack grows. */ +#ifndef YY_START_STACK_INCR +#define YY_START_STACK_INCR 25 +#endif + +/* Report a fatal error. */ +#ifndef YY_FATAL_ERROR +#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) +#endif + +/* Default declaration of generated scanner - a define so the user can + * easily add parameters. + */ +#ifndef YY_DECL +#define YY_DECL int yylex YY_PROTO(( void )) +#endif + +/* Code executed at the beginning of each rule, after yytext and yyleng + * have been set up. + */ +#ifndef YY_USER_ACTION +#define YY_USER_ACTION +#endif + +/* Code executed at the end of each rule. */ +#ifndef YY_BREAK +#define YY_BREAK break; +#endif + +#define YY_RULE_SETUP \ + if ( yyleng > 0 ) \ + yy_current_buffer->yy_at_bol = \ + (yytext[yyleng - 1] == '\n'); \ + YY_USER_ACTION + +YY_DECL + { + register yy_state_type yy_current_state; + register char *yy_cp, *yy_bp; + register int yy_act; + +#line 119 "toke.l" + +#line 1667 "lex.yy.c" + + if ( yy_init ) + { + yy_init = 0; + +#ifdef YY_USER_INIT + YY_USER_INIT; +#endif + + if ( ! yy_start ) + yy_start = 1; /* first start state */ + + if ( ! yyin ) + yyin = stdin; + + if ( ! yyout ) + yyout = stdout; + + if ( ! yy_current_buffer ) + yy_current_buffer = + yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_load_buffer_state(); + } + + while ( 1 ) /* loops until end-of-file is reached */ + { + yy_cp = yy_c_buf_p; + + /* Support of yytext. */ + *yy_cp = yy_hold_char; + + /* yy_bp points to the position in yy_ch_buf of the start of + * the current run. + */ + yy_bp = yy_cp; + + yy_current_state = yy_start; + yy_current_state += YY_AT_BOL(); +yy_match: + do + { + register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 607 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + ++yy_cp; + } + while ( yy_base[yy_current_state] != 3665 ); + +yy_find_action: + yy_act = yy_accept[yy_current_state]; + if ( yy_act == 0 ) + { /* have to back up */ + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + yy_act = yy_accept[yy_current_state]; + } + + YY_DO_BEFORE_ACTION; + + +do_action: /* This label is used only to access EOF actions. */ + + + switch ( yy_act ) + { /* beginning of action switch */ + case 0: /* must back up */ + /* undo the effects of YY_DO_BEFORE_ACTION */ + *yy_cp = yy_hold_char; + yy_cp = yy_last_accepting_cpos; + yy_current_state = yy_last_accepting_state; + goto yy_find_action; + +case 1: +YY_RULE_SETUP +#line 120 "toke.l" +{ + LEXTRACE(", "); + return ','; + } /* return ',' */ + YY_BREAK +case 2: +YY_RULE_SETUP +#line 125 "toke.l" +BEGIN STARTDEFS; + YY_BREAK +case 3: +YY_RULE_SETUP +#line 127 "toke.l" +{ + BEGIN INDEFS; + LEXTRACE("DEFVAR "); + if (!fill(yytext, yyleng)) + yyterminate(); + return DEFVAR; + } + YY_BREAK + +case 4: +YY_RULE_SETUP +#line 136 "toke.l" +{ + BEGIN STARTDEFS; + LEXTRACE(", "); + return ','; + } /* return ',' */ + YY_BREAK +case 5: +YY_RULE_SETUP +#line 142 "toke.l" +{ + LEXTRACE("= "); + return '='; + } /* return '=' */ + YY_BREAK +case 6: +YY_RULE_SETUP +#line 147 "toke.l" +{ + LEXTRACE("+= "); + return '+'; + } /* return '+' */ + YY_BREAK +case 7: +YY_RULE_SETUP +#line 152 "toke.l" +{ + LEXTRACE("-= "); + return '-'; + } /* return '-' */ + YY_BREAK +case 8: +YY_RULE_SETUP +#line 157 "toke.l" +{ + LEXTRACE("BEGINSTR "); + yylval.string = NULL; + prev_state = YY_START; + BEGIN INSTR; + } + YY_BREAK +case 9: +YY_RULE_SETUP +#line 164 "toke.l" +{ + LEXTRACE("WORD(2) "); + if (!fill(yytext, yyleng)) + yyterminate(); + return WORD; + } + YY_BREAK + + +case 10: +YY_RULE_SETUP +#line 173 "toke.l" +{ + /* Line continuation char followed by newline. */ + ++sudolineno; + continued = TRUE; + } + YY_BREAK +case 11: +YY_RULE_SETUP +#line 179 "toke.l" +{ + LEXTRACE("ENDSTR "); + BEGIN prev_state; + + if (yylval.string == NULL) { + LEXTRACE("ERROR "); /* empty string */ + return ERROR; + } + if (prev_state == INITIAL) { + switch (yylval.string[0]) { + case '%': + if (yylval.string[1] == '\0' || + (yylval.string[1] == ':' && + yylval.string[2] == '\0')) { + LEXTRACE("ERROR "); /* empty group */ + return ERROR; + } + LEXTRACE("USERGROUP "); + return USERGROUP; + case '+': + if (yylval.string[1] == '\0') { + LEXTRACE("ERROR "); /* empty netgroup */ + return ERROR; + } + LEXTRACE("NETGROUP "); + return NETGROUP; + } + } + LEXTRACE("WORD(4) "); + return WORD; + } + YY_BREAK +case 12: +YY_RULE_SETUP +#line 211 "toke.l" +{ + LEXTRACE("BACKSLASH "); + if (!append(yytext, yyleng)) + yyterminate(); + } + YY_BREAK +case 13: +YY_RULE_SETUP +#line 217 "toke.l" +{ + LEXTRACE("STRBODY "); + if (!append(yytext, yyleng)) + yyterminate(); + } + YY_BREAK + + +case 14: +YY_RULE_SETUP +#line 225 "toke.l" +{ + /* quoted fnmatch glob char, pass verbatim */ + LEXTRACE("QUOTEDCHAR "); + if (!fill_args(yytext, 2, sawspace)) + yyterminate(); + sawspace = FALSE; + } + YY_BREAK +case 15: +YY_RULE_SETUP +#line 233 "toke.l" +{ + /* quoted sudoers special char, strip backslash */ + LEXTRACE("QUOTEDCHAR "); + if (!fill_args(yytext + 1, 1, sawspace)) + yyterminate(); + sawspace = FALSE; + } + YY_BREAK +case 16: +YY_RULE_SETUP +#line 241 "toke.l" +{ + BEGIN INITIAL; + yyless(0); + return COMMAND; + } /* end of command line args */ + YY_BREAK +case 17: +YY_RULE_SETUP +#line 247 "toke.l" +{ + LEXTRACE("ARG "); + if (!fill_args(yytext, yyleng, sawspace)) + yyterminate(); + sawspace = FALSE; + } /* a command line arg */ + YY_BREAK + +case 18: +YY_RULE_SETUP +#line 255 "toke.l" +{ + char *path; + + if (continued) { + LEXTRACE("ERROR "); + return ERROR; + } + + if ((path = parse_include(yytext)) == NULL) + yyterminate(); + + LEXTRACE("INCLUDE\n"); + + /* Push current buffer and switch to include file */ + if (!push_include(path)) + yyterminate(); + } + YY_BREAK +case 19: +YY_RULE_SETUP +#line 273 "toke.l" +{ + char *path; + + if (continued) { + LEXTRACE("ERROR "); + return ERROR; + } + + if ((path = parse_include(yytext)) == NULL) + yyterminate(); + + LEXTRACE("INCLUDEDIR\n"); + + /* + * Push current buffer and switch to include file. + * We simply ignore empty directories. + */ + if (!push_includedir(path) && parse_error) + yyterminate(); + } + YY_BREAK +case 20: +YY_RULE_SETUP +#line 294 "toke.l" +{ + char deftype; + int n; + + if (continued) { + LEXTRACE("ERROR "); + return ERROR; + } + + for (n = 0; isblank((unsigned char)yytext[n]); n++) + continue; + n += sizeof("Defaults") - 1; + if ((deftype = yytext[n++]) != '\0') { + while (isblank((unsigned char)yytext[n])) + n++; + } + BEGIN GOTDEFS; + switch (deftype) { + case ':': + yyless(n); + LEXTRACE("DEFAULTS_USER "); + return DEFAULTS_USER; + case '>': + yyless(n); + LEXTRACE("DEFAULTS_RUNAS "); + return DEFAULTS_RUNAS; + case '@': + yyless(n); + LEXTRACE("DEFAULTS_HOST "); + return DEFAULTS_HOST; + case '!': + yyless(n); + LEXTRACE("DEFAULTS_CMND "); + return DEFAULTS_CMND; + default: + LEXTRACE("DEFAULTS "); + return DEFAULTS; + } + } + YY_BREAK +case 21: +YY_RULE_SETUP +#line 334 "toke.l" +{ + int n; + + if (continued) { + LEXTRACE("ERROR "); + return ERROR; + } + + for (n = 0; isblank((unsigned char)yytext[n]); n++) + continue; + switch (yytext[n]) { + case 'H': + LEXTRACE("HOSTALIAS "); + return HOSTALIAS; + case 'C': + LEXTRACE("CMNDALIAS "); + return CMNDALIAS; + case 'U': + LEXTRACE("USERALIAS "); + return USERALIAS; + case 'R': + LEXTRACE("RUNASALIAS "); + return RUNASALIAS; + } + } + YY_BREAK +case 22: +YY_RULE_SETUP +#line 360 "toke.l" +{ + /* cmnd does not require passwd for this user */ + LEXTRACE("NOPASSWD "); + return NOPASSWD; + } + YY_BREAK +case 23: +YY_RULE_SETUP +#line 366 "toke.l" +{ + /* cmnd requires passwd for this user */ + LEXTRACE("PASSWD "); + return PASSWD; + } + YY_BREAK +case 24: +YY_RULE_SETUP +#line 372 "toke.l" +{ + LEXTRACE("NOEXEC "); + return NOEXEC; + } + YY_BREAK +case 25: +YY_RULE_SETUP +#line 377 "toke.l" +{ + LEXTRACE("EXEC "); + return EXEC; + } + YY_BREAK +case 26: +YY_RULE_SETUP +#line 382 "toke.l" +{ + LEXTRACE("SETENV "); + return SETENV; + } + YY_BREAK +case 27: +YY_RULE_SETUP +#line 387 "toke.l" +{ + LEXTRACE("NOSETENV "); + return NOSETENV; + } + YY_BREAK +case 28: +YY_RULE_SETUP +#line 392 "toke.l" +{ + LEXTRACE("LOG_OUTPUT "); + return LOG_OUTPUT; + } + YY_BREAK +case 29: +YY_RULE_SETUP +#line 397 "toke.l" +{ + LEXTRACE("NOLOG_OUTPUT "); + return NOLOG_OUTPUT; + } + YY_BREAK +case 30: +YY_RULE_SETUP +#line 402 "toke.l" +{ + LEXTRACE("LOG_INPUT "); + return LOG_INPUT; + } + YY_BREAK +case 31: +YY_RULE_SETUP +#line 407 "toke.l" +{ + LEXTRACE("NOLOG_INPUT "); + return NOLOG_INPUT; + } + YY_BREAK +case 32: +YY_RULE_SETUP +#line 412 "toke.l" +{ + /* empty group or netgroup */ + LEXTRACE("ERROR "); + return ERROR; + } + YY_BREAK +case 33: +YY_RULE_SETUP +#line 418 "toke.l" +{ + /* netgroup */ + if (!fill(yytext, yyleng)) + yyterminate(); + LEXTRACE("NETGROUP "); + return NETGROUP; + } + YY_BREAK +case 34: +YY_RULE_SETUP +#line 426 "toke.l" +{ + /* group */ + if (!fill(yytext, yyleng)) + yyterminate(); + LEXTRACE("USERGROUP "); + return USERGROUP; + } + YY_BREAK +case 35: +YY_RULE_SETUP +#line 434 "toke.l" +{ + if (!fill(yytext, yyleng)) + yyterminate(); + LEXTRACE("NTWKADDR "); + return NTWKADDR; + } + YY_BREAK +case 36: +YY_RULE_SETUP +#line 441 "toke.l" +{ + if (!fill(yytext, yyleng)) + yyterminate(); + LEXTRACE("NTWKADDR "); + return NTWKADDR; + } + YY_BREAK +case 37: +YY_RULE_SETUP +#line 448 "toke.l" +{ + if (!ipv6_valid(yytext)) { + LEXTRACE("ERROR "); + return ERROR; + } + if (!fill(yytext, yyleng)) + yyterminate(); + LEXTRACE("NTWKADDR "); + return NTWKADDR; + } + YY_BREAK +case 38: +YY_RULE_SETUP +#line 459 "toke.l" +{ + if (!ipv6_valid(yytext)) { + LEXTRACE("ERROR "); + return ERROR; + } + if (!fill(yytext, yyleng)) + yyterminate(); + LEXTRACE("NTWKADDR "); + return NTWKADDR; + } + YY_BREAK +case 39: +YY_RULE_SETUP +#line 470 "toke.l" +{ + LEXTRACE("ALL "); + return ALL; + + } + YY_BREAK +case 40: +YY_RULE_SETUP +#line 476 "toke.l" +{ +#ifdef HAVE_SELINUX + LEXTRACE("ROLE "); + return ROLE; +#else + goto got_alias; +#endif + } + YY_BREAK +case 41: +YY_RULE_SETUP +#line 485 "toke.l" +{ +#ifdef HAVE_SELINUX + LEXTRACE("TYPE "); + return TYPE; +#else + goto got_alias; +#endif + } + YY_BREAK +case 42: +YY_RULE_SETUP +#line 494 "toke.l" +{ + got_alias: + if (!fill(yytext, yyleng)) + yyterminate(); + LEXTRACE("ALIAS "); + return ALIAS; + } + YY_BREAK +case 43: +YY_RULE_SETUP +#line 502 "toke.l" +{ + /* no command args allowed for Defaults!/path */ + if (!fill_cmnd(yytext, yyleng)) + yyterminate(); + LEXTRACE("COMMAND "); + return COMMAND; + } + YY_BREAK +case 44: +YY_RULE_SETUP +#line 510 "toke.l" +{ + BEGIN GOTCMND; + LEXTRACE("COMMAND "); + if (!fill_cmnd(yytext, yyleng)) + yyterminate(); + } /* sudo -e */ + YY_BREAK +case 45: +YY_RULE_SETUP +#line 517 "toke.l" +{ + /* directories can't have args... */ + if (yytext[yyleng - 1] == '/') { + LEXTRACE("COMMAND "); + if (!fill_cmnd(yytext, yyleng)) + yyterminate(); + return COMMAND; + } else { + BEGIN GOTCMND; + LEXTRACE("COMMAND "); + if (!fill_cmnd(yytext, yyleng)) + yyterminate(); + } + } /* a pathname */ + YY_BREAK +case 46: +YY_RULE_SETUP +#line 532 "toke.l" +{ + LEXTRACE("BEGINSTR "); + yylval.string = NULL; + prev_state = YY_START; + BEGIN INSTR; + } + YY_BREAK +case 47: +YY_RULE_SETUP +#line 539 "toke.l" +{ + /* a word */ + if (!fill(yytext, yyleng)) + yyterminate(); + LEXTRACE("WORD(5) "); + return WORD; + } + YY_BREAK +case 48: +YY_RULE_SETUP +#line 547 "toke.l" +{ + LEXTRACE("( "); + return '('; + } + YY_BREAK +case 49: +YY_RULE_SETUP +#line 552 "toke.l" +{ + LEXTRACE(") "); + return ')'; + } + YY_BREAK +case 50: +YY_RULE_SETUP +#line 557 "toke.l" +{ + LEXTRACE(", "); + return ','; + } /* return ',' */ + YY_BREAK +case 51: +YY_RULE_SETUP +#line 562 "toke.l" +{ + LEXTRACE("= "); + return '='; + } /* return '=' */ + YY_BREAK +case 52: +YY_RULE_SETUP +#line 567 "toke.l" +{ + LEXTRACE(": "); + return ':'; + } /* return ':' */ + YY_BREAK +case 53: +YY_RULE_SETUP +#line 572 "toke.l" +{ + if (yyleng & 1) { + LEXTRACE("!"); + return '!'; /* return '!' */ + } + } + YY_BREAK +case 54: +YY_RULE_SETUP +#line 579 "toke.l" +{ + if (YY_START == INSTR) { + LEXTRACE("ERROR "); + return ERROR; /* line break in string */ + } + BEGIN INITIAL; + ++sudolineno; + continued = FALSE; + LEXTRACE("\n"); + return COMMENT; + } /* return newline */ + YY_BREAK +case 55: +YY_RULE_SETUP +#line 591 "toke.l" +{ /* throw away space/tabs */ + sawspace = TRUE; /* but remember for fill_args */ + } + YY_BREAK +case 56: +YY_RULE_SETUP +#line 595 "toke.l" +{ + sawspace = TRUE; /* remember for fill_args */ + ++sudolineno; + continued = TRUE; + } /* throw away EOL after \ */ + YY_BREAK +case 57: +YY_RULE_SETUP +#line 601 "toke.l" +{ + BEGIN INITIAL; + ++sudolineno; + continued = FALSE; + LEXTRACE("#\n"); + return COMMENT; + } /* comment, not uid/gid */ + YY_BREAK +case 58: +YY_RULE_SETUP +#line 609 "toke.l" +{ + LEXTRACE("ERROR "); + return ERROR; + } /* parse error */ + YY_BREAK +case YY_STATE_EOF(INITIAL): +case YY_STATE_EOF(GOTDEFS): +case YY_STATE_EOF(GOTCMND): +case YY_STATE_EOF(STARTDEFS): +case YY_STATE_EOF(INDEFS): +case YY_STATE_EOF(INSTR): +#line 614 "toke.l" +{ + if (YY_START != INITIAL) { + BEGIN INITIAL; + LEXTRACE("ERROR "); + return ERROR; + } + if (!pop_include()) + yyterminate(); + } + YY_BREAK +case 59: +YY_RULE_SETUP +#line 624 "toke.l" +ECHO; + YY_BREAK +#line 2441 "lex.yy.c" + + case YY_END_OF_BUFFER: + { + /* Amount of text matched not including the EOB char. */ + int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; + + /* Undo the effects of YY_DO_BEFORE_ACTION. */ + *yy_cp = yy_hold_char; + YY_RESTORE_YY_MORE_OFFSET + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) + { + /* We're scanning a new file or input source. It's + * possible that this happened because the user + * just pointed yyin at a new source and called + * yylex(). If so, then we have to assure + * consistency between yy_current_buffer and our + * globals. Here is the right place to do so, because + * this is the first action (other than possibly a + * back-up) that will match for the new input source. + */ + yy_n_chars = yy_current_buffer->yy_n_chars; + yy_current_buffer->yy_input_file = yyin; + yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; + } + + /* Note that here we test for yy_c_buf_p "<=" to the position + * of the first EOB in the buffer, since yy_c_buf_p will + * already have been incremented past the NUL character + * (since all states make transitions on EOB to the + * end-of-buffer state). Contrast this with the test + * in input(). + */ + if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + { /* This was really a NUL. */ + yy_state_type yy_next_state; + + yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + /* Okay, we're now positioned to make the NUL + * transition. We couldn't have + * yy_get_previous_state() go ahead and do it + * for us because it doesn't know how to deal + * with the possibility of jamming (and we don't + * want to build jamming into it because then it + * will run more slowly). + */ + + yy_next_state = yy_try_NUL_trans( yy_current_state ); + + yy_bp = yytext_ptr + YY_MORE_ADJ; + + if ( yy_next_state ) + { + /* Consume the NUL. */ + yy_cp = ++yy_c_buf_p; + yy_current_state = yy_next_state; + goto yy_match; + } + + else + { + yy_cp = yy_c_buf_p; + goto yy_find_action; + } + } + + else switch ( yy_get_next_buffer() ) + { + case EOB_ACT_END_OF_FILE: + { + yy_did_buffer_switch_on_eof = 0; + + if ( yywrap() ) + { + /* Note: because we've taken care in + * yy_get_next_buffer() to have set up + * yytext, we can now set up + * yy_c_buf_p so that if some total + * hoser (like flex itself) wants to + * call the scanner after we return the + * YY_NULL, it'll still work - another + * YY_NULL will get returned. + */ + yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; + + yy_act = YY_STATE_EOF(YY_START); + goto do_action; + } + + else + { + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; + } + break; + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = + yytext_ptr + yy_amount_of_matched_text; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_match; + + case EOB_ACT_LAST_MATCH: + yy_c_buf_p = + &yy_current_buffer->yy_ch_buf[yy_n_chars]; + + yy_current_state = yy_get_previous_state(); + + yy_cp = yy_c_buf_p; + yy_bp = yytext_ptr + YY_MORE_ADJ; + goto yy_find_action; + } + break; + } + + default: + YY_FATAL_ERROR( + "fatal flex scanner internal error--no action found" ); + } /* end of action switch */ + } /* end of scanning one token */ + } /* end of yylex */ + + +/* yy_get_next_buffer - try to read in a new buffer + * + * Returns a code representing an action: + * EOB_ACT_LAST_MATCH - + * EOB_ACT_CONTINUE_SCAN - continue scanning from current position + * EOB_ACT_END_OF_FILE - end of file + */ + +static int yy_get_next_buffer() + { + register char *dest = yy_current_buffer->yy_ch_buf; + register char *source = yytext_ptr; + register int number_to_move, i; + int ret_val; + + if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) + YY_FATAL_ERROR( + "fatal flex scanner internal error--end of buffer missed" ); + + if ( yy_current_buffer->yy_fill_buffer == 0 ) + { /* Don't try to fill the buffer, so this is an EOF. */ + if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) + { + /* We matched a single character, the EOB, so + * treat this as a final EOF. + */ + return EOB_ACT_END_OF_FILE; + } + + else + { + /* We matched some text prior to the EOB, first + * process it. + */ + return EOB_ACT_LAST_MATCH; + } + } + + /* Try to read more data. */ + + /* First move last chars to start of buffer. */ + number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; + + for ( i = 0; i < number_to_move; ++i ) + *(dest++) = *(source++); + + if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) + /* don't do the read, it's not guaranteed to return an EOF, + * just force an EOF + */ + yy_current_buffer->yy_n_chars = yy_n_chars = 0; + + else + { + int num_to_read = + yy_current_buffer->yy_buf_size - number_to_move - 1; + + while ( num_to_read <= 0 ) + { /* Not enough room in the buffer - grow it. */ +#ifdef YY_USES_REJECT + YY_FATAL_ERROR( +"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); +#else + + /* just a shorter name for the current buffer */ + YY_BUFFER_STATE b = yy_current_buffer; + + int yy_c_buf_p_offset = + (int) (yy_c_buf_p - b->yy_ch_buf); + + if ( b->yy_is_our_buffer ) + { + int new_size = b->yy_buf_size * 2; + + if ( new_size <= 0 ) + b->yy_buf_size += b->yy_buf_size / 8; + else + b->yy_buf_size *= 2; + + b->yy_ch_buf = (char *) + /* Include room in for 2 EOB chars. */ + yy_flex_realloc( (void *) b->yy_ch_buf, + b->yy_buf_size + 2 ); + } + else + /* Can't grow it, we don't own it. */ + b->yy_ch_buf = 0; + + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( + "fatal error - scanner input buffer overflow" ); + + yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; + + num_to_read = yy_current_buffer->yy_buf_size - + number_to_move - 1; +#endif + } + + if ( num_to_read > YY_READ_BUF_SIZE ) + num_to_read = YY_READ_BUF_SIZE; + + /* Read in more data. */ + YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), + yy_n_chars, num_to_read ); + + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + if ( yy_n_chars == 0 ) + { + if ( number_to_move == YY_MORE_ADJ ) + { + ret_val = EOB_ACT_END_OF_FILE; + yyrestart( yyin ); + } + + else + { + ret_val = EOB_ACT_LAST_MATCH; + yy_current_buffer->yy_buffer_status = + YY_BUFFER_EOF_PENDING; + } + } + + else + ret_val = EOB_ACT_CONTINUE_SCAN; + + yy_n_chars += number_to_move; + yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; + yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; + + yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; + + return ret_val; + } + + +/* yy_get_previous_state - get the state just before the EOB char was reached */ + +static yy_state_type yy_get_previous_state() + { + register yy_state_type yy_current_state; + register char *yy_cp; + + yy_current_state = yy_start; + yy_current_state += YY_AT_BOL(); + + for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) + { + register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 607 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + } + + return yy_current_state; + } + + +/* yy_try_NUL_trans - try to make a transition on the NUL character + * + * synopsis + * next_state = yy_try_NUL_trans( current_state ); + */ + +#ifdef YY_USE_PROTOS +static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) +#else +static yy_state_type yy_try_NUL_trans( yy_current_state ) +yy_state_type yy_current_state; +#endif + { + register int yy_is_jam; + register char *yy_cp = yy_c_buf_p; + + register YY_CHAR yy_c = 1; + if ( yy_accept[yy_current_state] ) + { + yy_last_accepting_state = yy_current_state; + yy_last_accepting_cpos = yy_cp; + } + while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) + { + yy_current_state = (int) yy_def[yy_current_state]; + if ( yy_current_state >= 607 ) + yy_c = yy_meta[(unsigned int) yy_c]; + } + yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; + yy_is_jam = (yy_current_state == 606); + + return yy_is_jam ? 0 : yy_current_state; + } + + +#ifndef YY_NO_UNPUT +#ifdef YY_USE_PROTOS +static void yyunput( int c, register char *yy_bp ) +#else +static void yyunput( c, yy_bp ) +int c; +register char *yy_bp; +#endif + { + register char *yy_cp = yy_c_buf_p; + + /* undo effects of setting up yytext */ + *yy_cp = yy_hold_char; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + { /* need to shift things up to make room */ + /* +2 for EOB chars. */ + register int number_to_move = yy_n_chars + 2; + register char *dest = &yy_current_buffer->yy_ch_buf[ + yy_current_buffer->yy_buf_size + 2]; + register char *source = + &yy_current_buffer->yy_ch_buf[number_to_move]; + + while ( source > yy_current_buffer->yy_ch_buf ) + *--dest = *--source; + + yy_cp += (int) (dest - source); + yy_bp += (int) (dest - source); + yy_current_buffer->yy_n_chars = + yy_n_chars = yy_current_buffer->yy_buf_size; + + if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) + YY_FATAL_ERROR( "flex scanner push-back overflow" ); + } + + *--yy_cp = (char) c; + + + yytext_ptr = yy_bp; + yy_hold_char = *yy_cp; + yy_c_buf_p = yy_cp; + } +#endif /* ifndef YY_NO_UNPUT */ + + +#ifndef YY_NO_INPUT +#ifdef __cplusplus +static int yyinput() +#else +static int input() +#endif + { + int c; + + *yy_c_buf_p = yy_hold_char; + + if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) + { + /* yy_c_buf_p now points to the character we want to return. + * If this occurs *before* the EOB characters, then it's a + * valid NUL; if not, then we've hit the end of the buffer. + */ + if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) + /* This was really a NUL. */ + *yy_c_buf_p = '\0'; + + else + { /* need more input */ + int offset = yy_c_buf_p - yytext_ptr; + ++yy_c_buf_p; + + switch ( yy_get_next_buffer() ) + { + case EOB_ACT_LAST_MATCH: + /* This happens because yy_g_n_b() + * sees that we've accumulated a + * token and flags that we need to + * try matching the token before + * proceeding. But for input(), + * there's no matching to consider. + * So convert the EOB_ACT_LAST_MATCH + * to EOB_ACT_END_OF_FILE. + */ + + /* Reset buffer status. */ + yyrestart( yyin ); + + /* fall through */ + + case EOB_ACT_END_OF_FILE: + { + if ( yywrap() ) + return EOF; + + if ( ! yy_did_buffer_switch_on_eof ) + YY_NEW_FILE; +#ifdef __cplusplus + return yyinput(); +#else + return input(); +#endif + } + + case EOB_ACT_CONTINUE_SCAN: + yy_c_buf_p = yytext_ptr + offset; + break; + } + } + } + + c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ + *yy_c_buf_p = '\0'; /* preserve yytext */ + yy_hold_char = *++yy_c_buf_p; + + yy_current_buffer->yy_at_bol = (c == '\n'); + + return c; + } +#endif /* ifndef YY_NO_INPUT */ + + +#ifdef YY_USE_PROTOS +void yyrestart( FILE *input_file ) +#else +void yyrestart( input_file ) +FILE *input_file; +#endif + { + if ( ! yy_current_buffer ) + yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); + + yy_init_buffer( yy_current_buffer, input_file ); + yy_load_buffer_state(); + } + + +#ifdef YY_USE_PROTOS +void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) +#else +void yy_switch_to_buffer( new_buffer ) +YY_BUFFER_STATE new_buffer; +#endif + { + if ( yy_current_buffer == new_buffer ) + return; + + if ( yy_current_buffer ) + { + /* Flush out information for old buffer. */ + *yy_c_buf_p = yy_hold_char; + yy_current_buffer->yy_buf_pos = yy_c_buf_p; + yy_current_buffer->yy_n_chars = yy_n_chars; + } + + yy_current_buffer = new_buffer; + yy_load_buffer_state(); + + /* We don't actually know whether we did this switch during + * EOF (yywrap()) processing, but the only time this flag + * is looked at is after yywrap() is called, so it's safe + * to go ahead and always set it. + */ + yy_did_buffer_switch_on_eof = 1; + } + + +#ifdef YY_USE_PROTOS +void yy_load_buffer_state( void ) +#else +void yy_load_buffer_state() +#endif + { + yy_n_chars = yy_current_buffer->yy_n_chars; + yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; + yyin = yy_current_buffer->yy_input_file; + yy_hold_char = *yy_c_buf_p; + } + + +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) +#else +YY_BUFFER_STATE yy_create_buffer( file, size ) +FILE *file; +int size; +#endif + { + YY_BUFFER_STATE b; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_buf_size = size; + + /* yy_ch_buf has to be 2 characters longer than the size given because + * we need to put in 2 end-of-buffer characters. + */ + b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); + if ( ! b->yy_ch_buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); + + b->yy_is_our_buffer = 1; + + yy_init_buffer( b, file ); + + return b; + } + + +#ifdef YY_USE_PROTOS +void yy_delete_buffer( YY_BUFFER_STATE b ) +#else +void yy_delete_buffer( b ) +YY_BUFFER_STATE b; +#endif + { + if ( ! b ) + return; + + if ( b == yy_current_buffer ) + yy_current_buffer = (YY_BUFFER_STATE) 0; + + if ( b->yy_is_our_buffer ) + yy_flex_free( (void *) b->yy_ch_buf ); + + yy_flex_free( (void *) b ); + } + + +#ifndef YY_ALWAYS_INTERACTIVE +#ifndef YY_NEVER_INTERACTIVE +#include +#endif +#endif + +#ifdef YY_USE_PROTOS +void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) +#else +void yy_init_buffer( b, file ) +YY_BUFFER_STATE b; +FILE *file; +#endif + + + { + int oerrno = errno; + + yy_flush_buffer( b ); + + b->yy_input_file = file; + b->yy_fill_buffer = 1; + +#if defined(YY_ALWAYS_INTERACTIVE) && YY_ALWAYS_INTERACTIVE + b->yy_is_interactive = 1; +#else +#if defined(YY_NEVER_INTERACTIVE) && YY_NEVER_INTERACTIVE + b->yy_is_interactive = 0; +#else + b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; +#endif +#endif + errno = oerrno; + } + + +#ifdef YY_USE_PROTOS +void yy_flush_buffer( YY_BUFFER_STATE b ) +#else +void yy_flush_buffer( b ) +YY_BUFFER_STATE b; +#endif + + { + if ( ! b ) + return; + + b->yy_n_chars = 0; + + /* We always need two end-of-buffer characters. The first causes + * a transition to the end-of-buffer state. The second causes + * a jam in that state. + */ + b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; + b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; + + b->yy_buf_pos = &b->yy_ch_buf[0]; + + b->yy_at_bol = 1; + b->yy_buffer_status = YY_BUFFER_NEW; + + if ( b == yy_current_buffer ) + yy_load_buffer_state(); + } + + +#ifndef YY_NO_SCAN_BUFFER +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) +#else +YY_BUFFER_STATE yy_scan_buffer( base, size ) +char *base; +yy_size_t size; +#endif + { + YY_BUFFER_STATE b; + + if ( size < 2 || + base[size-2] != YY_END_OF_BUFFER_CHAR || + base[size-1] != YY_END_OF_BUFFER_CHAR ) + /* They forgot to leave room for the EOB's. */ + return 0; + + b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); + if ( ! b ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); + + b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ + b->yy_buf_pos = b->yy_ch_buf = base; + b->yy_is_our_buffer = 0; + b->yy_input_file = 0; + b->yy_n_chars = b->yy_buf_size; + b->yy_is_interactive = 0; + b->yy_at_bol = 1; + b->yy_fill_buffer = 0; + b->yy_buffer_status = YY_BUFFER_NEW; + + yy_switch_to_buffer( b ); + + return b; + } +#endif + + +#ifndef YY_NO_SCAN_STRING +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) +#else +YY_BUFFER_STATE yy_scan_string( yy_str ) +yyconst char *yy_str; +#endif + { + int len; + for ( len = 0; yy_str[len]; ++len ) + ; + + return yy_scan_bytes( yy_str, len ); + } +#endif + + +#ifndef YY_NO_SCAN_BYTES +#ifdef YY_USE_PROTOS +YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) +#else +YY_BUFFER_STATE yy_scan_bytes( bytes, len ) +yyconst char *bytes; +int len; +#endif + { + YY_BUFFER_STATE b; + char *buf; + yy_size_t n; + int i; + + /* Get memory for full buffer, including space for trailing EOB's. */ + n = len + 2; + buf = (char *) yy_flex_alloc( n ); + if ( ! buf ) + YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); + + for ( i = 0; i < len; ++i ) + buf[i] = bytes[i]; + + buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; + + b = yy_scan_buffer( buf, n ); + if ( ! b ) + YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); + + /* It's okay to grow etc. this buffer, and we should throw it + * away when we're done. + */ + b->yy_is_our_buffer = 1; + + return b; + } +#endif + + +#ifndef YY_NO_PUSH_STATE +#ifdef YY_USE_PROTOS +static void yy_push_state( int new_state ) +#else +static void yy_push_state( new_state ) +int new_state; +#endif + { + if ( yy_start_stack_ptr >= yy_start_stack_depth ) + { + yy_size_t new_size; + + yy_start_stack_depth += YY_START_STACK_INCR; + new_size = yy_start_stack_depth * sizeof( int ); + + if ( ! yy_start_stack ) + yy_start_stack = (int *) yy_flex_alloc( new_size ); + + else + yy_start_stack = (int *) yy_flex_realloc( + (void *) yy_start_stack, new_size ); + + if ( ! yy_start_stack ) + YY_FATAL_ERROR( + "out of memory expanding start-condition stack" ); + } + + yy_start_stack[yy_start_stack_ptr++] = YY_START; + + BEGIN(new_state); + } +#endif + + +#ifndef YY_NO_POP_STATE +static void yy_pop_state() + { + if ( --yy_start_stack_ptr < 0 ) + YY_FATAL_ERROR( "start-condition stack underflow" ); + + BEGIN(yy_start_stack[yy_start_stack_ptr]); + } +#endif + + +#ifndef YY_NO_TOP_STATE +static int yy_top_state() + { + return yy_start_stack[yy_start_stack_ptr - 1]; + } +#endif + +#ifndef YY_EXIT_FAILURE +#define YY_EXIT_FAILURE 2 +#endif + +#ifdef YY_USE_PROTOS +static void yy_fatal_error( yyconst char msg[] ) +#else +static void yy_fatal_error( msg ) +char msg[]; +#endif + { + (void) fprintf( stderr, "%s\n", msg ); + exit( YY_EXIT_FAILURE ); + } + + + +/* Redefine yyless() so it works in section 3 code. */ + +#undef yyless +#define yyless(n) \ + do \ + { \ + /* Undo effects of setting up yytext. */ \ + yytext[yyleng] = yy_hold_char; \ + yy_c_buf_p = yytext + n; \ + yy_hold_char = *yy_c_buf_p; \ + *yy_c_buf_p = '\0'; \ + yyleng = n; \ + } \ + while ( 0 ) + + +/* Internal utility routines. */ + +#ifndef yytext_ptr +#ifdef YY_USE_PROTOS +static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) +#else +static void yy_flex_strncpy( s1, s2, n ) +char *s1; +yyconst char *s2; +int n; +#endif + { + register int i; + for ( i = 0; i < n; ++i ) + s1[i] = s2[i]; + } +#endif + +#ifdef YY_NEED_STRLEN +#ifdef YY_USE_PROTOS +static int yy_flex_strlen( yyconst char *s ) +#else +static int yy_flex_strlen( s ) +yyconst char *s; +#endif + { + register int n; + for ( n = 0; s[n]; ++n ) + ; + + return n; + } +#endif + + +#ifdef YY_USE_PROTOS +static void *yy_flex_alloc( yy_size_t size ) +#else +static void *yy_flex_alloc( size ) +yy_size_t size; +#endif + { + return (void *) malloc( size ); + } + +#ifdef YY_USE_PROTOS +static void *yy_flex_realloc( void *ptr, yy_size_t size ) +#else +static void *yy_flex_realloc( ptr, size ) +void *ptr; +yy_size_t size; +#endif + { + /* The cast to (char *) in the following accommodates both + * implementations that use char* generic pointers, and those + * that use void* generic pointers. It works with the latter + * because both ANSI C and C++ allow castless assignment from + * any pointer type to void*, and deal with argument conversions + * as though doing an assignment. + */ + return (void *) realloc( (char *) ptr, size ); + } + +#ifdef YY_USE_PROTOS +static void yy_flex_free( void *ptr ) +#else +static void yy_flex_free( ptr ) +void *ptr; +#endif + { + free( ptr ); + } + +#if defined(YY_MAIN) && YY_MAIN +int main() + { + yylex(); + return 0; + } +#endif +#line 624 "toke.l" + +struct path_list { + char *path; + struct path_list *next; +}; + +struct include_stack { + YY_BUFFER_STATE bs; + char *path; + struct path_list *more; /* more files in case of includedir */ + int lineno; + int keepopen; +}; + +static int +pl_compare(const void *v1, const void *v2) +{ + const struct path_list * const *p1 = v1; + const struct path_list * const *p2 = v2; + + return strcmp((*p1)->path, (*p2)->path); +} + +static char * +switch_dir(struct include_stack *stack, char *dirpath) +{ + DIR *dir; + int i, count = 0; + char *path = NULL; + struct dirent *dent; + struct stat sb; + struct path_list *pl, *first = NULL; + struct path_list **sorted = NULL; + + if (!(dir = opendir(dirpath))) { + if (errno != ENOENT) { + char *errbuf; + if (asprintf(&errbuf, "%s: %s", dirpath, strerror(errno)) != -1) { + yyerror(errbuf); + free(errbuf); + } else { + yyerror("unable to allocate memory"); + } + } + goto done; + } + while ((dent = readdir(dir))) { + /* Ignore files that end in '~' or have a '.' in them. */ + if (dent->d_name[0] == '\0' || dent->d_name[NAMLEN(dent) - 1] == '~' + || strchr(dent->d_name, '.') != NULL) { + continue; + } + if (asprintf(&path, "%s/%s", dirpath, dent->d_name) == -1) { + closedir(dir); + goto bad; + } + if (stat(path, &sb) != 0 || !S_ISREG(sb.st_mode)) { + efree(path); + path = NULL; + continue; + } + pl = malloc(sizeof(*pl)); + if (pl == NULL) + goto bad; + pl->path = path; + pl->next = first; + first = pl; + count++; + } + closedir(dir); + + if (count == 0) + goto done; + + /* Sort the list as an array. */ + sorted = malloc(sizeof(*sorted) * count); + if (sorted == NULL) + goto bad; + pl = first; + for (i = 0; i < count; i++) { + sorted[i] = pl; + pl = pl->next; + } + qsort(sorted, count, sizeof(*sorted), pl_compare); + + /* Apply sorting to the list. */ + first = sorted[0]; + sorted[count - 1]->next = NULL; + for (i = 1; i < count; i++) + sorted[i - 1]->next = sorted[i]; + efree(sorted); + + /* Pull out the first element for parsing, leave the rest for later. */ + if (count) { + path = first->path; + pl = first->next; + efree(first); + stack->more = pl; + } else { + path = NULL; + } +done: + efree(dirpath); + return path; +bad: + while (first != NULL) { + pl = first; + first = pl->next; + free(pl->path); + free(pl); + } + efree(sorted); + efree(dirpath); + efree(path); + return NULL; +} + +#define MAX_SUDOERS_DEPTH 128 +#define SUDOERS_STACK_INCREMENT 16 + +static size_t istacksize, idepth; +static struct include_stack *istack; +static int keepopen; + +void +init_lexer(void) +{ + struct path_list *pl; + + while (idepth) { + idepth--; + while ((pl = istack[idepth].more) != NULL) { + istack[idepth].more = pl->next; + efree(pl->path); + efree(pl); + } + efree(istack[idepth].path); + if (idepth && !istack[idepth].keepopen) + fclose(istack[idepth].bs->yy_input_file); + yy_delete_buffer(istack[idepth].bs); + } + efree(istack); + istack = NULL; + istacksize = idepth = 0; + sudolineno = 1; + keepopen = FALSE; + sawspace = FALSE; + continued = FALSE; + prev_state = INITIAL; +} + +static int +_push_include(char *path, int isdir) +{ + struct path_list *pl; + FILE *fp; + + /* push current state onto stack */ + if (idepth >= istacksize) { + if (idepth > MAX_SUDOERS_DEPTH) { + yyerror("too many levels of includes"); + return FALSE; + } + istacksize += SUDOERS_STACK_INCREMENT; + istack = (struct include_stack *) realloc(istack, + sizeof(*istack) * istacksize); + if (istack == NULL) { + yyerror("unable to allocate memory"); + return FALSE; + } + } + if (isdir) { + if (!(path = switch_dir(&istack[idepth], path))) { + /* switch_dir() called yyerror() for us */ + return FALSE; + } + while ((fp = open_sudoers(path, FALSE, &keepopen)) == NULL) { + /* Unable to open path in includedir, go to next one, if any. */ + efree(path); + if ((pl = istack[idepth].more) == NULL) + return FALSE; + path = pl->path; + istack[idepth].more = pl->next; + efree(pl); + } + } else { + if ((fp = open_sudoers(path, TRUE, &keepopen)) == NULL) { + char *errbuf; + if (asprintf(&errbuf, "%s: %s", path, strerror(errno)) != -1) { + yyerror(errbuf); + free(errbuf); + } else { + yyerror("unable to allocate memory"); + } + return FALSE; + } + istack[idepth].more = NULL; + } + /* Push the old (current) file and open the new one. */ + istack[idepth].path = sudoers; /* push old path */ + istack[idepth].bs = YY_CURRENT_BUFFER; + istack[idepth].lineno = sudolineno; + istack[idepth].keepopen = keepopen; + idepth++; + sudolineno = 1; + sudoers = path; + yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); + + return TRUE; +} + +static int +pop_include(void) +{ + struct path_list *pl; + FILE *fp; + + if (idepth == 0) + return FALSE; + + if (!keepopen) + fclose(YY_CURRENT_BUFFER->yy_input_file); + yy_delete_buffer(YY_CURRENT_BUFFER); + /* If we are in an include dir, move to the next file. */ + while ((pl = istack[idepth - 1].more) != NULL) { + fp = open_sudoers(pl->path, FALSE, &keepopen); + if (fp != NULL) { + istack[idepth - 1].more = pl->next; + efree(sudoers); + sudoers = pl->path; + sudolineno = 1; + yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); + efree(pl); + break; + } + /* Unable to open path in include dir, go to next one. */ + istack[idepth - 1].more = pl->next; + efree(pl->path); + efree(pl); + } + /* If no path list, just pop the last dir on the stack. */ + if (pl == NULL) { + idepth--; + yy_switch_to_buffer(istack[idepth].bs); + efree(sudoers); + sudoers = istack[idepth].path; + sudolineno = istack[idepth].lineno; + keepopen = istack[idepth].keepopen; + } + return TRUE; +} + +static char * +parse_include(char *base) +{ + char *cp, *ep, *path; + int len = 0, subst = 0; + size_t shost_len = 0; + + /* Pull out path from #include line. */ + cp = base + sizeof("#include"); + if (*cp == 'i') + cp += 3; /* includedir */ + while (isblank((unsigned char) *cp)) + cp++; + ep = cp; + while (*ep != '\0' && !isspace((unsigned char) *ep)) { + if (ep[0] == '%' && ep[1] == 'h') { + shost_len = strlen(user_shost); + len += shost_len - 2; + subst = 1; + } + ep++; + } + + /* Make a copy of path and return it. */ + len += (int)(ep - cp); + if ((path = malloc(len + 1)) == NULL) + yyerror("unable to allocate memory"); + if (subst) { + /* substitute for %h */ + char *pp = path; + while (cp < ep) { + if (cp[0] == '%' && cp[1] == 'h') { + memcpy(pp, user_shost, shost_len); + pp += shost_len; + cp += 2; + continue; + } + *pp++ = *cp++; + } + *pp = '\0'; + } else { + memcpy(path, cp, len); + path[len] = '\0'; + } + + /* Push any excess characters (e.g. comment, newline) back to the lexer */ + if (*ep != '\0') + yyless((int)(ep - base)); + + return path; +} + +#ifdef TRACELEXER +static int +sudoers_trace_print(const char *msg) +{ + return fputs(msg, stderr); +} +#endif /* TRACELEXER */ diff --git a/toke.h b/plugins/sudoers/toke.h similarity index 69% rename from toke.h rename to plugins/sudoers/toke.h index 75e9495..5e2a24a 100644 --- a/toke.h +++ b/plugins/sudoers/toke.h @@ -17,14 +17,25 @@ #ifndef _SUDO_TOKE_H #define _SUDO_TOKE_H -int append __P((char *, int)); -int fill_args __P((char *, int, int)); -int fill_cmnd __P((char *, int)); -int fill_txt __P((char *, int, int)); -int ipv6_valid __P((const char *s)); -void yyerror __P((const char *)); +int append(const char *, int); +int fill_args(const char *, int, int); +int fill_cmnd(const char *, int); +int fill_txt(const char *, int, int); +int ipv6_valid(const char *s); +void yyerror(const char *); + +#ifndef FLEX_SCANNER +extern int (*trace_print)(const char *msg); +#endif + +#define fill(a, b) fill_txt(a, b, 0) /* realloc() to size + COMMANDARGINC to make room for command args */ #define COMMANDARGINC 64 +#define LEXTRACE(msg) do { \ + if (trace_print != NULL) \ + (*trace_print)(msg); \ +} while (0); + #endif /* _SUDO_TOKE_H */ diff --git a/toke.l b/plugins/sudoers/toke.l similarity index 95% rename from toke.l rename to plugins/sudoers/toke.l index 05ea663..9428049 100644 --- a/toke.l +++ b/plugins/sudoers/toke.l @@ -1,6 +1,6 @@ %{ /* - * Copyright (c) 1996, 1998-2005, 2007-2010 + * Copyright (c) 1996, 1998-2005, 2007-2011 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -67,7 +67,7 @@ #endif #include #include -#include "sudo.h" +#include "sudoers.h" #include "parse.h" #include "toke.h" #include @@ -79,20 +79,19 @@ char *sudoers; static int continued, prev_state, sawspace; -static int _push_include __P((char *, int)); -static int pop_include __P((void)); -static char *parse_include __P((char *)); - -#define fill(a, b) fill_txt(a, b, 0) - -#define push_include(_p) (_push_include((_p), FALSE)) -#define push_includedir(_p) (_push_include((_p), TRUE)) +static int _push_include(char *, int); +static int pop_include(void); +static char *parse_include(char *); #ifdef TRACELEXER -#define LEXTRACE(msg) fputs(msg, stderr) +static int sudoers_trace_print(const char *msg); #else -#define LEXTRACE(msg) +# define sudoers_trace_print NULL #endif +int (*trace_print)(const char *msg) = sudoers_trace_print; + +#define push_include(_p) (_push_include((_p), FALSE)) +#define push_includedir(_p) (_push_include((_p), TRUE)) %} HEX16 [0-9A-Fa-f]{1,4} @@ -439,7 +438,7 @@ NOLOG_INPUT[[:blank:]]*: { return NTWKADDR; } -{IPV4ADDR}\/([12][0-9]*|3[0-2]*) { +{IPV4ADDR}\/([12]?[0-9]|3[0-2]) { if (!fill(yytext, yyleng)) yyterminate(); LEXTRACE("NTWKADDR "); @@ -468,22 +467,32 @@ NOLOG_INPUT[[:blank:]]*: { return NTWKADDR; } -[[:upper:]][[:upper:][:digit:]_]* { - if (strcmp(yytext, "ALL") == 0) { - LEXTRACE("ALL "); - return ALL; - } +ALL { + LEXTRACE("ALL "); + return ALL; + + } + +ROLE { #ifdef HAVE_SELINUX - /* XXX - restrict type/role to initial state */ - if (strcmp(yytext, "TYPE") == 0) { - LEXTRACE("TYPE "); - return TYPE; - } - if (strcmp(yytext, "ROLE") == 0) { - LEXTRACE("ROLE "); - return ROLE; - } -#endif /* HAVE_SELINUX */ + LEXTRACE("ROLE "); + return ROLE; +#else + goto got_alias; +#endif + } + +TYPE { +#ifdef HAVE_SELINUX + LEXTRACE("TYPE "); + return TYPE; +#else + goto got_alias; +#endif + } + +[[:upper:]][[:upper:][:digit:]_]* { + got_alias: if (!fill(yytext, yyleng)) yyterminate(); LEXTRACE("ALIAS "); @@ -627,9 +636,7 @@ struct include_stack { }; static int -pl_compare(v1, v2) - const void *v1; - const void *v2; +pl_compare(const void *v1, const void *v2) { const struct path_list * const *p1 = v1; const struct path_list * const *p2 = v2; @@ -638,9 +645,7 @@ pl_compare(v1, v2) } static char * -switch_dir(stack, dirpath) - struct include_stack *stack; - char *dirpath; +switch_dir(struct include_stack *stack, char *dirpath) { DIR *dir; int i, count = 0; @@ -741,7 +746,7 @@ static struct include_stack *istack; static int keepopen; void -init_lexer() +init_lexer(void) { struct path_list *pl; @@ -768,9 +773,7 @@ init_lexer() } static int -_push_include(path, isdir) - char *path; - int isdir; +_push_include(char *path, int isdir) { struct path_list *pl; FILE *fp; @@ -830,7 +833,7 @@ _push_include(path, isdir) } static int -pop_include() +pop_include(void) { struct path_list *pl; FILE *fp; @@ -871,8 +874,7 @@ pop_include() } static char * -parse_include(base) - char *base; +parse_include(char *base) { char *cp, *ep, *path; int len = 0, subst = 0; @@ -922,3 +924,11 @@ parse_include(base) return path; } + +#ifdef TRACELEXER +static int +sudoers_trace_print(const char *msg) +{ + return fputs(msg, stderr); +} +#endif /* TRACELEXER */ diff --git a/toke_util.c b/plugins/sudoers/toke_util.c similarity index 94% rename from toke_util.c rename to plugins/sudoers/toke_util.c index 99e7552..16636b6 100644 --- a/toke_util.c +++ b/plugins/sudoers/toke_util.c @@ -48,7 +48,7 @@ # include #endif /* HAVE_MALLOC_H && !STDC_HEADERS */ #include -#include "sudo.h" +#include "sudoers.h" #include "parse.h" #include "toke.h" #include @@ -57,8 +57,7 @@ static int arg_len = 0; static int arg_size = 0; static unsigned char -hexchar(s) - const char *s; +hexchar(const char *s) { int i; int result = 0; @@ -103,9 +102,7 @@ hexchar(s) } int -fill_txt(src, len, olen) - char *src; - int len, olen; +fill_txt(const char *src, int len, int olen) { char *dst; @@ -140,9 +137,7 @@ fill_txt(src, len, olen) } int -append(src, len) - char *src; - int len; +append(const char *src, int len) { int olen = 0; @@ -156,9 +151,7 @@ append(src, len) ((c) == ',' || (c) == ':' || (c) == '=' || (c) == ' ' || (c) == '\t' || (c) == '#') int -fill_cmnd(src, len) - char *src; - int len; +fill_cmnd(const char *src, int len) { char *dst; int i; @@ -185,10 +178,7 @@ fill_cmnd(src, len) } int -fill_args(s, len, addspace) - char *s; - int len; - int addspace; +fill_args(const char *s, int len, int addspace) { int new_len; char *p; @@ -233,8 +223,7 @@ fill_args(s, len, addspace) * Returns TRUE if address is valid else FALSE. */ int -ipv6_valid(s) - const char *s; +ipv6_valid(const char *s) { int nmatch = 0; diff --git a/tsgetgrpw.c b/plugins/sudoers/tsgetgrpw.c similarity index 89% rename from tsgetgrpw.c rename to plugins/sudoers/tsgetgrpw.c index 5b38298..7b9ad79 100644 --- a/tsgetgrpw.c +++ b/plugins/sudoers/tsgetgrpw.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2008, 2010 Todd C. Miller + * Copyright (c) 2005, 2008, 2010-2011 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -46,7 +46,7 @@ #include #include "tsgetgrpw.h" -#include "sudo.h" +#include "sudoers.h" #ifndef LINE_MAX # define LINE_MAX 2048 @@ -63,9 +63,22 @@ static FILE *grf; static const char *grfile = "/etc/group"; static int gr_stayopen; +void setgrfile(const char *); +void setgrent(void); +void endgrent(void); +struct group *getgrent(void); +struct group *getgrnam(const char *); +struct group *getgrgid(gid_t); + +void setpwfile(const char *); +void setpwent(void); +void endpwent(void); +struct passwd *getpwent(void); +struct passwd *getpwnam(const char *); +struct passwd *getpwuid(uid_t); + void -setpwfile(file) - const char *file; +setpwfile(const char *file) { pwfile = file; if (pwf != NULL) @@ -73,7 +86,7 @@ setpwfile(file) } void -setpwent() +setpwent(void) { if (pwf == NULL) { pwf = fopen(pwfile, "r"); @@ -86,7 +99,7 @@ setpwent() } void -endpwent() +endpwent(void) { if (pwf != NULL) { fclose(pwf); @@ -96,7 +109,7 @@ endpwent() } struct passwd * -getpwent() +getpwent(void) { static struct passwd pw; static char pwbuf[LINE_MAX]; @@ -139,8 +152,7 @@ getpwent() } struct passwd * -getpwnam(name) - const char *name; +getpwnam(const char *name) { struct passwd *pw; @@ -163,8 +175,7 @@ getpwnam(name) } struct passwd * -getpwuid(uid) - uid_t uid; +getpwuid(uid_t uid) { struct passwd *pw; @@ -187,8 +198,7 @@ getpwuid(uid) } void -setgrfile(file) - const char *file; +setgrfile(const char *file) { grfile = file; if (grf != NULL) @@ -196,7 +206,7 @@ setgrfile(file) } void -setgrent() +setgrent(void) { if (grf == NULL) { grf = fopen(grfile, "r"); @@ -209,7 +219,7 @@ setgrent() } void -endgrent() +endgrent(void) { if (grf != NULL) { fclose(grf); @@ -219,7 +229,7 @@ endgrent() } struct group * -getgrent() +getgrent(void) { static struct group gr; static char grbuf[LINE_MAX], *gr_mem[GRMEM_MAX+1]; @@ -260,8 +270,7 @@ getgrent() } struct group * -getgrnam(name) - const char *name; +getgrnam(const char *name) { struct group *gr; @@ -284,8 +293,7 @@ getgrnam(name) } struct group * -getgrgid(gid) - gid_t gid; +getgrgid(gid_t gid) { struct group *gr; diff --git a/plugins/sudoers/tsgetgrpw.h b/plugins/sudoers/tsgetgrpw.h new file mode 100644 index 0000000..5c380c3 --- /dev/null +++ b/plugins/sudoers/tsgetgrpw.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2010 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +/* + * Trivial replacements for the libc get{gr,pw}{uid,nam}() routines + * for use by testsudoers in the sudo test harness. + * We need our own since many platforms don't provide set{pw,gr}file(). + */ + +#include + +/* + * Define away the system prototypes so we don't have any conflicts. + */ + +#define setgrfile sys_setgrfile +#define setgrent sys_setgrent +#define endgrent sys_endgrent +#define getgrent sys_getgrent +#define getgrnam sys_getgrnam +#define getgrgid sys_getgrgid + +#define setpwfile sys_setpwfile +#define setpwent sys_setpwent +#define endpwent sys_endpwent +#define getpwent sys_getpwent +#define getpwnam sys_getpwnam +#define getpwuid sys_getpwuid + +#include +#include + +#undef setgrfile +#undef setgrent +#undef endgrent +#undef getgrent +#undef getgrnam +#undef getgrgid + +void setgrfile(const char *); +void setgrent(void); +void endgrent(void); +struct group *getgrent(void); +struct group *getgrnam(const char *); +struct group *getgrgid(gid_t); + +#undef setpwfile +#undef setpwent +#undef endpwent +#undef getpwent +#undef getpwnam +#undef getpwuid + +void setpwfile(const char *); +void setpwent(void); +void endpwent(void); +struct passwd *getpwent(void); +struct passwd *getpwnam(const char *); +struct passwd *getpwuid(uid_t); diff --git a/visudo.c b/plugins/sudoers/visudo.c similarity index 89% rename from visudo.c rename to plugins/sudoers/visudo.c index bc77377..dd31f62 100644 --- a/visudo.c +++ b/plugins/sudoers/visudo.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 1998-2005, 2007-2010 + * Copyright (c) 1996, 1998-2005, 2007-2011 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -76,10 +76,11 @@ # include #endif -#include "sudo.h" +#include "sudoers.h" #include "interfaces.h" #include "parse.h" #include "redblack.h" +#include "sudoers_version.h" #include struct sudoersfile { @@ -95,26 +96,29 @@ TQ_DECLARE(sudoersfile) /* * Function prototypes */ -static RETSIGTYPE quit __P((int)); -static char *get_args __P((char *)); -static char *get_editor __P((char **)); -static void get_hostname __P((void)); -static char whatnow __P((void)); -static int check_aliases __P((int, int)); -static int check_syntax __P((char *, int, int)); -static int edit_sudoers __P((struct sudoersfile *, char *, char *, int)); -static int install_sudoers __P((struct sudoersfile *, int)); -static int print_unused __P((void *, void *)); -static int reparse_sudoers __P((char *, char *, int, int)); -static int run_command __P((char *, char **)); -static void print_selfref __P((char *, int, int, int)); -static void print_undefined __P((char *, int, int, int)); -static void setup_signals __P((void)); -static void help __P((void)) __attribute__((__noreturn__)); -static void usage __P((int)); - -extern void yyerror __P((const char *)); -extern void yyrestart __P((FILE *)); +static void quit(int); +static char *get_args(char *); +static char *get_editor(char **); +static void get_hostname(void); +static char whatnow(void); +static int check_aliases(int, int); +static int check_syntax(char *, int, int); +static int edit_sudoers(struct sudoersfile *, char *, char *, int); +static int install_sudoers(struct sudoersfile *, int); +static int print_unused(void *, void *); +static int reparse_sudoers(char *, char *, int, int); +static int run_command(char *, char **); +static int visudo_printf(int msg_type, const char *fmt, ...); +static void print_selfref(char *name, int, int, int); +static void print_undefined(char *name, int, int, int); +static void setup_signals(void); +static void help(void) __attribute__((__noreturn__)); +static void usage(int); + +void cleanup(int); + +extern void yyerror(const char *); +extern void yyrestart(FILE *); /* * External globals exported by the parser @@ -130,19 +134,15 @@ extern int optind; /* * Globals */ -int Argc; -char **Argv; -int num_interfaces; struct interface *interfaces; struct sudo_user sudo_user; struct passwd *list_pw; +sudo_printf_t sudo_printf = visudo_printf; static struct sudoersfile_list sudoerslist; static struct rbtree *alias_freelist; int -main(argc, argv) - int argc; - char **argv; +main(int argc, char *argv[]) { struct sudoersfile *sp; char *args, *editor, *sudoers_path; @@ -152,8 +152,10 @@ main(argc, argv) malloc_options = "AFGJPR"; #endif - Argv = argv; - if ((Argc = argc) < 1) +#if !defined(HAVE_GETPROGNAME) && !defined(HAVE___PROGNAME) + setprogname(argc > 0 ? argv[0] : "visudo"); +#endif + if (argc < 1) usage(1); /* @@ -161,10 +163,11 @@ main(argc, argv) */ checkonly = oldperms = quiet = strict = FALSE; sudoers_path = _PATH_SUDOERS; - while ((ch = getopt(argc, argv, "Vcf:hsq")) != -1) { + while ((ch = getopt(argc, argv, "Vcf:sq")) != -1) { switch (ch) { case 'V': (void) printf("%s version %s\n", getprogname(), PACKAGE_VERSION); + (void) printf("%s grammar version %d\n", getprogname(), SUDOERS_GRAMMAR_VERSION); exit(0); case 'c': checkonly++; /* check mode */ @@ -253,10 +256,7 @@ main(argc, argv) * Returns TRUE on success, else FALSE. */ static int -edit_sudoers(sp, editor, args, lineno) - struct sudoersfile *sp; - char *editor, *args; - int lineno; +edit_sudoers(struct sudoersfile *sp, char *editor, char *args, int lineno) { int tfd; /* sudoers temp file descriptor */ int modified; /* was the file modified? */ @@ -345,9 +345,9 @@ edit_sudoers(sp, editor, args, lineno) * XPG4 specifies that vi's exit value is a function of the * number of errors during editing (?!?!). */ - gettime(&tv1); + gettimeofday(&tv1, NULL); if (run_command(editor, av) != -1) { - gettime(&tv2); + gettimeofday(&tv2, NULL); /* * Sanity checks. */ @@ -396,9 +396,7 @@ edit_sudoers(sp, editor, args, lineno) * Returns TRUE on success, else FALSE. */ static int -reparse_sudoers(editor, args, strict, quiet) - char *editor, *args; - int strict, quiet; +reparse_sudoers(char *editor, char *args, int strict, int quiet) { struct sudoersfile *sp, *last; FILE *fp; @@ -477,9 +475,7 @@ reparse_sudoers(editor, args, strict, quiet) * move it into place. Returns TRUE on success, else FALSE. */ static int -install_sudoers(sp, oldperms) - struct sudoersfile *sp; - int oldperms; +install_sudoers(struct sudoersfile *sp, int oldperms) { struct stat sb; @@ -561,44 +557,44 @@ install_sudoers(sp, oldperms) /* STUB */ void -set_fqdn() +set_fqdn(void) { return; } /* STUB */ void -init_envtables() +init_envtables(void) { return; } /* STUB */ int -user_is_exempt() +user_is_exempt(void) { return FALSE; } /* STUB */ void -sudo_setspent() +sudo_setspent(void) { return; } /* STUB */ void -sudo_endspent() +sudo_endspent(void) { return; } -char * -sudo_getepw(pw) - const struct passwd *pw; +/* STUB */ +int +group_plugin_query(const char *user, const char *group, const struct passwd *pw) { - return pw->pw_passwd; + return FALSE; } /* @@ -606,7 +602,7 @@ sudo_getepw(pw) * to do now. Returns the first letter of their choice. */ static char -whatnow() +whatnow(void) { int choice, c; @@ -637,7 +633,7 @@ whatnow() * Install signal handlers for visudo. */ static void -setup_signals() +setup_signals(void) { sigaction_t sa; @@ -655,9 +651,7 @@ setup_signals() } static int -run_command(path, argv) - char *path; - char **argv; +run_command(char *path, char **argv) { int status; pid_t pid, rv; @@ -677,11 +671,7 @@ run_command(path, argv) } do { -#ifdef sudo_waitpid - rv = sudo_waitpid(pid, &status, 0); -#else - rv = wait(&status); -#endif + rv = waitpid(pid, &status, 0); } while (rv == -1 && errno == EINTR); if (rv == -1 || !WIFEXITED(status)) @@ -690,10 +680,7 @@ run_command(path, argv) } static int -check_syntax(sudoers_path, quiet, strict) - char *sudoers_path; - int quiet; - int strict; +check_syntax(char *sudoers_path, int quiet, int strict) { struct stat sb; int error; @@ -760,10 +747,7 @@ check_syntax(sudoers_path, quiet, strict) * any subsequent files #included via a callback from the parser. */ FILE * -open_sudoers(path, doedit, keepopen) - const char *path; - int doedit; - int *keepopen; +open_sudoers(const char *path, int doedit, int *keepopen) { struct sudoersfile *entry; FILE *fp; @@ -809,8 +793,7 @@ open_sudoers(path, doedit, keepopen) } static char * -get_editor(args) - char **args; +get_editor(char **args) { char *Editor, *EditorArgs, *EditorPath, *UserEditor, *UserEditorArgs; @@ -913,8 +896,7 @@ get_editor(args) * Split out any command line arguments and return them. */ static char * -get_args(cmnd) - char *cmnd; +get_args(char *cmnd) { char *args; @@ -933,7 +915,7 @@ get_args(cmnd) * Look up the hostname and set user_host and user_shost. */ static void -get_hostname() +get_hostname(void) { char *p, thost[MAXHOSTNAMELEN + 1]; @@ -954,11 +936,7 @@ get_hostname() } static int -alias_remove_recursive(name, type, strict, quiet) - char *name; - int type; - int strict; - int quiet; +alias_remove_recursive(char *name, int type, int strict, int quiet) { struct member *m; struct alias *a; @@ -989,9 +967,7 @@ alias_remove_recursive(name, type, strict, quiet) * aliases or unused aliases. */ static int -check_aliases(strict, quiet) - int strict; - int quiet; +check_aliases(int strict, int quiet) { struct cmndspec *cs; struct member *m, *binding; @@ -1108,11 +1084,7 @@ check_aliases(strict, quiet) } static void -print_undefined(name, type, strict, quiet) - char *name; - int type; - int strict; - int quiet; +print_undefined(char *name, int type, int strict, int quiet) { if (!quiet) { warningx("%s: %s_Alias `%s' referenced but not defined", @@ -1140,9 +1112,7 @@ print_selfref(name, type, strict, quiet) } static int -print_unused(v1, v2) - void *v1; - void *v2; +print_unused(void *v1, void *v2) { struct alias *a = (struct alias *)v1; char *prefix = (char *)v2; @@ -1158,8 +1128,7 @@ print_unused(v1, v2) * Unlink any sudoers temp files that remain. */ void -cleanup(gotsignal) - int gotsignal; +cleanup(int gotsignal) { struct sudoersfile *sp; @@ -1176,21 +1145,25 @@ cleanup(gotsignal) /* * Unlink sudoers temp files (if any) and exit. */ -static RETSIGTYPE -quit(signo) - int signo; +static void +quit(int signo) { + const char *signame, *myname; + cleanup(signo); -#define emsg " exiting due to signal.\n" - if (write(STDERR_FILENO, getprogname(), strlen(getprogname())) == -1 || - write(STDERR_FILENO, emsg, sizeof(emsg) - 1) == -1) +#define emsg " exiting due to signal: " + myname = getprogname(); + signame = strsignal(signo); + if (write(STDERR_FILENO, myname, strlen(myname)) == -1 || + write(STDERR_FILENO, emsg, sizeof(emsg) - 1) == -1 || + write(STDERR_FILENO, signame, strlen(signame)) == -1 || + write(STDERR_FILENO, "\n", 1) == -1) /* shut up glibc */; _exit(signo); } static void -usage(fatal) - int fatal; +usage(int fatal) { (void) fprintf(fatal ? stderr : stdout, "usage: %s [-chqsV] [-f sudoers]\n", getprogname()); @@ -1199,7 +1172,7 @@ usage(fatal) } static void -help() +help(void) { (void) printf("%s - safely edit the sudoers file\n\n", getprogname()); usage(0); @@ -1212,3 +1185,28 @@ help() (void) puts(" -V display version information and exit"); exit(0); } + +static int +visudo_printf(int msg_type, const char *fmt, ...) +{ + va_list ap; + FILE *fp; + + switch (msg_type) { + case SUDO_CONV_INFO_MSG: + fp = stdout; + break; + case SUDO_CONV_ERROR_MSG: + fp = stderr; + break; + default: + errno = EINVAL; + return -1; + } + + va_start(ap, fmt); + vfprintf(fp, fmt, ap); + va_end(ap); + + return 0; +} diff --git a/set_perms.c b/set_perms.c deleted file mode 100644 index 355baad..0000000 --- a/set_perms.c +++ /dev/null @@ -1,663 +0,0 @@ -/* - * Copyright (c) 1994-1996,1998-2010 Todd C. Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Sponsored in part by the Defense Advanced Research Projects - * Agency (DARPA) and Air Force Research Laboratory, Air Force - * Materiel Command, USAF, under agreement number F39502-99-1-0512. - */ - -#include - -#include -#include -#include -#include -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif /* STDC_HEADERS */ -#ifdef HAVE_STRING_H -# include -#endif /* HAVE_STRING_H */ -#ifdef HAVE_STRINGS_H -# include -#endif /* HAVE_STRINGS_H */ -#ifdef HAVE_UNISTD_H -# include -#endif /* HAVE_UNISTD_H */ -#include -#include -#include -#ifdef HAVE_LOGIN_CAP_H -# include -#endif -#ifdef HAVE_PROJECT_H -# include -# include -#endif - -#include "sudo.h" - -#ifdef __TANDEM -# define ROOT_UID 65535 -#else -# define ROOT_UID 0 -#endif - -/* - * Prototypes - */ -static void runas_setup __P((void)); -static void runas_setgroups __P((void)); -static void restore_groups __P((void)); - -static int current_perm = -1; - -#ifdef HAVE_SETRESUID -/* - * Set real and effective and saved uids and gids based on perm. - * We always retain a saved uid of 0 unless we are headed for an exec(). - * We only flip the effective gid since it only changes for PERM_SUDOERS. - * This version of set_perms() works fine with the "stay_setuid" option. - */ -int -set_perms(perm) - int perm; -{ - const char *errstr; - int noexit; - - noexit = ISSET(perm, PERM_NOEXIT); - CLR(perm, PERM_MASK); - - if (perm == current_perm) - return 1; - - switch (perm) { - case PERM_ROOT: - if (setresuid(ROOT_UID, ROOT_UID, ROOT_UID)) { - errstr = "setresuid(ROOT_UID, ROOT_UID, ROOT_UID)"; - goto bad; - } - (void) setresgid(-1, user_gid, -1); - if (current_perm == PERM_RUNAS) - restore_groups(); - break; - - case PERM_USER: - (void) setresgid(-1, user_gid, -1); - if (setresuid(user_uid, user_uid, ROOT_UID)) { - errstr = "setresuid(user_uid, user_uid, ROOT_UID)"; - goto bad; - } - break; - - case PERM_FULL_USER: - /* headed for exec() */ - (void) setgid(user_gid); - if (setresuid(user_uid, user_uid, user_uid)) { - errstr = "setresuid(user_uid, user_uid, user_uid)"; - goto bad; - } - break; - - case PERM_RUNAS: - runas_setgroups(); - (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)) { - errstr = "unable to change to runas uid"; - goto bad; - } - break; - - case PERM_FULL_RUNAS: - /* headed for exec(), assume euid == ROOT_UID */ - runas_setup(); - if (setresuid(def_stay_setuid ? - user_uid : runas_pw->pw_uid, - runas_pw->pw_uid, runas_pw->pw_uid)) { - errstr = "unable to change to runas uid"; - goto bad; - } - break; - - case PERM_SUDOERS: - /* assume euid == ROOT_UID, ruid == user */ - if (setresgid(-1, SUDOERS_GID, -1)) - error(1, "unable to change to sudoers gid"); - - /* - * If SUDOERS_UID == ROOT_UID and SUDOERS_MODE - * is group readable we use a non-zero - * uid in order to avoid NFS lossage. - * Using uid 1 is a bit bogus but should - * work on all OS's. - */ - if (SUDOERS_UID == ROOT_UID) { - if ((SUDOERS_MODE & 040) && setresuid(ROOT_UID, 1, ROOT_UID)) { - errstr = "setresuid(ROOT_UID, 1, ROOT_UID)"; - goto bad; - } - } else { - if (setresuid(ROOT_UID, SUDOERS_UID, ROOT_UID)) { - errstr = "setresuid(ROOT_UID, SUDOERS_UID, ROOT_UID)"; - goto bad; - } - } - break; - case PERM_TIMESTAMP: - if (setresuid(ROOT_UID, timestamp_uid, ROOT_UID)) { - errstr = "setresuid(ROOT_UID, timestamp_uid, ROOT_UID)"; - goto bad; - } - break; - } - - current_perm = perm; - return 1; -bad: - warningx("%s: %s", errstr, - errno == EAGAIN ? "too many processes" : strerror(errno)); - if (noexit) - return 0; - exit(1); -} - -#else -# ifdef HAVE_SETREUID - -/* - * Set real and effective uids and gids based on perm. - * We always retain a real or effective uid of ROOT_UID unless - * we are headed for an exec(). - * This version of set_perms() works fine with the "stay_setuid" option. - */ -int -set_perms(perm) - int perm; -{ - const char *errstr; - int noexit; - - noexit = ISSET(perm, PERM_NOEXIT); - CLR(perm, PERM_MASK); - - if (perm == current_perm) - return 1; - - switch (perm) { - case PERM_ROOT: - if (setreuid(-1, ROOT_UID)) { - errstr = "setreuid(-1, ROOT_UID)"; - goto bad; - } - if (setuid(ROOT_UID)) { - errstr = "setuid(ROOT_UID)"; - goto bad; - } - (void) setregid(-1, user_gid); - if (current_perm == PERM_RUNAS) - restore_groups(); - break; - - case PERM_USER: - (void) setregid(-1, user_gid); - if (setreuid(ROOT_UID, user_uid)) { - errstr = "setreuid(ROOT_UID, user_uid)"; - goto bad; - } - break; - - case PERM_FULL_USER: - /* headed for exec() */ - (void) setgid(user_gid); - if (setreuid(user_uid, user_uid)) { - errstr = "setreuid(user_uid, user_uid)"; - goto bad; - } - break; - - case PERM_RUNAS: - runas_setgroups(); - (void) setregid(-1, runas_gr ? - runas_gr->gr_gid : runas_pw->pw_gid); - if (setreuid(-1, - runas_pw ? runas_pw->pw_uid : user_uid)) { - errstr = "unable to change to runas uid"; - goto bad; - } - break; - - case PERM_FULL_RUNAS: - /* headed for exec(), assume euid == ROOT_UID */ - runas_setup(); - if (setreuid(def_stay_setuid ? user_uid : - runas_pw->pw_uid, runas_pw->pw_uid)) { - errstr = "unable to change to runas uid"; - goto bad; - } - break; - - case PERM_SUDOERS: - /* assume euid == ROOT_UID, ruid == user */ - if (setregid(-1, SUDOERS_GID)) - error(1, "unable to change to sudoers gid"); - - /* - * If SUDOERS_UID == ROOT_UID and SUDOERS_MODE - * is group readable we use a non-zero - * uid in order to avoid NFS lossage. - * Using uid 1 is a bit bogus but should - * work on all OS's. - */ - if (SUDOERS_UID == ROOT_UID) { - if ((SUDOERS_MODE & 040) && setreuid(ROOT_UID, 1)) { - errstr = "setreuid(ROOT_UID, 1)"; - goto bad; - } - } else { - if (setreuid(ROOT_UID, SUDOERS_UID)) { - errstr = "setreuid(ROOT_UID, SUDOERS_UID)"; - goto bad; - } - } - break; - case PERM_TIMESTAMP: - if (setreuid(ROOT_UID, timestamp_uid)) { - errstr = "setreuid(ROOT_UID, timestamp_uid)"; - goto bad; - } - break; - } - - current_perm = perm; - return 1; -bad: - warningx("%s: %s", errstr, - errno == EAGAIN ? "too many processes" : strerror(errno)); - if (noexit) - return 0; - exit(1); -} - -# else /* !HAVE_SETRESUID && !HAVE_SETREUID */ -# ifdef HAVE_SETEUID - -/* - * Set real and effective uids and gids based on perm. - * NOTE: does not support the "stay_setuid" option. - */ -int -set_perms(perm) - int perm; -{ - const char *errstr; - int noexit; - - noexit = ISSET(perm, PERM_NOEXIT); - CLR(perm, PERM_MASK); - - if (perm == current_perm) - return 1; - - /* - * Since we only have setuid() and seteuid() and semantics - * for these calls differ on various systems, we set - * real and effective uids to ROOT_UID initially to be safe. - */ - if (seteuid(ROOT_UID)) { - errstr = "seteuid(ROOT_UID)"; - goto bad; - } - if (setuid(ROOT_UID)) { - errstr = "setuid(ROOT_UID)"; - goto bad; - } - - switch (perm) { - case PERM_ROOT: - /* uid set above */ - (void) setegid(user_gid); - if (current_perm == PERM_RUNAS) - restore_groups(); - break; - - case PERM_USER: - (void) setegid(user_gid); - if (seteuid(user_uid)) { - errstr = "seteuid(user_uid)"; - goto bad; - } - break; - - case PERM_FULL_USER: - /* headed for exec() */ - (void) setgid(user_gid); - if (setuid(user_uid)) { - errstr = "setuid(user_uid)"; - goto bad; - } - break; - - case PERM_RUNAS: - runas_setgroups(); - (void) setegid(runas_gr ? - runas_gr->gr_gid : runas_pw->pw_gid); - if (seteuid(runas_pw ? runas_pw->pw_uid : user_uid)) { - errstr = "unable to change to runas uid"; - goto bad; - } - break; - - case PERM_FULL_RUNAS: - /* headed for exec() */ - runas_setup(); - if (setuid(runas_pw->pw_uid)) { - errstr = "unable to change to runas uid"; - goto bad; - } - break; - - case PERM_SUDOERS: - if (setegid(SUDOERS_GID)) - error(1, "unable to change to sudoers gid"); - - /* - * If SUDOERS_UID == ROOT_UID and SUDOERS_MODE - * is group readable we use a non-zero - * uid in order to avoid NFS lossage. - * Using uid 1 is a bit bogus but should - * work on all OS's. - */ - if (SUDOERS_UID == ROOT_UID) { - if ((SUDOERS_MODE & 040) && seteuid(1)) { - errstr = "seteuid(1)"; - goto bad; - } - } else { - if (seteuid(SUDOERS_UID)) { - errstr = "seteuid(SUDOERS_UID)"; - goto bad; - } - } - break; - case PERM_TIMESTAMP: - if (seteuid(timestamp_uid)) { - errstr = "seteuid(timestamp_uid)"; - goto bad; - } - break; - } - - current_perm = perm; - return 1; -bad: - warningx("%s: %s", errstr, - errno == EAGAIN ? "too many processes" : strerror(errno)); - if (noexit) - return 0; - exit(1); -} - -# else /* !HAVE_SETRESUID && !HAVE_SETREUID && !HAVE_SETEUID */ - -/* - * Set uids and gids based on perm via setuid() and setgid(). - * NOTE: does not support the "stay_setuid" or timestampowner options. - * Also, SUDOERS_UID and SUDOERS_GID are not used. - */ -int -set_perms(perm) - int perm; -{ - const char *errstr; - int noexit; - - noexit = ISSET(perm, PERM_NOEXIT); - CLR(perm, PERM_MASK); - - if (perm == current_perm) - return 1; - - switch (perm) { - case PERM_ROOT: - if (setuid(ROOT_UID)) { - errstr = "setuid(ROOT_UID)"; - goto bad; - } - if (current_perm == PERM_RUNAS) - restore_groups(); - break; - - case PERM_FULL_USER: - (void) setgid(user_gid); - if (setuid(user_uid)) { - errstr = "setuid(user_uid)"; - goto bad; - } - break; - - case PERM_FULL_RUNAS: - runas_setup(); - if (setuid(runas_pw->pw_uid)) { - errstr = "unable to change to runas uid"; - goto bad; - } - break; - - case PERM_USER: - case PERM_SUDOERS: - case PERM_RUNAS: - case PERM_TIMESTAMP: - /* Unsupported since we can't set euid. */ - break; - } - - current_perm = perm; - return 1; -bad: - warningx("%s: %s", errstr, - errno == EAGAIN ? "too many processes" : strerror(errno)); - if (noexit) - return 0; - exit(1); -} -# endif /* HAVE_SETEUID */ -# endif /* HAVE_SETREUID */ -#endif /* HAVE_SETRESUID */ - -#ifdef HAVE_INITGROUPS -static void -runas_setgroups() -{ - static int ngroups = -1; -# ifdef HAVE_GETGROUPS - static GETGROUPS_T *groups; -# endif - static struct passwd *pw; - struct passwd *opw = pw; - - if (def_preserve_groups) - return; - - /* - * Use stashed copy of runas groups if available, else initgroups and stash. - */ - pw = runas_pw ? runas_pw : sudo_user.pw; - if (pw != opw) { -# ifdef HAVE_SETAUTHDB - aix_setauthdb(pw->pw_name); -# endif - if (initgroups(pw->pw_name, pw->pw_gid) < 0) - log_error(USE_ERRNO|MSG_ONLY, "can't set runas group vector"); -# ifdef HAVE_GETGROUPS - if (groups) { - efree(groups); - groups = NULL; - } - if ((ngroups = getgroups(0, NULL)) > 0) { - groups = emalloc2(ngroups, sizeof(GETGROUPS_T)); - if (getgroups(ngroups, groups) < 0) - log_error(USE_ERRNO|MSG_ONLY, "can't get runas group vector"); - } -# ifdef HAVE_SETAUTHDB - aix_restoreauthdb(); -# endif - } else { - if (setgroups(ngroups, groups) < 0) - log_error(USE_ERRNO|MSG_ONLY, "can't set runas group vector"); -# endif /* HAVE_GETGROUPS */ - } -} - -static void -restore_groups() -{ - if (user_ngroups >= 0 && setgroups(user_ngroups, user_groups) < 0) - log_error(USE_ERRNO|MSG_ONLY, "can't reset user group vector"); -} - -#else - -static void -runas_setgroups() -{ - /* STUB */ -} - -static void -restore_groups() -{ - /* STUB */ -} - -#endif /* HAVE_INITGROUPS */ - -#ifdef HAVE_PROJECT_H -static void -set_project(pw) - struct passwd *pw; -{ - struct project proj; - char buf[PROJECT_BUFSZ]; - int errval; - - /* - * Collect the default project for the user and settaskid - */ - setprojent(); - if (getdefaultproj(pw->pw_name, &proj, buf, sizeof(buf)) != NULL) { - errval = setproject(proj.pj_name, pw->pw_name, TASK_NORMAL); - switch(errval) { - case 0: - break; - case SETPROJ_ERR_TASK: - switch (errno) { - case EAGAIN: - warningx("resource control limit has been reached"); - break; - case ESRCH: - warningx("user \"%s\" is not a member of project \"%s\"", - pw->pw_name, proj.pj_name); - break; - case EACCES: - warningx("the invoking task is final"); - break; - default: - warningx("could not join project \"%s\"", proj.pj_name); - } - case SETPROJ_ERR_POOL: - switch (errno) { - case EACCES: - warningx("no resource pool accepting default bindings " - "exists for project \"%s\"", proj.pj_name); - break; - case ESRCH: - warningx("specified resource pool does not exist for " - "project \"%s\"", proj.pj_name); - break; - default: - warningx("could not bind to default resource pool for " - "project \"%s\"", proj.pj_name); - } - break; - default: - if (errval <= 0) { - warningx("setproject failed for project \"%s\"", proj.pj_name); - } else { - warningx("warning, resource control assignment failed for " - "project \"%s\"", proj.pj_name); - } - } - } else { - warning("getdefaultproj"); - } - endprojent(); -} -#endif /* HAVE_PROJECT_H */ - -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_PROJECT_H - set_project(runas_pw); -#endif -#ifdef HAVE_GETUSERATTR - aix_prep_user(runas_pw->pw_name, user_ttypath); -#endif -#ifdef HAVE_PAM - pam_begin_session(runas_pw); -#endif /* HAVE_PAM */ - -#ifdef HAVE_LOGIN_CAP_H - if (def_use_loginclass) { - /* - * We only use setusercontext() to set the nice value and rlimits. - */ - flags = LOGIN_SETRESOURCES|LOGIN_SETPRIORITY; - if (setusercontext(lc, runas_pw, runas_pw->pw_uid, flags)) { - if (runas_pw->pw_uid != ROOT_UID) - error(1, "unable to set user context"); - else - warning("unable to set user context"); - } - } -#endif /* HAVE_LOGIN_CAP_H */ - /* - * Initialize group vector - */ - runas_setgroups(); -#ifdef HAVE_SETEUID - if (setegid(gid)) - warning("cannot set egid to runas gid"); -#endif - if (setgid(gid)) - warning("cannot set gid to runas gid"); - } -} diff --git a/sigaction.c b/sigaction.c deleted file mode 100644 index 9285dda..0000000 --- a/sigaction.c +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2001-2005 Todd C. Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Sponsored in part by the Defense Advanced Research Projects - * Agency (DARPA) and Air Force Research Laboratory, Air Force - * Materiel Command, USAF, under agreement number F39502-99-1-0512. - */ - -#include - -#include - -#include -#include - -#include "missing.h" - -int -sigaction(signo, sa, osa) - int signo; - const sigaction_t *sa; - sigaction_t *osa; -{ - sigaction_t nsa; - int error; - - /* We must reverse SV_INTERRUPT since it is the opposite of SA_RESTART */ - if (sa) { - nsa = *sa; - nsa.sa_flags ^= SV_INTERRUPT; - sa = &nsa; - } - - error = sigvec(signo, sa, osa); - if (!error && osa) - osa->sa_flags ^= SV_INTERRUPT; /* flip SV_INTERRUPT as above */ - - return error; -} - -int -sigemptyset(set) - sigset_t *set; -{ - - *set = 0; - return 0; -} - -int -sigfillset(set) - sigset_t *set; -{ - - *set = ~0;; - return 0; -} - -int -sigaddset(set, signo) - sigset_t *set; - int signo; -{ - - if (signo <= 0 || signo >= NSIG) { - errno = EINVAL; - return -1; - } - - SET(*set, sigmask(signo)); - return 0; -} - -int -sigdelset(set, signo) - sigset_t *set; - int signo; -{ - - if (signo <= 0 || signo >= NSIG) { - errno = EINVAL; - return -1; - } - - CLR(*set, sigmask(signo)); - return 0; -} - -int -sigismember(set, signo) - sigset_t *set; - int signo; -{ - - return ISSET(*set, sigmask(signo)); -} - -int -sigprocmask(how, set, oset) - int how; - const sigset_t *set; - sigset_t *oset; -{ - int mask; - - /* If 'set' is NULL the user just wants the current signal mask. */ - if (set == 0) - mask = sigblock(0); - else - switch (how) { - case SIG_BLOCK: - mask = sigblock(*set); - break; - case SIG_UNBLOCK: - mask = sigsetmask(sigblock(0) & ~(*set)); - break; - case SIG_SETMASK: - mask = sigsetmask(*set); - break; - default: - return -1; - } - - if (mask == -1) - return -1; - if (oset) - *oset = mask; - return 0; -} diff --git a/src/Makefile.in b/src/Makefile.in new file mode 100644 index 0000000..c1b15bc --- /dev/null +++ b/src/Makefile.in @@ -0,0 +1,189 @@ +# +# Copyright (c) 2011 Todd C. Miller +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# @configure_input@ +# + +#### Start of system configuration section. #### + +srcdir = @srcdir@ +devdir = @devdir@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +incdir = $(top_srcdir)/include + +# Compiler & tools to use +CC = @CC@ +LIBTOOL = @LIBTOOL@ @LT_STATIC@ + +# Our install program supports extra flags... +INSTALL = $(SHELL) $(top_srcdir)/install-sh -c + +# Libraries +LT_LIBS = $(top_builddir)/common/libcommon.la $(LIBOBJDIR)libreplace.la +LIBS = @LIBS@ @SUDO_LIBS@ @GETGROUPS_LIB@ @NET_LIBS@ $(LT_LIBS) + +# C preprocessor flags +CPPFLAGS = -I$(incdir) -I$(top_builddir) -I$(srcdir) -I. @CPPFLAGS@ + +# Usually -O and/or -g +CFLAGS = @CFLAGS@ + +# Flags to pass to the link stage +LDFLAGS = @LDFLAGS@ + +# Where to install things... +prefix = @prefix@ +exec_prefix = @exec_prefix@ +bindir = @bindir@ +sbindir = @sbindir@ +sysconfdir = @sysconfdir@ +libexecdir = @libexecdir@ +datarootdir = @datarootdir@ +localstatedir = @localstatedir@ +noexecfile = @NOEXECFILE@ +noexecdir = @NOEXECDIR@ + +# User and group ids the installed files should be "owned" by +install_uid = 0 +install_gid = 0 + +# OS dependent defines +DEFS = @OSDEFS@ -D_PATH_SUDO_CONF=\"$(sysconfdir)/sudo.conf\" + +#### End of system configuration section. #### + +SHELL = @SHELL@ + +PROGS = @PROGS@ + +OBJS = conversation.o error.o exec.o exec_pty.o get_pty.o net_ifs.o \ + load_plugins.o parse_args.o sudo.o sudo_edit.o tgetpass.o \ + ttysize.o utmp.o @SUDO_OBJS@ + +LIBOBJDIR = $(top_builddir)/@ac_config_libobj_dir@/ + +VERSION = @PACKAGE_VERSION@ + +SUDODEP = $(srcdir)/sudo.h $(incdir)/sudo_plugin.h $(incdir)/alloc.h \ + $(incdir)/error.h $(incdir)/list.h $(incdir)/missing.h \ + $(top_builddir)/pathnames.h $(top_builddir)/config.h + +all: $(PROGS) + +Makefile: $(srcdir)/Makefile.in + (cd $(top_builddir) && ./config.status --file src/Makefile) + +.SUFFIXES: .c .h .lo .o + +.c.o: + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $< + +.c.lo: + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $< + +sudo: $(OBJS) $(LT_LIBS) + $(LIBTOOL) --mode=link $(CC) -o $@ $(OBJS) $(LDFLAGS) $(LIBS) -static-libtool-libs + +libsudo_noexec.la: sudo_noexec.lo + $(LIBTOOL) --mode=link $(CC) $(LDFLAGS) -o $@ sudo_noexec.lo -avoid-version -rpath $(noexecdir) + +sesh: sesh.o + $(CC) -o $@ sesh.o + +# Dependencies +# XXX - SUDODEP is overkill for some of these +conversation.o: $(srcdir)/conversation.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/conversation.c +error.o: $(srcdir)/error.c $(incdir)/missing.h $(incdir)/error.h $(top_builddir)/config.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/error.c +exec.o: $(srcdir)/exec.c $(SUDODEP) $(srcdir)/sudo_exec.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/exec.c +exec_pty.o: $(srcdir)/exec_pty.c $(SUDODEP) $(srcdir)/sudo_exec.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/exec_pty.c +get_pty.o: $(srcdir)/get_pty.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/get_pty.c +net_ifs.o: $(srcdir)/net_ifs.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/net_ifs.c +load_plugins.o: $(srcdir)/load_plugins.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/load_plugins.c +parse_args.o: $(srcdir)/parse_args.c sudo_usage.h $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/parse_args.c +preload.o: $(srcdir)/preload.c $(incdir)/sudo_plugin.h $(top_builddir)/config.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/preload.c +selinux.o: $(srcdir)/selinux.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/selinux.c +sesh.o: $(srcdir)/sesh.c $(incdir)/missing.h $(top_builddir)/config.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/sesh.c +sudo.o: $(srcdir)/sudo.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/sudo.c +sudo_edit.o: $(srcdir)/sudo_edit.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/sudo_edit.c +sudo_noexec.lo: $(srcdir)/sudo_noexec.c $(incdir)/missing.h $(top_builddir)/config.h + $(LIBTOOL) --mode=compile $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/sudo_noexec.c +tgetpass.o: $(srcdir)/tgetpass.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/tgetpass.c +ttysize.o: $(srcdir)/ttysize.c $(incdir)/missing.h $(top_builddir)/config.h + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/ttysize.c +utmp.o: $(srcdir)/utmp.c $(SUDODEP) + $(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/utmp.c + +pre-install: + +install: install-dirs install-binaries @INSTALL_NOEXEC@ + +install-dirs: + $(SHELL) $(top_srcdir)/mkinstalldirs $(DESTDIR)$(bindir) \ + $(DESTDIR)$(noexecdir) + +install-binaries: install-dirs $(PROGS) + $(INSTALL) -b~ -O $(install_uid) -G $(install_gid) -M 04111 sudo $(DESTDIR)$(bindir)/sudo + rm -f $(DESTDIR)$(bindir)/sudoedit + ln $(DESTDIR)$(bindir)/sudo $(DESTDIR)$(bindir)/sudoedit + if [ -f sesh ]; then $(INSTALL) -b~ -O $(install_uid) -G $(install_gid) -M 0111 sesh $(DESTDIR)$(libexecdir)/sesh; fi + +install-doc: + +install-includes: + +# We install sudo_noexec by hand so we can avoid a "lib" prefix +# and a version number. Since we use LD_PRELOAD, neither is needed. +install-noexec: install-dirs libsudo_noexec.la + if [ -f .libs/lib$(noexecfile) ]; then $(INSTALL) -b~ -O $(install_uid) -G $(install_gid) -M 0755 .libs/lib$(noexecfile) $(DESTDIR)$(noexecdir)/$(noexecfile); fi + +install-plugin: + +uninstall: + -rm -f $(DESTDIR)$(bindir)/sudo $(DESTDIR)$(bindir)/sudoedit \ + $(DESTDIR)$(libexecdir)/sesh \ + $(DESTDIR)$(noexecdir)/$(noexecfile) \ + +check: + +clean: + -$(LIBTOOL) --mode=clean rm -f $(PROGS) *.lo *.o *.la *.a stamp-* core *.core core.* + +mostlyclean: clean + +distclean: clean + -rm -rf Makefile .libs sudo_usage.h + +clobber: distclean + +realclean: distclean + rm -f TAGS tags + +cleandir: realclean diff --git a/src/conversation.c b/src/conversation.c new file mode 100644 index 0000000..fa40f79 --- /dev/null +++ b/src/conversation.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 1999-2005, 2007-2010 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ + +#include + +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS) +# include +# endif +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#include + +#include "sudo.h" +#include "sudo_plugin.h" + +extern int tgetpass_flags; /* XXX */ + +/* + * Sudo conversation function. + */ +int +sudo_conversation(int num_msgs, const struct sudo_conv_message msgs[], + struct sudo_conv_reply replies[]) +{ + struct sudo_conv_reply *repl; + const struct sudo_conv_message *msg; + char *pass; + int n, flags = tgetpass_flags; + + for (n = 0; n < num_msgs; n++) { + msg = &msgs[n]; + repl = &replies[n]; + switch (msg->msg_type & 0xff) { + case SUDO_CONV_PROMPT_ECHO_ON: + case SUDO_CONV_PROMPT_MASK: + if (msg->msg_type == SUDO_CONV_PROMPT_ECHO_ON) + SET(flags, TGP_ECHO); + else + SET(flags, TGP_MASK); + /* FALLTHROUGH */ + case SUDO_CONV_PROMPT_ECHO_OFF: + if (ISSET(msg->msg_type, SUDO_CONV_PROMPT_ECHO_OK)) + SET(flags, TGP_NOECHO_TRY); + /* Read the password unless interrupted. */ + pass = tgetpass(msg->msg, msg->timeout, flags); + if (pass == NULL) + goto err; + repl->reply = estrdup(pass); + zero_bytes(pass, strlen(pass)); + break; + case SUDO_CONV_INFO_MSG: + if (msg->msg) + (void) fputs(msg->msg, stdout); + break; + case SUDO_CONV_ERROR_MSG: + if (msg->msg) + (void) fputs(msg->msg, stderr); + break; + default: + goto err; + } + } + + return 0; + +err: + /* Zero and free allocated memory and return an error. */ + do { + repl = &replies[n]; + if (repl->reply != NULL) { + zero_bytes(repl->reply, strlen(repl->reply)); + free(repl->reply); + repl->reply = NULL; + } + } while (n--); + + return -1; +} + +int +_sudo_printf(int msg_type, const char *fmt, ...) +{ + va_list ap; + FILE *fp; + int len; + + switch (msg_type) { + case SUDO_CONV_INFO_MSG: + fp = stdout; + break; + case SUDO_CONV_ERROR_MSG: + fp = stderr; + break; + default: + errno = EINVAL; + return -1; + } + + va_start(ap, fmt); + len = vfprintf(fp, fmt, ap); + va_end(ap); + + return len; +} diff --git a/error.c b/src/error.c similarity index 68% rename from error.c rename to src/error.c index e5cb959..8e26789 100644 --- a/error.c +++ b/src/error.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2005 Todd C. Miller + * Copyright (c) 2004-2005, 2010 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -26,25 +26,14 @@ #include "missing.h" #include "error.h" -static void _warning __P((int, const char *, va_list)); - void cleanup __P((int)); +static void _warning(int, const char *, va_list); + void cleanup(int); void -#ifdef __STDC__ error(int eval, const char *fmt, ...) -#else -error(eval, fmt, va_alist) - int eval; - const char *fmt; - va_dcl -#endif { va_list ap; -#ifdef __STDC__ va_start(ap, fmt); -#else - va_start(ap); -#endif _warning(1, fmt, ap); va_end(ap); cleanup(0); @@ -52,21 +41,10 @@ error(eval, fmt, va_alist) } void -#ifdef __STDC__ errorx(int eval, const char *fmt, ...) -#else -errorx(eval, fmt, va_alist) - int eval; - const char *fmt; - va_dcl -#endif { va_list ap; -#ifdef __STDC__ va_start(ap, fmt); -#else - va_start(ap); -#endif _warning(0, fmt, ap); va_end(ap); cleanup(0); @@ -74,48 +52,25 @@ errorx(eval, fmt, va_alist) } void -#ifdef __STDC__ warning(const char *fmt, ...) -#else -warning(fmt, va_alist) - const char *fmt; - va_dcl -#endif { va_list ap; -#ifdef __STDC__ va_start(ap, fmt); -#else - va_start(ap); -#endif _warning(1, fmt, ap); va_end(ap); } void -#ifdef __STDC__ warningx(const char *fmt, ...) -#else -warningx(fmt, va_alist) - const char *fmt; - va_dcl -#endif { va_list ap; -#ifdef __STDC__ va_start(ap, fmt); -#else - va_start(ap); -#endif _warning(0, fmt, ap); va_end(ap); } static void -_warning(use_errno, fmt, ap) - int use_errno; - const char *fmt; - va_list ap; +_warning(int use_errno, const char *fmt, va_list ap) { int serrno = errno; diff --git a/exec.c b/src/exec.c similarity index 78% rename from exec.c rename to src/exec.c index 19dbad2..510ce11 100644 --- a/exec.c +++ b/src/exec.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2010 Todd C. Miller + * Copyright (c) 2009-2011 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -25,11 +25,6 @@ #include #include #include -#ifdef HAVE_TERMIOS_H -# include -#else -# include -#endif /* HAVE_TERMIOS_H */ #include #ifdef HAVE_SYS_SELECT_H # include @@ -61,17 +56,16 @@ #include #include #include -#ifdef HAVE_SELINUX -# include -#endif +#include #include "sudo.h" #include "sudo_exec.h" +#include "sudo_plugin.h" +#include "sudo_plugin_int.h" /* Shared with exec_pty.c for use with handler(). */ int signal_pipe[2]; -#ifdef _PATH_SUDO_IO_LOGDIR /* We keep a tailq of signals to forward to child. */ struct sigforward { struct sigforward *prev, *next; @@ -79,30 +73,32 @@ struct sigforward { }; TQ_DECLARE(sigforward) static struct sigforward_list sigfwd_list; -static void forward_signals __P((int fd)); -static void schedule_signal __P((int signo)); -static int log_io; -#endif /* _PATH_SUDO_IO_LOGDIR */ -static int handle_signals __P((int fd, pid_t child, - struct command_status *cstat)); +static int handle_signals(int fd, pid_t child, int log_io, + struct command_status *cstat); +static void forward_signals(int fd); +static void schedule_signal(int signo); /* * Like execve(2) but falls back to running through /bin/sh * ala execvp(3) if we get ENOEXEC. */ int -my_execve(path, argv, envp) - const char *path; - char *argv[]; - char *envp[]; +my_execve(const char *path, char *const argv[], char *const envp[]) { execve(path, argv, envp); if (errno == ENOEXEC) { - argv--; /* at least one extra slot... */ - argv[0] = "sh"; - argv[1] = (char *)path; - execve(_PATH_BSHELL, argv, envp); + int argc; + char **nargv; + + for (argc = 0; argv[argc] != NULL; argc++) + continue; + nargv = emalloc2(argc + 2, sizeof(char *)); + nargv[0] = "sh"; + nargv[1] = (char *)path; + memcpy(nargv + 2, argv + 1, argc * sizeof(char *)); + execve(_PATH_BSHELL, nargv, envp); + efree(nargv); } return -1; } @@ -111,12 +107,7 @@ my_execve(path, argv, envp) * Fork and execute a command, returns the child's pid. * Sends errno back on sv[1] if execve() fails. */ -static int fork_cmnd(path, argv, envp, sv, rbac_enabled) - const char *path; - char *argv[]; - char *envp[]; - int sv[2]; - int rbac_enabled; +static int fork_cmnd(struct command_details *details, int sv[2]) { struct command_status cstat; sigaction_t sa; @@ -140,15 +131,16 @@ static int fork_cmnd(path, argv, envp, sv, rbac_enabled) close(signal_pipe[1]); fcntl(sv[1], F_SETFD, FD_CLOEXEC); restore_signals(); - if (exec_setup(rbac_enabled, user_ttypath, -1) == TRUE) { + if (exec_setup(details, NULL, -1) == TRUE) { /* headed for execve() */ - closefrom(def_closefrom); + if (details->closefrom >= 0) + closefrom(details->closefrom); #ifdef HAVE_SELINUX - if (rbac_enabled) - selinux_execve(path, argv, envp); + if (ISSET(details->flags, CD_RBAC_ENABLED)) + selinux_execve(details->command, details->argv, details->envp); else #endif - my_execve(path, argv, envp); + my_execve(details->command, details->argv, details->envp); } cstat.type = CMD_ERRNO; cstat.val = errno; @@ -182,7 +174,7 @@ static struct signal_state { * Save signal handler state so it can be restored before exec. */ void -save_signals() +save_signals(void) { struct signal_state *ss; @@ -194,7 +186,7 @@ save_signals() * Restore signal handlers to initial state. */ void -restore_signals() +restore_signals(void) { struct signal_state *ss; @@ -208,23 +200,16 @@ restore_signals() * we fact that we have two different controlling terminals to deal with. */ int -sudo_execve(path, argv, envp, uid, cstat, dowait, bgmode) - const char *path; - char *argv[]; - char *envp[]; - uid_t uid; - struct command_status *cstat; - int dowait; - int bgmode; +sudo_execve(struct command_details *details, struct command_status *cstat) { - int maxfd, n, nready, sv[2]; - int rbac_enabled = 0; + int maxfd, n, nready, sv[2], log_io = FALSE; + const char *utmp_user = NULL; fd_set *fdsr, *fdsw; sigaction_t sa; pid_t child; /* If running in background mode, fork and exit. */ - if (bgmode) { + if (ISSET(details->flags, CD_BACKGROUND)) { switch (fork()) { case -1: cstat->type = CMD_ERRNO; @@ -239,32 +224,19 @@ sudo_execve(path, argv, envp, uid, cstat, dowait, bgmode) } } -#ifdef _PATH_SUDO_IO_LOGDIR - log_io = def_log_output || def_log_input || def_use_pty; - if (log_io) { - if (!bgmode) - pty_setup(uid); - io_log_open(); - dowait = TRUE; - } -#endif /* _PATH_SUDO_IO_LOGDIR */ - -#ifdef HAVE_SELINUX - rbac_enabled = is_selinux_enabled() > 0 && user_role != NULL; - if (rbac_enabled) - dowait = TRUE; -#endif - /* - * If we don't need to wait for the command to finish, just exec it. + * If we have an I/O plugin or the policy plugin has requested one, we + * need to allocate a pty. It is OK to set log_io in the pty-only case + * as the tailqueue plugin will be empty and no I/O logging will occur. */ - if (!dowait) { - exec_setup(FALSE, NULL, -1); - closefrom(def_closefrom); - my_execve(path, argv, envp); - cstat->type = CMD_ERRNO; - cstat->val = errno; - return 127; + if (!tq_empty(&io_plugins) || ISSET(details->flags, CD_USE_PTY)) { + log_io = TRUE; + if (!ISSET(details->flags, CD_BACKGROUND)) { + if (ISSET(details->flags, CD_SET_UTMP)) + utmp_user = details->utmp_user ? details->utmp_user : user_details.username; + sudo_debug(8, "allocate pty for I/O logging"); + pty_setup(details->euid, user_details.tty, utmp_user); + } } /* @@ -285,7 +257,7 @@ sudo_execve(path, argv, envp, uid, cstat, dowait, bgmode) sigemptyset(&sa.sa_mask); /* - * Signals for forward to the child process (excluding SIGCHLD). + * Signals for forward to the child process (excluding SIGALRM and SIGCHLD). * Note: HP-UX select() will not be interrupted if SA_RESTART set. */ sa.sa_flags = SA_INTERRUPT; /* do not restart syscalls */ @@ -307,14 +279,16 @@ sudo_execve(path, argv, envp, uid, cstat, dowait, bgmode) * Child will run the command in the pty, parent will pass data * to and from pty. Adjusts maxfd as needed. */ -#ifdef _PATH_SUDO_IO_LOGDIR if (log_io) - child = fork_pty(path, argv, envp, sv, rbac_enabled, &maxfd); + child = fork_pty(details, sv, &maxfd); else -#endif - child = fork_cmnd(path, argv, envp, sv, rbac_enabled); + child = fork_cmnd(details, sv); close(sv[1]); + /* Set command timeout if specified. */ + if (ISSET(details->flags, CD_SET_TIMEOUT)) + alarm(details->timeout); + #ifdef HAVE_SETLOCALE /* * I/O logging must be in the C locale for floating point numbers @@ -335,25 +309,21 @@ sudo_execve(path, argv, envp, uid, cstat, dowait, bgmode) FD_SET(signal_pipe[0], fdsr); FD_SET(sv[0], fdsr); -#ifdef _PATH_SUDO_IO_LOGDIR if (!tq_empty(&sigfwd_list)) FD_SET(sv[0], fdsw); if (log_io) fd_set_iobs(fdsr, fdsw); /* XXX - better name */ -#endif nready = select(maxfd + 1, fdsr, fdsw, NULL, NULL); if (nready == -1) { if (errno == EINTR) continue; error(1, "select failed"); } -#ifdef _PATH_SUDO_IO_LOGDIR if (FD_ISSET(sv[0], fdsw)) { forward_signals(sv[0]); } -#endif /* _PATH_SUDO_IO_LOGDIR */ if (FD_ISSET(signal_pipe[0], fdsr)) { - n = handle_signals(signal_pipe[0], child, cstat); + n = handle_signals(signal_pipe[0], child, log_io, cstat); if (n == 0) { /* Child has exited, cstat is set, we are done. */ goto done; @@ -371,7 +341,6 @@ sudo_execve(path, argv, envp, uid, cstat, dowait, bgmode) if (n == -1) { if (errno == EINTR) continue; -#ifdef _PATH_SUDO_IO_LOGDIR /* * If not logging I/O we will receive ECONNRESET when * the command is executed. It is safe to ignore this. @@ -381,12 +350,11 @@ sudo_execve(path, argv, envp, uid, cstat, dowait, bgmode) cstat->val = errno; break; } -#endif } -#ifdef _PATH_SUDO_IO_LOGDIR /* XXX */ if (cstat->type == CMD_WSTATUS) { if (WIFSTOPPED(cstat->val)) { /* Suspend parent and tell child how to resume on return. */ + sudo_debug(8, "child stopped, suspending parent"); n = suspend_parent(WSTOPSIG(cstat->val)); schedule_signal(n); continue; @@ -394,33 +362,27 @@ sudo_execve(path, argv, envp, uid, cstat, dowait, bgmode) /* Child exited or was killed, either way we are done. */ break; } - } else -#endif /* _PATH_SUDO_IO_LOGDIR */ - if (cstat->type == CMD_ERRNO) { + } else if (cstat->type == CMD_ERRNO) { /* Child was unable to execute command or broken pipe. */ break; } } -#ifdef _PATH_SUDO_IO_LOGDIR if (perform_io(fdsr, fdsw, cstat) != 0) { /* I/O error, kill child if still alive and finish. */ schedule_signal(SIGKILL); forward_signals(sv[0]); break; } -#endif /* _PATH_SUDO_IO_LOGDIR */ } -#ifdef _PATH_SUDO_IO_LOGDIR if (log_io) { /* Flush any remaining output and free pty-related memory. */ pty_close(cstat); - } -#endif /* _PATH_SUDO_IO_LOGDIR */ + } #ifdef HAVE_SELINUX - if (rbac_enabled) { + if (ISSET(details->flags, CD_RBAC_ENABLED)) { /* This is probably not needed in log_io mode. */ if (selinux_restore_tty() != 0) warningx("unable to restore tty label"); @@ -430,13 +392,11 @@ sudo_execve(path, argv, envp, uid, cstat, dowait, bgmode) done: efree(fdsr); efree(fdsw); -#ifdef _PATH_SUDO_IO_LOGDIR while (!tq_empty(&sigfwd_list)) { struct sigforward *sigfwd = tq_first(&sigfwd_list); tq_remove(&sigfwd_list, sigfwd); efree(sigfwd); } -#endif /* _PATH_SUDO_IO_LOGDIR */ return cstat->type == CMD_ERRNO ? -1 : 0; } @@ -446,10 +406,7 @@ done: * Returns -1 on error, 0 on child exit, else 1. */ static int -handle_signals(fd, child, cstat) - int fd; - pid_t child; - struct command_status *cstat; +handle_signals(int fd, pid_t child, int log_io, struct command_status *cstat) { unsigned char signo; ssize_t nread; @@ -469,48 +426,39 @@ handle_signals(fd, child, cstat) /* If pipe is empty, we are done. */ if (errno == EAGAIN) break; + sudo_debug(9, "error reading signal pipe %s", strerror(errno)); cstat->type = CMD_ERRNO; cstat->val = errno; return -1; } + sudo_debug(9, "received signal %d", signo); if (signo == SIGCHLD) { /* * If logging I/O, child is the intermediate process, * otherwise it is the command itself. */ do { -#ifdef sudo_waitpid - pid = sudo_waitpid(child, &status, WUNTRACED|WNOHANG); -#else - pid = wait(&status); -#endif + pid = waitpid(child, &status, WUNTRACED|WNOHANG); } while (pid == -1 && errno == EINTR); if (pid == child) { /* If not logging I/O and child has exited we are done. */ -#ifdef _PATH_SUDO_IO_LOGDIR - if (!log_io) -#endif - { + if (!log_io) { if (WIFSTOPPED(status)) { /* * Save the controlling terminal's process group * so we can restore it after we resume. */ -#ifdef HAVE_TCSETPGRP pid_t saved_pgrp = (pid_t)-1; int fd = open(_PATH_TTY, O_RDWR|O_NOCTTY, 0); if (fd != -1) saved_pgrp = tcgetpgrp(fd); -#endif /* HAVE_TCSETPGRP */ if (kill(getpid(), WSTOPSIG(status)) != 0) warning("kill(%d, %d)", getpid(), WSTOPSIG(status)); -#ifdef HAVE_TCSETPGRP if (fd != -1) { if (saved_pgrp != (pid_t)-1) (void)tcsetpgrp(fd, saved_pgrp); close(fd); } -#endif /* HAVE_TCSETPGRP */ } else { /* Child has exited, we are done. */ cstat->type = CMD_WSTATUS; @@ -521,15 +469,14 @@ handle_signals(fd, child, cstat) /* Else we get ECONNRESET on sv[0] if child dies. */ } } else { -#ifdef _PATH_SUDO_IO_LOGDIR if (log_io) { /* Schedule signo to be forwared to the child. */ schedule_signal(signo); - } else -#endif - { + } else { /* Nothing listening on sv[0], send directly. */ - if (kill(child, signo) != 0) + if (signo == SIGALRM) + terminate_child(child, FALSE); + else if (kill(child, signo) != 0) warning("kill(%d, %d)", child, signo); } } @@ -537,13 +484,11 @@ handle_signals(fd, child, cstat) return 1; } -#ifdef _PATH_SUDO_IO_LOGDIR /* * Forward signals in sigfwd_list to child listening on fd. */ static void -forward_signals(sock) - int sock; +forward_signals(int sock) { struct sigforward *sigfwd; struct command_status cstat; @@ -551,6 +496,8 @@ forward_signals(sock) while (!tq_empty(&sigfwd_list)) { sigfwd = tq_first(&sigfwd_list); + sudo_debug(9, "sending signal %d to child over backchannel", + sigfwd->signo); cstat.type = CMD_SIGNO; cstat.val = sigfwd->signo; do { @@ -576,8 +523,7 @@ forward_signals(sock) * Schedule a signal to be forwared. */ static void -schedule_signal(signo) - int signo; +schedule_signal(int signo) { struct sigforward *sigfwd; @@ -587,15 +533,13 @@ schedule_signal(signo) sigfwd->signo = signo; tq_append(&sigfwd_list, sigfwd); } -#endif /* _PATH_SUDO_IO_LOGDIR */ /* * Generic handler for signals passed from parent -> child. * The other end of signal_pipe is checked in the main event loop. */ -RETSIGTYPE -handler(s) - int s; +void +handler(int s) { unsigned char signo = (unsigned char)s; @@ -612,8 +556,7 @@ handler(s) * Returns 0 on success and -1 on error. */ int -pipe_nonblock(fds) - int fds[2]; +pipe_nonblock(int fds[2]) { int flags, rval; diff --git a/exec_pty.c b/src/exec_pty.c similarity index 81% rename from exec_pty.c rename to src/exec_pty.c index ec54a1f..914d55f 100644 --- a/exec_pty.c +++ b/src/exec_pty.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2010 Todd C. Miller + * Copyright (c) 2009-2011 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -24,11 +24,6 @@ #include #include #include -#ifdef HAVE_TERMIOS_H -# include -#else -# include -#endif /* HAVE_TERMIOS_H */ #include #ifdef HAVE_SYS_SELECT_H # include @@ -60,9 +55,12 @@ #include #include #include +#include #include "sudo.h" #include "sudo_exec.h" +#include "sudo_plugin.h" +#include "sudo_plugin_int.h" #define SFD_STDIN 0 #define SFD_STDOUT 1 @@ -87,7 +85,7 @@ struct io_buffer { int off; /* write position (how much already consumed) */ int rfd; /* reader (producer) */ int wfd; /* writer (consumer) */ - int (*action) __P((const char *buf, unsigned int len)); + int (*action)(const char *buf, unsigned int len); char buf[16 * 1024]; }; @@ -98,17 +96,30 @@ static int pipeline = FALSE; static int tty_initialized; static int ttymode = TERM_COOKED; static pid_t ppgrp, child, child_pgrp; +static sigset_t ttyblock; static struct io_buffer *iobufs; -static void flush_output __P((void)); -static int exec_monitor __P((const char *path, char *argv[], - char *envp[], int, int)); -static void exec_pty __P((const char *path, char *argv[], - char *envp[], int)); -static RETSIGTYPE sigwinch __P((int s)); -static void sync_ttysize __P((int src, int dst)); -static void deliver_signal __P((pid_t pid, int signo)); -static int safe_close __P((int fd)); +static void flush_output(void); +static int exec_monitor(struct command_details *details, int backchannel); +static void exec_pty(struct command_details *detail); +static void sigwinch(int s); +static void sync_ttysize(int src, int dst); +static void deliver_signal(pid_t pid, int signo); +static int safe_close(int fd); + +/* + * Cleanup hook for error()/errorx() + */ +void +cleanup(int gotsignal) +{ + if (!tq_empty(&io_plugins)) + term_restore(io_fds[SFD_USERTTY], 0); +#ifdef HAVE_SELINUX + selinux_restore_tty(); +#endif + utmp_logout(slavename, 0); /* XXX - only if CD_SET_UTMP */ +} /* * Allocate a pty if /dev/tty is a tty. @@ -116,15 +127,132 @@ static int safe_close __P((int fd)); * and slavename globals. */ void -pty_setup(uid) - uid_t uid; +pty_setup(uid_t uid, const char *tty, const char *utmp_user) { io_fds[SFD_USERTTY] = open(_PATH_TTY, O_RDWR|O_NOCTTY, 0); if (io_fds[SFD_USERTTY] != -1) { if (!get_pty(&io_fds[SFD_MASTER], &io_fds[SFD_SLAVE], slavename, sizeof(slavename), uid)) error(1, "Can't get pty"); + /* Add entry to utmp/utmpx? */ + if (utmp_user != NULL) + utmp_login(tty, slavename, io_fds[SFD_SLAVE], utmp_user); + } +} + +/* Call I/O plugin tty input log method. */ +static int +log_ttyin(const char *buf, unsigned int n) +{ + struct plugin_container *plugin; + sigset_t omask; + int rval = TRUE; + + sigprocmask(SIG_BLOCK, &ttyblock, &omask); + + tq_foreach_fwd(&io_plugins, plugin) { + if (plugin->u.io->log_ttyin) { + if (!plugin->u.io->log_ttyin(buf, n)) { + rval = FALSE; + break; + } + } + } + + sigprocmask(SIG_SETMASK, &omask, NULL); + return rval; +} + +/* Call I/O plugin stdin log method. */ +static int +log_stdin(const char *buf, unsigned int n) +{ + struct plugin_container *plugin; + sigset_t omask; + int rval = TRUE; + + sigprocmask(SIG_BLOCK, &ttyblock, &omask); + + tq_foreach_fwd(&io_plugins, plugin) { + if (plugin->u.io->log_stdin) { + if (!plugin->u.io->log_stdin(buf, n)) { + rval = FALSE; + break; + } + } + } + + sigprocmask(SIG_SETMASK, &omask, NULL); + return rval; +} + +/* Call I/O plugin tty output log method. */ +static int +log_ttyout(const char *buf, unsigned int n) +{ + struct plugin_container *plugin; + sigset_t omask; + int rval = TRUE; + + sigprocmask(SIG_BLOCK, &ttyblock, &omask); + + tq_foreach_fwd(&io_plugins, plugin) { + if (plugin->u.io->log_ttyout) { + if (!plugin->u.io->log_ttyout(buf, n)) { + rval = FALSE; + break; + } + } } + + sigprocmask(SIG_SETMASK, &omask, NULL); + return rval; +} + +/* Call I/O plugin stdout log method. */ +static int +log_stdout(const char *buf, unsigned int n) +{ + struct plugin_container *plugin; + sigset_t omask; + int rval = TRUE; + + sigprocmask(SIG_BLOCK, &ttyblock, &omask); + + tq_foreach_fwd(&io_plugins, plugin) { + if (plugin->u.io->log_stdout) { + if (!plugin->u.io->log_stdout(buf, n)) { + rval = FALSE; + break; + } + } + } + + sigprocmask(SIG_SETMASK, &omask, NULL); + return rval; +} + +/* Call I/O plugin stderr log method. */ +static int +log_stderr(const char *buf, unsigned int n) +{ + struct plugin_container *plugin; + sigset_t omask; + int rval = TRUE; + + sigprocmask(SIG_BLOCK, &ttyblock, &omask); + + tq_foreach_fwd(&io_plugins, plugin) { + if (plugin->u.io->log_stderr) { + if (!plugin->u.io->log_stderr(buf, n)) { + rval = FALSE; + break; + } + } + } + + sigprocmask(SIG_SETMASK, &omask, NULL); + return rval; } /* @@ -133,7 +261,7 @@ pty_setup(uid) * the pty slave as needed. */ static void -check_foreground() +check_foreground(void) { if (io_fds[SFD_USERTTY] != -1) { foreground = tcgetpgrp(io_fds[SFD_USERTTY]) == ppgrp; @@ -152,8 +280,7 @@ check_foreground() * foreground or SIGCONT_BG if it is a background process. */ int -suspend_parent(signo) - int signo; +suspend_parent(int signo) { sigaction_t sa, osa; int n, oldmode = ttymode, rval = 0; @@ -194,6 +321,7 @@ suspend_parent(signo) /* Suspend self and continue child when we resume. */ sa.sa_handler = SIG_DFL; sigaction(signo, &sa, &osa); + sudo_debug(8, "kill parent %d", signo); if (killpg(ppgrp, signo) != 0) warning("killpg(%d, %d)", ppgrp, signo); @@ -204,6 +332,9 @@ suspend_parent(signo) * Only modify term if we are foreground process and either * the old tty mode was not cooked or child got SIGTT{IN,OU} */ + sudo_debug(8, "parent is in %sground, ttymode %d -> %d", + foreground ? "fore" : "back", oldmode, ttymode); + if (ttymode != TERM_COOKED) { if (foreground) { /* Set raw mode. */ @@ -227,10 +358,8 @@ suspend_parent(signo) /* * Kill child with increasing urgency. */ -static void -terminate_child(pid, use_pgrp) - pid_t pid; - int use_pgrp; +void +terminate_child(pid_t pid, int use_pgrp) { /* * Note that SIGCHLD will interrupt the sleep() @@ -248,16 +377,9 @@ terminate_child(pid, use_pgrp) } } -/* - * Allocate a new io_buffer struct and insert it at the head of the list. - * Returns the new head element. - */ static struct io_buffer * -io_buf_new(rfd, wfd, action, head) - int rfd; - int wfd; - int (*action) __P((const char *, unsigned int)); - struct io_buffer *head; +io_buf_new(int rfd, int wfd, int (*action)(const char *, unsigned int), + struct io_buffer *head) { struct io_buffer *iob; @@ -272,14 +394,10 @@ io_buf_new(rfd, wfd, action, head) /* * Read/write iobufs depending on fdsr and fdsw. - * Fills in cstat on error. * Returns the number of errors. */ int -perform_io(fdsr, fdsw, cstat) - fd_set *fdsr; - fd_set *fdsw; - struct command_status *cstat; +perform_io(fd_set *fdsr, fd_set *fdsw, struct command_status *cstat) { struct io_buffer *iob; int n, errors = 0; @@ -347,30 +465,32 @@ perform_io(fdsr, fdsw, cstat) * Returns the child pid. */ int -fork_pty(path, argv, envp, sv, rbac_enabled, maxfd) - const char *path; - char *argv[]; - char *envp[]; - int sv[2]; - int rbac_enabled; - int *maxfd; +fork_pty(struct command_details *details, int sv[], int *maxfd) { struct command_status cstat; struct io_buffer *iob; int io_pipe[3][2], n; sigaction_t sa; - + ppgrp = getpgrp(); /* parent's pgrp, so child can signal us */ - + zero_bytes(&sa, sizeof(sa)); sigemptyset(&sa.sa_mask); - + if (io_fds[SFD_USERTTY] != -1) { sa.sa_flags = SA_RESTART; sa.sa_handler = sigwinch; sigaction(SIGWINCH, &sa, NULL); } + /* So we can block tty-generated signals */ + sigemptyset(&ttyblock); + sigaddset(&ttyblock, SIGINT); + sigaddset(&ttyblock, SIGQUIT); + sigaddset(&ttyblock, SIGTSTP); + sigaddset(&ttyblock, SIGTTIN); + sigaddset(&ttyblock, SIGTTOU); + /* * Setup stdin/stdout/stderr for child, to be duped after forking. */ @@ -454,7 +574,7 @@ fork_pty(path, argv, envp, sv, rbac_enabled, maxfd) close(signal_pipe[0]); close(signal_pipe[1]); fcntl(sv[1], F_SETFD, FD_CLOEXEC); - if (exec_setup(rbac_enabled, slavename, io_fds[SFD_SLAVE]) == TRUE) { + if (exec_setup(details, slavename, io_fds[SFD_SLAVE]) == TRUE) { /* Close the other end of the stdin/stdout/stderr pipes and exec. */ if (io_pipe[STDIN_FILENO][1]) close(io_pipe[STDIN_FILENO][1]); @@ -462,7 +582,7 @@ fork_pty(path, argv, envp, sv, rbac_enabled, maxfd) close(io_pipe[STDOUT_FILENO][0]); if (io_pipe[STDERR_FILENO][0]) close(io_pipe[STDERR_FILENO][0]); - exec_monitor(path, argv, envp, sv[1], rbac_enabled); + exec_monitor(details, sv[1]); } cstat.type = CMD_ERRNO; cstat.val = errno; @@ -475,11 +595,11 @@ fork_pty(path, argv, envp, sv, rbac_enabled, maxfd) close(io_pipe[STDIN_FILENO][0]); if (io_pipe[STDOUT_FILENO][1]) close(io_pipe[STDOUT_FILENO][1]); - if (io_pipe[STDERR_FILENO][1]) + if (io_pipe[STDERR_FILENO][1]) close(io_pipe[STDERR_FILENO][1]); for (iob = iobufs; iob; iob = iob->next) { - /* Adjust maxfd. */ + /* Determine maxfd */ if (iob->rfd > *maxfd) *maxfd = iob->rfd; if (iob->wfd > *maxfd) @@ -497,13 +617,8 @@ fork_pty(path, argv, envp, sv, rbac_enabled, maxfd) return child; } -/* - * Flush any remaining output and restore /dev/tty to the way we found it. - * If the command died due to a signal, writes the reason to stdout. - */ void -pty_close(cstat) - struct command_status *cstat; +pty_close(struct command_status *cstat) { int n; @@ -540,17 +655,15 @@ pty_close(cstat) } } } + utmp_logout(slavename, cstat->type == CMD_WSTATUS ? cstat->val : 0); /* XXX - only if CD_SET_UTMP */ } - /* * Fill in fdsr and fdsw based on the io buffers list. * Called prior to select(). */ void -fd_set_iobs(fdsr, fdsw) - fd_set *fdsr; - fd_set *fdsw; +fd_set_iobs(fd_set *fdsr, fd_set *fdsw) { struct io_buffer *iob; @@ -579,18 +692,17 @@ fd_set_iobs(fdsr, fdsw) } } -/* - * Deliver a relayed signal to the command. - */ static void -deliver_signal(pid, signo) - pid_t pid; - int signo; +deliver_signal(pid_t pid, int signo) { int status; /* Handle signal from parent. */ + sudo_debug(8, "signal %d from parent", signo); switch (signo) { + case SIGALRM: + terminate_child(pid, TRUE); + break; case SIGCONT_FG: /* Continue in foreground, grant it controlling tty. */ do { @@ -620,9 +732,7 @@ deliver_signal(pid, signo) * Return value is the same as send(2). */ static int -send_status(fd, cstat) - int fd; - struct command_status *cstat; +send_status(int fd, struct command_status *cstat) { int n = -1; @@ -630,6 +740,11 @@ send_status(fd, cstat) do { n = send(fd, cstat, sizeof(*cstat), 0); } while (n == -1 && errno == EINTR); + if (n != sizeof(*cstat)) { + sudo_debug(8, "unable to send status to parent: %s", strerror(errno)); + } else { + sudo_debug(8, "sent status to parent"); + } cstat->type = CMD_INVALID; /* prevent re-sending */ } return n; @@ -642,31 +757,33 @@ send_status(fd, cstat) * Returns TRUE if child is still alive, else FALSE. */ static int -handle_sigchld(backchannel, cstat) - int backchannel; - struct command_status *cstat; +handle_sigchld(int backchannel, struct command_status *cstat) { int status, alive = TRUE; pid_t pid; /* read child status */ do { -#ifdef sudo_waitpid - pid = sudo_waitpid(child, &status, WUNTRACED|WNOHANG); -#else - pid = wait(&status); -#endif + pid = waitpid(child, &status, WUNTRACED|WNOHANG); } while (pid == -1 && errno == EINTR); if (pid == child) { if (cstat->type != CMD_ERRNO) { cstat->type = CMD_WSTATUS; cstat->val = status; if (WIFSTOPPED(status)) { + sudo_debug(8, "command stopped, signal %d", + WSTOPSIG(status)); do { child_pgrp = tcgetpgrp(io_fds[SFD_SLAVE]); } while (child_pgrp == -1 && errno == EINTR); if (send_status(backchannel, cstat) == -1) return alive; /* XXX */ + } else if (WIFSIGNALED(status)) { + sudo_debug(8, "command killed, signal %d", + WTERMSIG(status)); + } else { + sudo_debug(8, "command exited: %d", + WEXITSTATUS(status)); } } if (!WIFSTOPPED(status)) @@ -683,12 +800,7 @@ handle_sigchld(backchannel, cstat) * Returns an error if fork(2) fails, else calls _exit(2). */ static int -exec_monitor(path, argv, envp, backchannel, rbac) - const char *path; - char *argv[]; - char *envp[]; - int backchannel; - int rbac; +exec_monitor(struct command_details *details, int backchannel) { struct command_status cstat; struct timeval tv; @@ -711,12 +823,13 @@ exec_monitor(path, argv, envp, backchannel, rbac) if (pipe_nonblock(signal_pipe) != 0) error(1, "cannot create pipe"); - /* Reset SIGWINCH. */ + /* Reset SIGWINCH and SIGALRM. */ zero_bytes(&sa, sizeof(sa)); sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; sa.sa_handler = SIG_DFL; sigaction(SIGWINCH, &sa, NULL); + sigaction(SIGALRM, &sa, NULL); /* Ignore any SIGTTIN or SIGTTOU we get. */ sa.sa_handler = SIG_IGN; @@ -775,7 +888,7 @@ exec_monitor(path, argv, envp, backchannel, rbac) restore_signals(); /* setup tty and exec command */ - exec_pty(path, argv, envp, rbac); + exec_pty(details); cstat.type = CMD_ERRNO; cstat.val = errno; if (write(errpipe[1], &cstat, sizeof(cstat)) == -1) @@ -899,7 +1012,7 @@ bad: * Does not read from /dev/tty. */ static void -flush_output() +flush_output(void) { struct io_buffer *iob; struct timeval tv; @@ -972,11 +1085,7 @@ flush_output() * Returns only if execve() fails. */ static void -exec_pty(path, argv, envp, rbac_enabled) - const char *path; - char *argv[]; - char *envp[]; - int rbac_enabled; +exec_pty(struct command_details *details) { pid_t self = getpid(); @@ -1005,22 +1114,21 @@ exec_pty(path, argv, envp, rbac_enabled) if (io_fds[SFD_STDERR] != io_fds[SFD_SLAVE]) close(io_fds[SFD_STDERR]); - closefrom(def_closefrom); + if (details->closefrom >= 0) + closefrom(details->closefrom); #ifdef HAVE_SELINUX - if (rbac_enabled) - selinux_execve(path, argv, envp); + if (ISSET(details->flags, CD_RBAC_ENABLED)) + selinux_execve(details->command, details->argv, details->envp); else #endif - my_execve(path, argv, envp); + my_execve(details->command, details->argv, details->envp); } /* * Propagates tty size change signals to pty being used by the command. */ static void -sync_ttysize(src, dst) - int src; - int dst; +sync_ttysize(int src, int dst) { #ifdef TIOCGWINSZ struct winsize wsize; @@ -1038,8 +1146,7 @@ sync_ttysize(src, dst) * Handler for SIGWINCH in parent. */ static void -sigwinch(s) - int s; +sigwinch(int s) { int serrno = errno; @@ -1052,8 +1159,7 @@ sigwinch(s) * Return value is the same as send(2). */ static int -safe_close(fd) - int fd; +safe_close(int fd) { /* Avoid closing /dev/tty or std{in,out,err}. */ if (fd < 3 || fd == io_fds[SFD_USERTTY]) { diff --git a/get_pty.c b/src/get_pty.c similarity index 84% rename from get_pty.c rename to src/get_pty.c index 8549794..4bac6b9 100644 --- a/get_pty.c +++ b/src/get_pty.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009-2010 Todd C. Miller + * Copyright (c) 2009-2011 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -57,20 +57,13 @@ #if defined(HAVE_OPENPTY) int -get_pty(master, slave, name, namesz, ttyuid) - int *master; - int *slave; - char *name; - size_t namesz; - uid_t ttyuid; +get_pty(int *master, int *slave, char *name, size_t namesz, uid_t ttyuid) { struct group *gr; gid_t ttygid = -1; - if ((gr = sudo_getgrnam("tty")) != NULL) { + if ((gr = getgrnam("tty")) != NULL) ttygid = gr->gr_gid; - gr_delref(gr); - } if (openpty(master, slave, name, NULL, NULL) != 0) return 0; @@ -81,12 +74,7 @@ get_pty(master, slave, name, namesz, ttyuid) #elif defined(HAVE__GETPTY) int -get_pty(master, slave, name, namesz, ttyuid) - int *master; - int *slave; - char *name; - size_t namesz; - uid_t ttyuid; +get_pty(int *master, int *slave, char *name, size_t namesz, uid_t ttyuid) { char *line; @@ -106,8 +94,7 @@ get_pty(master, slave, name, namesz, ttyuid) #elif defined(HAVE_GRANTPT) # ifndef HAVE_POSIX_OPENPT static int -posix_openpt(oflag) - int oflag; +posix_openpt(int oflag) { int fd; @@ -121,12 +108,7 @@ posix_openpt(oflag) # endif /* HAVE_POSIX_OPENPT */ int -get_pty(master, slave, name, namesz, ttyuid) - int *master; - int *slave; - char *name; - size_t namesz; - uid_t ttyuid; +get_pty(int *master, int *slave, char *name, size_t namesz, uid_t ttyuid) { char *line; @@ -163,18 +145,13 @@ get_pty(master, slave, name, namesz, ttyuid) static char line[] = "/dev/ptyXX"; int -get_pty(master, slave, name, namesz, ttyuid) - int *master; - int *slave; - char *name; - size_t namesz; - uid_t ttyuid; +get_pty(int *master, int *slave, char *name, size_t namesz, uid_t ttyuid) { char *bank, *cp; struct group *gr; gid_t ttygid = -1; - if ((gr = sudo_getgrnam("tty")) != NULL) + if ((gr = getgrnam("tty")) != NULL) ttygid = gr->gr_gid; for (bank = "pqrs"; *bank != '\0'; bank++) { diff --git a/src/load_plugins.c b/src/load_plugins.c new file mode 100644 index 0000000..68be423 --- /dev/null +++ b/src/load_plugins.c @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2009-2011 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#ifdef HAVE_DLOPEN +# include +#else +# include "compat/dlfcn.h" +#endif +#include + +#include "sudo.h" +#include "sudo_plugin.h" +#include "sudo_plugin_int.h" + +#ifndef RTLD_LOCAL +# define RTLD_LOCAL 0 +#endif + +const char *noexec_path = _PATH_SUDO_NOEXEC; + +/* + * Read in /etc/sudo.conf + * Returns a list of plugins. + */ +static struct plugin_info_list * +sudo_read_conf(const char *conf_file) +{ + FILE *fp; + char *cp, *name, *path; + struct plugin_info *info; + static struct plugin_info_list pil; /* XXX */ + + if ((fp = fopen(conf_file, "r")) == NULL) + goto done; + + while ((cp = sudo_parseln(fp)) != NULL) { + /* Skip blank or comment lines */ + if (*cp == '\0') + continue; + + /* Look for a line starting with "Path" */ + if (strncasecmp(cp, "Path", 4) == 0) { + /* Parse line */ + if ((name = strtok(cp + 4, " \t")) == NULL || + (path = strtok(NULL, " \t")) == NULL) { + continue; + } + if (strcasecmp(name, "askpass") == 0) + askpass_path = estrdup(path); + else if (strcasecmp(name, "noexec") == 0) + noexec_path = estrdup(path); + continue; + } + + /* Look for a line starting with "Plugin" */ + if (strncasecmp(cp, "Plugin", 6) == 0) { + /* Parse line */ + if ((name = strtok(cp + 6, " \t")) == NULL || + (path = strtok(NULL, " \t")) == NULL) { + continue; + } + info = emalloc(sizeof(*info)); + info->symbol_name = estrdup(name); + info->path = estrdup(path); + info->prev = info; + info->next = NULL; + tq_append(&pil, info); + continue; + } + } + fclose(fp); + +done: + if (tq_empty(&pil)) { + /* Default policy plugin */ + info = emalloc(sizeof(*info)); + info->symbol_name = "sudoers_policy"; + info->path = SUDOERS_PLUGIN; + info->prev = info; + info->next = NULL; + tq_append(&pil, info); + + /* Default I/O plugin */ + info = emalloc(sizeof(*info)); + info->symbol_name = "sudoers_io"; + info->path = SUDOERS_PLUGIN; + info->prev = info; + info->next = NULL; + tq_append(&pil, info); + } + + return &pil; +} + +/* + * Load the plugins listed in conf_file. + */ +int +sudo_load_plugins(const char *conf_file, + struct plugin_container *policy_plugin, + struct plugin_container_list *io_plugins) +{ + struct generic_plugin *plugin; + struct plugin_container *container; + struct plugin_info *info; + struct plugin_info_list *plugin_list; + struct stat sb; + void *handle; + char path[PATH_MAX]; + int rval = FALSE; + + /* Parse sudo.conf */ + plugin_list = sudo_read_conf(conf_file); + + tq_foreach_fwd(plugin_list, info) { + if (info->path[0] == '/') { + if (strlcpy(path, info->path, sizeof(path)) >= sizeof(path)) { + warningx("%s: %s", info->path, strerror(ENAMETOOLONG)); + goto done; + } + } else { + if (snprintf(path, sizeof(path), "%s%s", _PATH_SUDO_PLUGIN_DIR, + info->path) >= sizeof(path)) { + warningx("%s%s: %s", _PATH_SUDO_PLUGIN_DIR, info->path, + strerror(ENAMETOOLONG)); + goto done; + } + } + if (stat(path, &sb) != 0) { + warning("%s", path); + goto done; + } + if (sb.st_uid != ROOT_UID) { + warningx("%s must be owned by uid %d", path, ROOT_UID); + goto done; + } + if ((sb.st_mode & (S_IWGRP|S_IWOTH)) != 0) { + warningx("%s must be only be writable by owner", path); + goto done; + } + + /* Open plugin and map in symbol */ + handle = dlopen(path, RTLD_LAZY|RTLD_LOCAL); + if (!handle) { + warningx("unable to dlopen %s: %s", path, dlerror()); + goto done; + } + plugin = dlsym(handle, info->symbol_name); + if (!plugin) { + warningx("unable to find symbol %s in %s", info->symbol_name, path); + goto done; + } + + if (plugin->type != SUDO_POLICY_PLUGIN && plugin->type != SUDO_IO_PLUGIN) { + warningx("%s: unknown policy type %d", path, plugin->type); + goto done; + } + if (SUDO_API_VERSION_GET_MAJOR(plugin->version) != SUDO_API_VERSION_MAJOR) { + warningx("%s: incompatible policy major version %d, expected %d", + path, SUDO_API_VERSION_GET_MAJOR(plugin->version), + SUDO_API_VERSION_MAJOR); + goto done; + } + if (plugin->type == SUDO_POLICY_PLUGIN) { + if (policy_plugin->handle) { + warningx("only a single policy plugin may be loaded"); + goto done; + } + policy_plugin->handle = handle; + policy_plugin->name = info->symbol_name; + policy_plugin->u.generic = plugin; + } else if (plugin->type == SUDO_IO_PLUGIN) { + container = emalloc(sizeof(*container)); + container->prev = container; + container->next = NULL; + container->handle = handle; + container->name = info->symbol_name; + container->u.generic = plugin; + tq_append(io_plugins, container); + } + } + if (policy_plugin->handle == NULL) { + warningx("%s: at least one policy plugin must be specified", conf_file); + goto done; + } + if (policy_plugin->u.policy->check_policy == NULL) { + warningx("policy plugin %s does not include a check_policy method", + policy_plugin->name); + goto done; + } + + rval = TRUE; + +done: + return rval; +} diff --git a/interfaces.c b/src/net_ifs.c similarity index 62% rename from interfaces.c rename to src/net_ifs.c index 502cb94..f6de080 100644 --- a/interfaces.c +++ b/src/net_ifs.c @@ -80,41 +80,48 @@ struct rtentry; # include #endif -#include "sudo.h" -#include "interfaces.h" +#include "missing.h" +#include "alloc.h" +#include "error.h" /* Minix apparently lacks IFF_LOOPBACK */ #ifndef IFF_LOOPBACK # define IFF_LOOPBACK 0 #endif +#ifndef INET6_ADDRSTRLEN +# define INET6_ADDRSTRLEN 46 +#endif + #ifdef HAVE_GETIFADDRS /* - * Allocate and fill in the interfaces global variable with the - * machine's ip addresses and netmasks. + * Fill in the interfaces string with the machine's ip addresses and netmasks + * and return the number of interfaces found. */ -void -load_interfaces() +int +get_net_ifs(char **addrinfo) { struct ifaddrs *ifa, *ifaddrs; struct sockaddr_in *sin; #ifdef HAVE_IN6_ADDR struct sockaddr_in6 *sin6; + char addrbuf[INET6_ADDRSTRLEN]; #endif - int i; + int ailen, i, len, num_interfaces = 0; + char *cp; if (getifaddrs(&ifaddrs)) - return; + return 0; - /* Allocate space for the interfaces list. */ + /* Allocate space for the interfaces info string. */ for (ifa = ifaddrs; ifa != NULL; ifa = ifa -> ifa_next) { /* Skip interfaces marked "down" and "loopback". */ - if (ifa->ifa_addr == NULL || !ISSET(ifa->ifa_flags, IFF_UP) || - ISSET(ifa->ifa_flags, IFF_LOOPBACK)) + if (ifa->ifa_addr == NULL || ifa->ifa_netmask == NULL || + !ISSET(ifa->ifa_flags, IFF_UP) || ISSET(ifa->ifa_flags, IFF_LOOPBACK)) continue; - switch(ifa->ifa_addr->sa_family) { + switch (ifa->ifa_addr->sa_family) { case AF_INET: #ifdef HAVE_IN6_ADDR case AF_INET6: @@ -124,55 +131,70 @@ load_interfaces() } } if (num_interfaces == 0) - return; - interfaces = - (struct interface *) emalloc2(num_interfaces, sizeof(struct interface)); + return 0; + ailen = num_interfaces * 2 * INET6_ADDRSTRLEN; + *addrinfo = cp = emalloc(ailen); - /* Store the ip addr / netmask pairs. */ + /* Store the IP addr/netmask pairs. */ for (ifa = ifaddrs, i = 0; ifa != NULL; ifa = ifa -> ifa_next) { /* Skip interfaces marked "down" and "loopback". */ - if (ifa->ifa_addr == NULL || !ISSET(ifa->ifa_flags, IFF_UP) || - ISSET(ifa->ifa_flags, IFF_LOOPBACK)) + if (ifa->ifa_addr == NULL || ifa->ifa_netmask == NULL || + !ISSET(ifa->ifa_flags, IFF_UP) || ISSET(ifa->ifa_flags, IFF_LOOPBACK)) continue; - switch(ifa->ifa_addr->sa_family) { + switch (ifa->ifa_addr->sa_family) { case AF_INET: sin = (struct sockaddr_in *)ifa->ifa_addr; - if (sin == NULL) - continue; - memcpy(&interfaces[i].addr, &sin->sin_addr, - sizeof(struct in_addr)); + len = snprintf(cp, ailen - (*addrinfo - cp), + "%s%s/", cp == *addrinfo ? "" : " ", + inet_ntoa(sin->sin_addr)); + if (len <= 0 || len >= ailen - (*addrinfo - cp)) { + warningx("load_interfaces: overflow detected"); + goto done; + } + cp += len; + sin = (struct sockaddr_in *)ifa->ifa_netmask; - if (sin == NULL) - continue; - memcpy(&interfaces[i].netmask, &sin->sin_addr, - sizeof(struct in_addr)); - interfaces[i].family = AF_INET; - i++; + len = snprintf(cp, ailen - (*addrinfo - cp), + "%s", inet_ntoa(sin->sin_addr)); + if (len <= 0 || len >= ailen - (*addrinfo - cp)) { + warningx("load_interfaces: overflow detected"); + goto done; + } + cp += len; break; #ifdef HAVE_IN6_ADDR case AF_INET6: sin6 = (struct sockaddr_in6 *)ifa->ifa_addr; - if (sin6 == NULL) - continue; - memcpy(&interfaces[i].addr, &sin6->sin6_addr, - sizeof(struct in6_addr)); + inet_ntop(AF_INET6, &sin6->sin6_addr, addrbuf, sizeof(addrbuf)); + len = snprintf(cp, ailen - (*addrinfo - cp), + "%s%s/", cp == *addrinfo ? "" : " ", addrbuf); + if (len <= 0 || len >= ailen - (*addrinfo - cp)) { + warningx("load_interfaces: overflow detected"); + goto done; + } + cp += len; + sin6 = (struct sockaddr_in6 *)ifa->ifa_netmask; - if (sin6 == NULL) - continue; - memcpy(&interfaces[i].netmask, &sin6->sin6_addr, - sizeof(struct in6_addr)); - interfaces[i].family = AF_INET6; - i++; + inet_ntop(AF_INET6, &sin6->sin6_addr, addrbuf, sizeof(addrbuf)); + len = snprintf(cp, ailen - (*addrinfo - cp), "%s", addrbuf); + if (len <= 0 || len >= ailen - (*addrinfo - cp)) { + warningx("load_interfaces: overflow detected"); + goto done; + } + cp += len; break; #endif /* HAVE_IN6_ADDR */ } } + +done: #ifdef HAVE_FREEIFADDRS freeifaddrs(ifaddrs); #else efree(ifaddrs); #endif + return num_interfaces; } #elif defined(SIOCGIFCONF) && !defined(STUB_LOAD_INTERFACES) @@ -181,15 +203,15 @@ load_interfaces() * Allocate and fill in the interfaces global variable with the * machine's ip addresses and netmasks. */ -void -load_interfaces() +int +get_net_ifs(char **addrinfo) { struct ifconf *ifconf; struct ifreq *ifr, ifr_tmp; struct sockaddr_in *sin; - int sock, n, i; - size_t len = sizeof(struct ifconf) + BUFSIZ; - char *previfname = "", *ifconf_buf = NULL; + int ailen, i, len, n, sock, num_interfaces = 0; + size_t buflen = sizeof(struct ifconf) + BUFSIZ; + char *cp, *previfname = "", *ifconf_buf = NULL; #ifdef _ISC struct strioctl strioctl; #endif /* _ISC */ @@ -199,36 +221,35 @@ load_interfaces() error(1, "cannot open socket"); /* - * Get interface configuration or return (leaving num_interfaces == 0) + * Get interface configuration or return. */ for (;;) { - ifconf_buf = erealloc(ifconf_buf, len); + ifconf_buf = emalloc(buflen); ifconf = (struct ifconf *) ifconf_buf; - ifconf->ifc_len = len - sizeof(struct ifconf); + ifconf->ifc_len = buflen - sizeof(struct ifconf); ifconf->ifc_buf = (caddr_t) (ifconf_buf + sizeof(struct ifconf)); #ifdef _ISC - STRSET(SIOCGIFCONF, (caddr_t) ifconf, len); - if (ioctl(sock, I_STR, (caddr_t) &strioctl) < 0) { + STRSET(SIOCGIFCONF, (caddr_t) ifconf, buflen); + if (ioctl(sock, I_STR, (caddr_t) &strioctl) < 0) #else /* Note that some kernels return EINVAL if the buffer is too small */ - if (ioctl(sock, SIOCGIFCONF, (caddr_t) ifconf) < 0 && errno != EINVAL) { + if (ioctl(sock, SIOCGIFCONF, (caddr_t) ifconf) < 0 && errno != EINVAL) #endif /* _ISC */ - efree(ifconf_buf); - (void) close(sock); - return; - } + goto done; /* Break out of loop if we have a big enough buffer. */ - if (ifconf->ifc_len + sizeof(struct ifreq) < len) + if (ifconf->ifc_len + sizeof(struct ifreq) < buflen) break; - len += BUFSIZ; + buflen += BUFSIZ; + efree(ifconf_buf); } /* Allocate space for the maximum number of interfaces that could exist. */ if ((n = ifconf->ifc_len / sizeof(struct ifreq)) == 0) - return; - interfaces = (struct interface *) emalloc2(n, sizeof(struct interface)); + return 0; + ailen = n * 2 * INET6_ADDRSTRLEN; + *addrinfo = cp = emalloc(ailen); /* For each interface, store the ip address and netmask. */ for (i = 0; i < ifconf->ifc_len; ) { @@ -252,7 +273,7 @@ load_interfaces() continue; #ifdef SIOCGIFFLAGS - zero_bytes(&ifr_tmp, sizeof(ifr_tmp)); + memset(&ifr_tmp, 0, sizeof(ifr_tmp)); strncpy(ifr_tmp.ifr_name, ifr->ifr_name, sizeof(ifr_tmp.ifr_name) - 1); if (ioctl(sock, SIOCGIFFLAGS, (caddr_t) &ifr_tmp) < 0) #endif @@ -264,90 +285,57 @@ load_interfaces() continue; sin = (struct sockaddr_in *) &ifr->ifr_addr; - interfaces[num_interfaces].addr.ip4.s_addr = sin->sin_addr.s_addr; + len = snprintf(cp, ailen - (*addrinfo - cp), + "%s%s/", cp == *addrinfo ? "" : " ", + inet_ntoa(sin->sin_addr)); + if (len <= 0 || len >= ailen - (*addrinfo - cp)) { + warningx("load_interfaces: overflow detected"); + goto done; + } + cp += len; /* Stash the name of the interface we saved. */ previfname = ifr->ifr_name; /* Get the netmask. */ - zero_bytes(&ifr_tmp, sizeof(ifr_tmp)); + memset(&ifr_tmp, 0, sizeof(ifr_tmp)); strncpy(ifr_tmp.ifr_name, ifr->ifr_name, sizeof(ifr_tmp.ifr_name) - 1); -#ifdef SIOCGIFNETMASK #ifdef _ISC STRSET(SIOCGIFNETMASK, (caddr_t) &ifr_tmp, sizeof(ifr_tmp)); - if (ioctl(sock, I_STR, (caddr_t) &strioctl) == 0) { + if (ioctl(sock, I_STR, (caddr_t) &strioctl) < 0) { #else - if (ioctl(sock, SIOCGIFNETMASK, (caddr_t) &ifr_tmp) == 0) { + if (ioctl(sock, SIOCGIFNETMASK, (caddr_t) &ifr_tmp) < 0) { #endif /* _ISC */ sin = (struct sockaddr_in *) &ifr_tmp.ifr_addr; - - interfaces[num_interfaces].netmask.ip4.s_addr = sin->sin_addr.s_addr; - } else { -#else - { -#endif /* SIOCGIFNETMASK */ - if (IN_CLASSC(interfaces[num_interfaces].addr.ip4.s_addr)) - interfaces[num_interfaces].netmask.ip4.s_addr = htonl(IN_CLASSC_NET); - else if (IN_CLASSB(interfaces[num_interfaces].addr.ip4.s_addr)) - interfaces[num_interfaces].netmask.ip4.s_addr = htonl(IN_CLASSB_NET); - else - interfaces[num_interfaces].netmask.ip4.s_addr = htonl(IN_CLASSA_NET); + sin->sin_addr.s_addr = htonl(IN_CLASSC_NET); } - - /* Only now can we be sure it was a good/interesting interface. */ - interfaces[num_interfaces].family = AF_INET; + sin = (struct sockaddr_in *) &ifr_tmp.ifr_addr; + len = snprintf(cp, ailen - (*addrinfo - cp), + "%s", inet_ntoa(sin->sin_addr)); + if (len <= 0 || len >= ailen - (*addrinfo - cp)) { + warningx("load_interfaces: overflow detected"); + goto done; + } + cp += len; num_interfaces++; } - /* If the expected size < real size, realloc the array. */ - if (n != num_interfaces) { - if (num_interfaces != 0) - interfaces = (struct interface *) erealloc3(interfaces, - num_interfaces, sizeof(struct interface)); - else - efree(interfaces); - } +done: efree(ifconf_buf); (void) close(sock); + + return num_interfaces; } #else /* !SIOCGIFCONF || STUB_LOAD_INTERFACES */ /* - * Stub function for those without SIOCGIFCONF + * Stub function for those without SIOCGIFCONF or getifaddrs() */ -void -load_interfaces() +int +get_net_ifs(char **addrinfo) { - return; + return 0; } #endif /* SIOCGIFCONF && !STUB_LOAD_INTERFACES */ - -void -dump_interfaces() -{ - int i; -#ifdef HAVE_IN6_ADDR - char addrbuf[INET6_ADDRSTRLEN], maskbuf[INET6_ADDRSTRLEN]; -#endif - - puts("Local IP address and netmask pairs:"); - for (i = 0; i < num_interfaces; i++) { - switch(interfaces[i].family) { - case AF_INET: - printf("\t%s / ", inet_ntoa(interfaces[i].addr.ip4)); - puts(inet_ntoa(interfaces[i].netmask.ip4)); - break; -#ifdef HAVE_IN6_ADDR - case AF_INET6: - inet_ntop(AF_INET6, &interfaces[i].addr.ip6, - addrbuf, sizeof(addrbuf)); - inet_ntop(AF_INET6, &interfaces[i].netmask.ip6, - maskbuf, sizeof(maskbuf)); - printf("\t%s / %s\n", addrbuf, maskbuf); - break; -#endif /* HAVE_IN6_ADDR */ - } - } -} diff --git a/parse_args.c b/src/parse_args.c similarity index 60% rename from parse_args.c rename to src/parse_args.c index ee4245b..e9f09e4 100644 --- a/parse_args.c +++ b/src/parse_args.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1993-1996, 1998-2010 Todd C. Miller + * Copyright (c) 1993-1996, 1998-2011 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -41,52 +41,108 @@ #ifdef HAVE_UNISTD_H # include #endif /* HAVE_UNISTD_H */ -#include +#include #include +#include +#include #include "sudo.h" #include "lbuf.h" -#include + +/* For getopt(3) */ +extern char *optarg; +extern int optind; + +int tgetpass_flags; /* - * Local functions + * Local functions. */ -static void usage_excl __P((int)); +static void help(void) __attribute__((__noreturn__)); +static void usage_excl(int); /* - * For sudo.c + * Mapping of command line flags to name/value settings. */ -extern int NewArgc; -extern char **NewArgv; -extern int user_closefrom; -extern char *runas_user; -extern char *runas_group; - -/* For getopt(3) */ -extern char *optarg; -extern int optind; - -#ifdef HAVE_BSD_AUTH_H -char *login_style; -#endif /* HAVE_BSD_AUTH_H */ +static struct sudo_settings { + const char *name; + const char *value; +} sudo_settings[] = { +#define ARG_BSDAUTH_TYPE 0 + { "bsdauth_type" }, +#define ARG_LOGIN_CLASS 1 + { "login_class" }, +#define ARG_DEBUG_LEVEL 2 + { "debug_level" }, +#define ARG_PRESERVE_ENVIRONMENT 3 + { "preserve_environment" }, +#define ARG_RUNAS_GROUP 4 + { "runas_group" }, +#define ARG_SET_HOME 5 + { "set_home" }, +#define ARG_USER_SHELL 6 + { "run_shell" }, +#define ARG_LOGIN_SHELL 7 + { "login_shell" }, +#define ARG_IGNORE_TICKET 8 + { "ignore_ticket" }, +#define ARG_PROMPT 9 + { "prompt" }, +#define ARG_SELINUX_ROLE 10 + { "selinux_role" }, +#define ARG_SELINUX_TYPE 11 + { "selinux_type" }, +#define ARG_RUNAS_USER 12 + { "runas_user" }, +#define ARG_PROGNAME 13 + { "progname" }, +#define ARG_IMPLIED_SHELL 14 + { "implied_shell" }, +#define ARG_PRESERVE_GROUPS 15 + { "preserve_groups" }, +#define ARG_NONINTERACTIVE 16 + { "noninteractive" }, +#define ARG_SUDOEDIT 17 + { "sudoedit" }, +#define ARG_CLOSEFROM 18 + { "closefrom" }, +#define ARG_NET_ADDRS 19 + { "network_addrs" }, +#define NUM_SETTINGS 20 + { NULL } +}; /* * Command line argument parsing. - * Sets NewArgc and NewArgv which corresponds to the argc/argv we'll use + * Sets nargc and nargv which corresponds to the argc/argv we'll use * for the command to be run (if we are running one). */ int -parse_args(argc, argv) - int argc; - char **argv; +parse_args(int argc, char **argv, int *nargc, char ***nargv, char ***settingsp, + char ***env_addp) { int mode = 0; /* what mode is sudo to be run in? */ int flags = 0; /* mode flags */ int valid_flags, ch; + int i, j; + char *cp, **env_add, **settings; + int nenv = 0; + int env_size = 32; + + env_add = emalloc2(env_size, sizeof(char *)); + + /* Pass progname to plugin so it can call setprogname() */ + sudo_settings[ARG_PROGNAME].value = getprogname(); /* First, check to see if we were invoked as "sudoedit". */ - if (strcmp(getprogname(), "sudoedit") == 0) + if (strcmp(getprogname(), "sudoedit") == 0) { mode = MODE_EDIT; + sudo_settings[ARG_SUDOEDIT].value = "true"; + } + + /* Load local IP addresses and masks. */ + if (get_net_ifs(&cp) > 0) + sudo_settings[ARG_NET_ADDRS].value = cp; /* Returns true if the last option string was "--" */ #define got_end_of_args (optind > 1 && argv[optind - 1][0] == '-' && \ @@ -98,53 +154,62 @@ parse_args(argc, argv) /* Flags allowed when running a command */ valid_flags = MODE_BACKGROUND|MODE_PRESERVE_ENV|MODE_RESET_HOME| - MODE_LOGIN_SHELL|MODE_INVALIDATE|MODE_NONINTERACTIVE| - MODE_PRESERVE_GROUPS|MODE_SHELL; + MODE_LOGIN_SHELL|MODE_NONINTERACTIVE|MODE_SHELL; + /* XXX - should fill in settings at the end to avoid dupes */ for (;;) { /* * We disable arg permutation for GNU getopt(). * Some trickiness is required to allow environment variables * to be interspersed with command line options. */ - if ((ch = getopt(argc, argv, "+Aa:bC:c:Eeg:HhiKkLlnPp:r:Sst:U:u:Vv")) != -1) { + if ((ch = getopt(argc, argv, "+Aa:bC:c:D:Eeg:HhiKklnPp:r:Sst:U:u:Vv")) != -1) { switch (ch) { case 'A': SET(tgetpass_flags, TGP_ASKPASS); break; #ifdef HAVE_BSD_AUTH_H case 'a': - login_style = optarg; + sudo_settings[ARG_BSDAUTH_TYPE].value = optarg; break; #endif case 'b': SET(flags, MODE_BACKGROUND); break; case 'C': - if ((user_closefrom = atoi(optarg)) < 3) { + if (atoi(optarg) < 3) { warningx("the argument to -C must be a number greater than or equal to 3"); usage(1); } + sudo_settings[ARG_CLOSEFROM].value = optarg; break; #ifdef HAVE_LOGIN_CAP_H case 'c': - login_class = optarg; - def_use_loginclass = TRUE; + sudo_settings[ARG_LOGIN_CLASS].value = optarg; break; #endif + case 'D': + if ((debug_level = atoi(optarg)) < 1 || debug_level > 9) { + warningx("the argument to -D must be between 1 and 9 inclusive"); + usage(1); + } + sudo_settings[ARG_DEBUG_LEVEL].value = optarg; + break; case 'E': - SET(flags, MODE_PRESERVE_ENV); + sudo_settings[ARG_PRESERVE_ENVIRONMENT].value = "true"; break; case 'e': if (mode && mode != MODE_EDIT) usage_excl(1); mode = MODE_EDIT; - valid_flags = MODE_INVALIDATE|MODE_NONINTERACTIVE; + sudo_settings[ARG_SUDOEDIT].value = "true"; + valid_flags = MODE_NONINTERACTIVE; break; case 'g': runas_group = optarg; + sudo_settings[ARG_RUNAS_GROUP].value = optarg; break; case 'H': - SET(flags, MODE_RESET_HOME); + sudo_settings[ARG_SET_HOME].value = "true"; break; case 'h': if (mode && mode != MODE_HELP) { @@ -155,70 +220,68 @@ parse_args(argc, argv) valid_flags = 0; break; case 'i': + sudo_settings[ARG_LOGIN_SHELL].value = "true"; SET(flags, MODE_LOGIN_SHELL); - def_env_reset = TRUE; break; case 'k': - SET(flags, MODE_INVALIDATE); + sudo_settings[ARG_IGNORE_TICKET].value = "true"; break; case 'K': + sudo_settings[ARG_IGNORE_TICKET].value = "true"; if (mode && mode != MODE_KILL) usage_excl(1); mode = MODE_KILL; valid_flags = 0; break; - case 'L': - if (mode && mode != MODE_LISTDEFS) - usage_excl(1); - mode = MODE_LISTDEFS; - valid_flags = MODE_INVALIDATE|MODE_NONINTERACTIVE; - break; case 'l': if (mode) { if (mode == MODE_LIST) - long_list = 1; + SET(flags, MODE_LONG_LIST); else usage_excl(1); } mode = MODE_LIST; - valid_flags = MODE_INVALIDATE|MODE_NONINTERACTIVE; + valid_flags = MODE_NONINTERACTIVE|MODE_LONG_LIST; break; case 'n': SET(flags, MODE_NONINTERACTIVE); + sudo_settings[ARG_NONINTERACTIVE].value = "true"; break; case 'P': - SET(flags, MODE_PRESERVE_GROUPS); + sudo_settings[ARG_PRESERVE_GROUPS].value = "true"; break; case 'p': - user_prompt = optarg; - def_passprompt_override = TRUE; + sudo_settings[ARG_PROMPT].value = optarg; break; #ifdef HAVE_SELINUX case 'r': - user_role = optarg; + sudo_settings[ARG_SELINUX_ROLE].value = optarg; break; case 't': - user_type = optarg; + sudo_settings[ARG_SELINUX_TYPE].value = optarg; break; #endif case 'S': SET(tgetpass_flags, TGP_STDIN); break; case 's': + sudo_settings[ARG_USER_SHELL].value = "true"; SET(flags, MODE_SHELL); break; case 'U': - if ((list_pw = sudo_getpwnam(optarg)) == NULL) + if ((getpwnam(optarg)) == NULL) errorx(1, "unknown user: %s", optarg); + list_user = optarg; break; case 'u': runas_user = optarg; + sudo_settings[ARG_RUNAS_USER].value = optarg; break; case 'v': if (mode && mode != MODE_VALIDATE) usage_excl(1); mode = MODE_VALIDATE; - valid_flags = MODE_INVALIDATE|MODE_NONINTERACTIVE; + valid_flags = MODE_NONINTERACTIVE; break; case 'V': if (mode && mode != MODE_VERSION) @@ -230,13 +293,11 @@ parse_args(argc, argv) usage(1); } } else if (!got_end_of_args && is_envar) { - struct list_member *ev; - - /* Store environment variable. */ - ev = emalloc(sizeof(*ev)); - ev->value = argv[optind]; - ev->next = sudo_user.env_vars; - sudo_user.env_vars = ev; + if (nenv == env_size - 2) { + env_size *= 2; + env_add = erealloc3(env_add, env_size, sizeof(char *)); + } + env_add[nenv++] = argv[optind]; /* Crank optind and resume getopt. */ optind++; @@ -245,22 +306,25 @@ parse_args(argc, argv) break; } } + env_add[nenv] = NULL; - NewArgc = argc - optind; - NewArgv = argv + optind; + argc -= optind; + argv += optind; if (!mode) { /* Defer -k mode setting until we know whether it is a flag or not */ - if (ISSET(flags, MODE_INVALIDATE) && NewArgc == 0) { - mode = MODE_INVALIDATE; /* -k by itself */ - CLR(flags, MODE_INVALIDATE); - valid_flags = 0; - } else { - mode = MODE_RUN; /* running a command */ + if (sudo_settings[ARG_IGNORE_TICKET].value != NULL) { + if (argc == 0) { + mode = MODE_INVALIDATE; /* -k by itself */ + sudo_settings[ARG_IGNORE_TICKET].value = NULL; + valid_flags = 0; + } } + if (!mode) + mode = MODE_RUN; /* running a command */ } - if (NewArgc > 0 && mode == MODE_LIST) + if (argc > 0 && mode == MODE_LIST) mode = MODE_CHECK; if (ISSET(flags, MODE_LOGIN_SHELL)) { @@ -277,10 +341,10 @@ parse_args(argc, argv) if ((flags & valid_flags) != flags) usage(1); if (mode == MODE_EDIT && - (ISSET(flags, MODE_PRESERVE_ENV) || sudo_user.env_vars != NULL)) { + (ISSET(flags, MODE_PRESERVE_ENV) || env_add[0] != NULL)) { if (ISSET(mode, MODE_PRESERVE_ENV)) warningx("the `-E' option is not valid in edit mode"); - if (sudo_user.env_vars != NULL) + if (env_add[0] != NULL) warningx("you may not specify environment variables in edit mode"); usage(1); } @@ -288,7 +352,7 @@ parse_args(argc, argv) !ISSET(mode, MODE_EDIT | MODE_RUN | MODE_CHECK | MODE_VALIDATE)) { usage(1); } - if (list_pw != NULL && mode != MODE_LIST && mode != MODE_CHECK) { + if (list_user != NULL && mode != MODE_LIST && mode != MODE_CHECK) { warningx("the `-U' option may only be used with the `-l' option"); usage(1); } @@ -296,25 +360,93 @@ parse_args(argc, argv) warningx("the `-A' and `-S' options may not be used together"); usage(1); } - if ((NewArgc == 0 && mode == MODE_EDIT) || - (NewArgc > 0 && !ISSET(mode, MODE_RUN | MODE_EDIT | MODE_CHECK))) + if ((argc == 0 && mode == MODE_EDIT) || + (argc > 0 && !ISSET(mode, MODE_RUN | MODE_EDIT | MODE_CHECK))) usage(1); - if (NewArgc == 0 && mode == MODE_RUN && !ISSET(flags, MODE_SHELL)) + if (argc == 0 && mode == MODE_RUN && !ISSET(flags, MODE_SHELL)) { SET(flags, (MODE_IMPLIED_SHELL | MODE_SHELL)); + sudo_settings[ARG_IMPLIED_SHELL].value = "true"; + } + + if (mode == MODE_HELP) + help(); + + /* + * For shell mode we need to rewrite argv + */ + if (ISSET(mode, MODE_RUN) && ISSET(flags, MODE_SHELL)) { + char **av; + int ac; + + if (argc == 0) { + /* just the shell */ + ac = argc + 1; + av = emalloc2(ac + 1, sizeof(char *)); + memcpy(av + 1, argv, argc * sizeof(char *)); + } else { + /* shell -c "command" */ + char *src, *dst, *end; + size_t cmnd_size = (size_t) (argv[argc - 1] - argv[0]) + + strlen(argv[argc - 1]) + 1; + ac = 3; + av = emalloc2(ac + 1, sizeof(char *)); + av[1] = "-c"; + av[2] = dst = emalloc(cmnd_size); + src = argv[0]; + for (end = src + cmnd_size - 1; src < end; src++, dst++) + *dst = *src == '\0' ? ' ' : *src; + *dst = '\0'; + } + av[0] = (char *)user_details.shell; /* plugin may override shell */ + av[ac] = NULL; + + argv = av; + argc = ac; + } + /* + * Format setting_pairs into settings array. + */ + settings = emalloc2(NUM_SETTINGS + 1, sizeof(char *)); + for (i = 0, j = 0; i < NUM_SETTINGS; i++) { + if (sudo_settings[i].value) { + sudo_debug(9, "settings: %s=%s", sudo_settings[i].name, + sudo_settings[i].value); + settings[j] = fmt_string(sudo_settings[i].name, + sudo_settings[i].value); + if (settings[j] == NULL) + errorx(1, "unable to allocate memory"); + j++; + } + } + settings[j] = NULL; + + if (mode == MODE_EDIT) { +#if defined(HAVE_SETRESUID) || defined(HAVE_SETREUID) || defined(HAVE_SETEUID) + /* Must have the command in argv[0]. */ + argc++; + argv--; + argv[0] = "sudoedit"; +#else + errorx(1, "sudoedit is not supported on this platform"); +#endif + } + + *settingsp = settings; + *env_addp = env_add; + *nargc = argc; + *nargv = argv; return mode | flags; } static int -usage_err(buf) - const char *buf; +usage_err(const char *buf) { return fputs(buf, stderr); } static int -usage_out(buf) - const char *buf; +usage_out(const char *buf) { return fputs(buf, stdout); } @@ -324,8 +456,7 @@ usage_out(buf) * The actual usage strings are in sudo_usage.h for configure substitution. */ void -usage(fatal) - int fatal; +usage(int fatal) { struct lbuf lbuf; char *uvec[6]; @@ -351,7 +482,8 @@ usage(fatal) * tty width. */ ulen = (int)strlen(getprogname()) + 8; - lbuf_init(&lbuf, fatal ? usage_err : usage_out, ulen, NULL); + lbuf_init(&lbuf, fatal ? usage_err : usage_out, ulen, NULL, + user_details.ts_cols); for (i = 0; uvec[i] != NULL; i++) { lbuf_append(&lbuf, "usage: ", getprogname(), uvec[i], NULL); lbuf_print(&lbuf); @@ -365,21 +497,20 @@ usage(fatal) * Tell which options are mutually exclusive and exit. */ static void -usage_excl(fatal) - int fatal; +usage_excl(int fatal) { warningx("Only one of the -e, -h, -i, -K, -l, -s, -v or -V options may be specified"); usage(fatal); } -void -help() +static void +help(void) { struct lbuf lbuf; int indent = 16; const char *pname = getprogname(); - lbuf_init(&lbuf, usage_out, indent, NULL); + lbuf_init(&lbuf, usage_out, indent, NULL, user_details.ts_cols); if (strcmp(pname, "sudoedit") == 0) lbuf_append(&lbuf, pname, " - edit files as another user\n\n", NULL); else @@ -421,8 +552,6 @@ help() " -K remove timestamp file completely\n", NULL); lbuf_append(&lbuf, " -k invalidate timestamp file\n", NULL); - lbuf_append(&lbuf, - " -L list supported sudoers Defaults values\n", NULL); lbuf_append(&lbuf, " -l[l] command list user's available commands\n", NULL); lbuf_append(&lbuf, diff --git a/src/preload.c b/src/preload.c new file mode 100644 index 0000000..9e77f0b --- /dev/null +++ b/src/preload.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2010 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include "sudo_plugin.h" + +extern struct policy_plugin sudoers_policy; +extern struct io_plugin sudoers_io; + +struct sudo_preload_table { + const char *name; + void *address; +} sudo_preload_table[] = { + { "sudoers_policy", (void *) &sudoers_policy}, + { "sudoers_io", (void *) &sudoers_io}, + { NULL, NULL } +}; diff --git a/selinux.c b/src/selinux.c similarity index 87% rename from selinux.c rename to src/selinux.c index 2c03e6c..b5c3dc8 100644 --- a/selinux.c +++ b/src/selinux.c @@ -36,9 +36,6 @@ #include #include #include -#ifdef HAVE_LINUX_AUDIT -#include -#endif #include /* for SECCLASS_CHR_FILE */ #include /* for is_selinux_enabled() */ @@ -46,8 +43,11 @@ #include #include +#ifdef HAVE_LINUX_AUDIT +# include +#endif + #include "sudo.h" -#include "linux_audit.h" static struct selinux_state { security_context_t old_context; @@ -59,6 +59,38 @@ static struct selinux_state { int enforcing; } se_state; +#ifdef HAVE_LINUX_AUDIT +static int +audit_role_change(const security_context_t old_context, + const security_context_t new_context, const char *ttyn) +{ + int au_fd, rc; + char *message; + + au_fd = audit_open(); + if (au_fd == -1) { + /* Kernel may not have audit support. */ + if (errno != EINVAL && errno != EPROTONOSUPPORT && errno != EAFNOSUPPORT +) + error(1, "unable to open audit system"); + return -1; + } + + /* audit role change using the same format as newrole(1) */ + easprintf(&message, "newrole: old-context=%s new-context=%s", + old_context, new_context); + rc = audit_log_user_message(au_fd, AUDIT_USER_ROLE_CHANGE, + message, NULL, NULL, ttyn, 1); + if (rc <= 0) + warning("unable to send audit message"); + + efree(message); + close(au_fd); + + return rc; +} +#endif + /* * This function attempts to revert the relabeling done to the tty. * fd - referencing the opened ttyn @@ -315,7 +347,7 @@ selinux_setup(const char *role, const char *type, const char *ttyn, #endif #ifdef HAVE_LINUX_AUDIT - linux_audit_role_change(se_state.old_context, se_state.new_context, + audit_role_change(se_state.old_context, se_state.new_context, se_state.ttyn); #endif @@ -328,6 +360,9 @@ done: void selinux_execve(const char *path, char *argv[], char *envp[]) { + char **nargv; + int argc, serrno; + if (setexeccon(se_state.new_context)) { warning("unable to set exec context to %s", se_state.new_context); if (se_state.enforcing) @@ -342,10 +377,17 @@ selinux_execve(const char *path, char *argv[], char *envp[]) } #endif /* HAVE_SETKEYCREATECON */ - /* We use the "spare" slot in argv to store sesh. */ - --argv; - argv[0] = *argv[1] == '-' ? "-sesh" : "sesh"; - argv[1] = (char *)path; + for (argc = 0; argv[argc] != NULL; argc++) + continue; + + /* Build new argv with sesh as argv[0]. */ + nargv = emalloc2(argc + 2, sizeof(char *)); + nargv[0] = *argv[0] == '-' ? "-sesh" : "sesh"; + nargv[1] = (char *)path; + memcpy(&nargv[2], &argv[1], argc * sizeof(char *)); /* copies NULL */ - execve(_PATH_SUDO_SESH, argv, envp); + execve(_PATH_SUDO_SESH, nargv, envp); + serrno = errno; + free(nargv); + errno = serrno; } diff --git a/sesh.c b/src/sesh.c similarity index 94% rename from sesh.c rename to src/sesh.c index 4001614..e0aef78 100644 --- a/sesh.c +++ b/src/sesh.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008 Todd C. Miller + * Copyright (c) 2008, 2010 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -30,7 +30,7 @@ #include "missing.h" int -main (int argc, char **argv) +main (int argc, char *argv[]) { char *cp, *cmnd; diff --git a/src/sudo.c b/src/sudo.c new file mode 100644 index 0000000..1f9b565 --- /dev/null +++ b/src/sudo.c @@ -0,0 +1,1205 @@ +/* + * Copyright (c) 2009-2011 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef __TANDEM +# include +#endif + +#include + +#include +#include +#include +#include +#include +#ifdef HAVE_SYS_SELECT_H +# include +#endif /* HAVE_SYS_SELECT_H */ +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS) +# include +# endif +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#include +#include +#include +#include +#include +#include +#include +#if TIME_WITH_SYS_TIME +# include +#endif +#ifdef HAVE_SETLOCALE +# include +#endif +#ifdef HAVE_LOGIN_CAP_H +# include +#endif +#ifdef HAVE_PROJECT_H +# include +# include +#endif +#ifdef HAVE_SELINUX +# include +#endif +#ifdef HAVE_SETAUTHDB +# include +#endif /* HAVE_SETAUTHDB */ +#if defined(HAVE_GETPRPWNAM) && defined(HAVE_SET_AUTH_PARAMETERS) +# ifdef __hpux +# undef MAXINT +# include +# else +# include +# endif /* __hpux */ +# include +#endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */ +#ifdef HAVE_PRIV_SET +# include +#endif + +#include "sudo.h" +#include "sudo_plugin.h" +#include "sudo_plugin_int.h" +#include + +/* + * Local variables + */ +struct plugin_container policy_plugin; +struct plugin_container_list io_plugins; +struct user_details user_details; +const char *list_user, *runas_user, *runas_group; /* extern for parse_args.c */ +int debug_level; + +/* + * Local functions + */ +static void fix_fds(void); +static void disable_coredumps(void); +static char **get_user_info(struct user_details *); +static void command_info_to_details(char * const info[], + struct command_details *details); +static int policy_open(struct plugin_container *plugin, char * const settings[], + char * const user_info[], char * const user_env[]); +static void policy_close(struct plugin_container *plugin, int exit_status, + int error); +static int iolog_open(struct plugin_container *plugin, char * const settings[], + char * const user_info[], char * const command_details[], + int argc, char * const argv[], char * const user_env[]); +static void iolog_close(struct plugin_container *plugin, int exit_status, + int error); +static char *escape_cmnd(const char *src); + +/* Policy plugin convenience functions. */ +static int policy_open(struct plugin_container *plugin, char * const settings[], + char * const user_info[], char * const user_env[]); +static void policy_close(struct plugin_container *plugin, int exit_status, + int error); +static int policy_show_version(struct plugin_container *plugin, int verbose); +static int policy_check(struct plugin_container *plugin, int argc, + char * const argv[], char *env_add[], char **command_info[], + char **argv_out[], char **user_env_out[]); +static int policy_list(struct plugin_container *plugin, int argc, + char * const argv[], int verbose, const char *list_user); +static int policy_validate(struct plugin_container *plugin); +static void policy_invalidate(struct plugin_container *plugin, int remove); +static int policy_init_session(struct plugin_container *plugin, + struct passwd *pwd); + +/* I/O log plugin convenience functions. */ +static int iolog_open(struct plugin_container *plugin, char * const settings[], + char * const user_info[], char * const command_details[], + int argc, char * const argv[], char * const user_env[]); +static void iolog_close(struct plugin_container *plugin, int exit_status, + int error); +static int iolog_show_version(struct plugin_container *plugin, int verbose); + +#if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL) +static struct rlimit corelimit; +#endif /* RLIMIT_CORE && !SUDO_DEVEL */ +#if defined(__linux__) +static struct rlimit nproclimit; +#endif + +int +main(int argc, char *argv[], char *envp[]) +{ + int nargc, sudo_mode, exitcode = 0; + char **nargv, **settings, **env_add; + char **user_info, **command_info, **argv_out, **user_env_out; + struct plugin_container *plugin, *next; + struct command_details command_details; + sigset_t mask; + int ok; +#if defined(SUDO_DEVEL) && defined(__OpenBSD__) + extern char *malloc_options; + malloc_options = "AFGJPR"; +#endif + +#ifdef HAVE_SETLOCALE + setlocale(LC_ALL, ""); +#endif + +#if !defined(HAVE_GETPROGNAME) && !defined(HAVE___PROGNAME) + if (argc > 0) + setprogname(argv[0]); +#endif + + /* Must be done before we do any password lookups */ +#if defined(HAVE_GETPRPWNAM) && defined(HAVE_SET_AUTH_PARAMETERS) + (void) set_auth_parameters(argc, argv); +# ifdef HAVE_INITPRIVS + initprivs(); +# endif +#endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */ + + if (geteuid() != 0) + errorx(1, "must be setuid root"); + + /* Reset signal mask, disable core dumps and make sure fds 0-2 are open. */ + (void) sigemptyset(&mask); + (void) sigprocmask(SIG_SETMASK, &mask, NULL); + disable_coredumps(); + fix_fds(); + + /* Fill in user_info with user name, uid, cwd, etc. */ + memset(&user_details, 0, sizeof(user_details)); + user_info = get_user_info(&user_details); + + /* Parse command line arguments. */ + sudo_mode = parse_args(argc, argv, &nargc, &nargv, &settings, &env_add); + sudo_debug(9, "sudo_mode %d", sudo_mode); + + /* Print sudo version early, in case of plugin init failure. */ + if (ISSET(sudo_mode, MODE_VERSION)) { + printf("Sudo version %s\n", PACKAGE_VERSION); + if (user_details.uid == ROOT_UID) + (void) printf("Configure args: %s\n", CONFIGURE_ARGS); + } + + /* Read sudo.conf and load plugins. */ + if (!sudo_load_plugins(_PATH_SUDO_CONF, &policy_plugin, &io_plugins)) + errorx(1, "fatal error, unable to load plugins"); + + /* Open policy plugin. */ + ok = policy_open(&policy_plugin, settings, user_info, envp); + if (ok != TRUE) { + if (ok == -2) + usage(1); + else + errorx(1, "unable to initialize policy plugin"); + } + + switch (sudo_mode & MODE_MASK) { + case MODE_VERSION: + policy_show_version(&policy_plugin, !user_details.uid); + tq_foreach_fwd(&io_plugins, plugin) { + ok = iolog_open(plugin, settings, user_info, NULL, + nargc, nargv, envp); + if (ok == TRUE) + iolog_show_version(plugin, !user_details.uid); + } + break; + case MODE_VALIDATE: + case MODE_VALIDATE|MODE_INVALIDATE: + ok = policy_validate(&policy_plugin); + exit(ok != TRUE); + case MODE_KILL: + case MODE_INVALIDATE: + policy_invalidate(&policy_plugin, sudo_mode == MODE_KILL); + exit(0); + break; + case MODE_CHECK: + case MODE_CHECK|MODE_INVALIDATE: + case MODE_LIST: + case MODE_LIST|MODE_INVALIDATE: + ok = policy_list(&policy_plugin, nargc, nargv, + ISSET(sudo_mode, MODE_LONG_LIST), list_user); + exit(ok != TRUE); + case MODE_EDIT: + case MODE_RUN: + ok = policy_check(&policy_plugin, nargc, nargv, env_add, + &command_info, &argv_out, &user_env_out); + sudo_debug(8, "policy plugin returns %d", ok); + if (ok != TRUE) { + if (ok == -2) + usage(1); + exit(1); /* plugin printed error message */ + } + /* Open I/O plugins once policy plugin succeeds. */ + for (plugin = io_plugins.first; plugin != NULL; plugin = next) { + next = plugin->next; + ok = iolog_open(plugin, settings, user_info, + command_info, nargc, nargv, envp); + switch (ok) { + case TRUE: + break; + case FALSE: + /* I/O plugin asked to be disabled, remove from list. */ + tq_remove(&io_plugins, plugin); + break; + case -2: + usage(1); + break; + default: + errorx(1, "error initializing I/O plugin %s", plugin->name); + } + } + command_info_to_details(command_info, &command_details); + command_details.argv = argv_out; + command_details.envp = user_env_out; + if (ISSET(sudo_mode, MODE_BACKGROUND)) + SET(command_details.flags, CD_BACKGROUND); + /* Restore coredumpsize resource limit before running. */ +#if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL) + (void) setrlimit(RLIMIT_CORE, &corelimit); +#endif /* RLIMIT_CORE && !SUDO_DEVEL */ + if (ISSET(command_details.flags, CD_SUDOEDIT)) { + exitcode = sudo_edit(&command_details); + } else { + if (ISSET(sudo_mode, MODE_SHELL)) { + /* Escape meta chars if running a shell with args. */ + if (argv_out[1] != NULL && strcmp(argv_out[1], "-c") == 0 && + argv_out[2] != NULL && argv_out[3] == NULL) + argv_out[2] = escape_cmnd(argv_out[2]); + } + exitcode = run_command(&command_details); + } + /* The close method was called by sudo_edit/run_command. */ + break; + default: + errorx(1, "unexpected sudo mode 0x%x", sudo_mode); + } + exit(exitcode); +} + +/* + * Ensure that stdin, stdout and stderr are open; set to /dev/null if not. + * Some operating systems do this automatically in the kernel or libc. + */ +static void +fix_fds(void) +{ + int miss[3], devnull = -1; + + /* + * stdin, stdout and stderr must be open; set them to /dev/null + * if they are closed. + */ + miss[STDIN_FILENO] = fcntl(STDIN_FILENO, F_GETFL, 0) == -1; + miss[STDOUT_FILENO] = fcntl(STDOUT_FILENO, F_GETFL, 0) == -1; + miss[STDERR_FILENO] = fcntl(STDERR_FILENO, F_GETFL, 0) == -1; + if (miss[STDIN_FILENO] || miss[STDOUT_FILENO] || miss[STDERR_FILENO]) { + if ((devnull = open(_PATH_DEVNULL, O_RDWR, 0644)) == -1) + error(1, "unable to open %s", _PATH_DEVNULL); + if (miss[STDIN_FILENO] && dup2(devnull, STDIN_FILENO) == -1) + error(1, "dup2"); + if (miss[STDOUT_FILENO] && dup2(devnull, STDOUT_FILENO) == -1) + error(1, "dup2"); + if (miss[STDERR_FILENO] && dup2(devnull, STDERR_FILENO) == -1) + error(1, "dup2"); + if (devnull > STDERR_FILENO) + close(devnull); + } +} + +static char * +get_user_groups(struct user_details *ud) +{ + char *gid_list = NULL; +#ifdef HAVE_GETGROUPS + size_t glsize; + char *cp; + int i, len; + + if ((ud->ngroups = getgroups(0, NULL)) <= 0) + return NULL; + + ud->groups = emalloc2(ud->ngroups, sizeof(GETGROUPS_T)); + if (getgroups(ud->ngroups, ud->groups) < 0) + error(1, "can't get group vector"); + glsize = sizeof("groups=") - 1 + (ud->ngroups * (MAX_UID_T_LEN + 1)); + gid_list = emalloc(glsize); + memcpy(gid_list, "groups=", sizeof("groups=") - 1); + cp = gid_list + sizeof("groups=") - 1; + for (i = 0; i < ud->ngroups; i++) { + /* XXX - check rval */ + len = snprintf(cp, glsize - (cp - gid_list), "%s%u", + i ? "," : "", (unsigned int)ud->groups[i]); + cp += len; + } +#endif + return gid_list; +} + +/* + * Return user information as an array of name=value pairs. + * and fill in struct user_details (which shares the same strings). + */ +static char ** +get_user_info(struct user_details *ud) +{ + char cwd[PATH_MAX]; + char host[MAXHOSTNAMELEN]; + char **user_info, *cp; + struct passwd *pw; + int i = 0; + + /* XXX - bound check number of entries */ + user_info = emalloc2(32, sizeof(char *)); + + ud->uid = getuid(); + ud->euid = geteuid(); + ud->gid = getgid(); + ud->egid = getegid(); + + pw = getpwuid(ud->uid); + if (pw == NULL) + errorx(1, "unknown uid %u: who are you?", (unsigned int)ud->uid); + + user_info[i] = fmt_string("user", pw->pw_name); + if (user_info[i] == NULL) + errorx(1, "unable to allocate memory"); + ud->username = user_info[i] + sizeof("user=") - 1; + + /* Stash user's shell for use with the -s flag; don't pass to plugin. */ + if ((ud->shell = getenv("SHELL")) == NULL || ud->shell[0] == '\0') { + ud->shell = pw->pw_shell[0] ? pw->pw_shell : _PATH_BSHELL; + } + ud->shell = estrdup(ud->shell); + + easprintf(&user_info[++i], "uid=%u", (unsigned int)ud->uid); + easprintf(&user_info[++i], "euid=%u", (unsigned int)ud->euid); + easprintf(&user_info[++i], "gid=%u", (unsigned int)ud->gid); + easprintf(&user_info[++i], "egid=%u", (unsigned int)ud->egid); + + if ((cp = get_user_groups(ud)) != NULL) + user_info[++i] = cp; + + if (getcwd(cwd, sizeof(cwd)) != NULL) { + user_info[++i] = fmt_string("cwd", cwd); + if (user_info[i] == NULL) + errorx(1, "unable to allocate memory"); + ud->cwd = user_info[i] + sizeof("cwd=") - 1; + } + + if ((cp = ttyname(STDIN_FILENO)) || (cp = ttyname(STDOUT_FILENO)) || + (cp = ttyname(STDERR_FILENO))) { + user_info[++i] = fmt_string("tty", cp); + if (user_info[i] == NULL) + errorx(1, "unable to allocate memory"); + ud->tty = user_info[i] + sizeof("tty=") - 1; + } + + if (gethostname(host, sizeof(host)) == 0) + host[sizeof(host) - 1] = '\0'; + else + strlcpy(host, "localhost", sizeof(host)); + user_info[++i] = fmt_string("host", host); + if (user_info[i] == NULL) + errorx(1, "unable to allocate memory"); + ud->host = user_info[i] + sizeof("host=") - 1; + + get_ttysize(&ud->ts_lines, &ud->ts_cols); + easprintf(&user_info[++i], "lines=%d", ud->ts_lines); + easprintf(&user_info[++i], "cols=%d", ud->ts_cols); + + user_info[++i] = NULL; + + return user_info; +} + +/* + * Convert a command_info array into a command_details structure. + */ +static void +command_info_to_details(char * const info[], struct command_details *details) +{ + int i; + long lval; + unsigned long ulval; + char *cp, *ep; + + memset(details, 0, sizeof(*details)); + details->closefrom = -1; + +#define SET_STRING(s, n) \ + if (strncmp(s, info[i], sizeof(s) - 1) == 0 && info[i][sizeof(s) - 1]) { \ + details->n = info[i] + sizeof(s) - 1; \ + break; \ + } + + for (i = 0; info[i] != NULL; i++) { + sudo_debug(9, "command info: %s", info[i]); + switch (info[i][0]) { + case 'c': + SET_STRING("chroot=", chroot) + SET_STRING("command=", command) + SET_STRING("cwd=", cwd) + if (strncmp("closefrom=", info[i], sizeof("closefrom=") - 1) == 0) { + cp = info[i] + sizeof("closefrom=") - 1; + if (*cp == '\0') + break; + errno = 0; + lval = strtol(cp, &ep, 0); + if (*cp != '\0' && *ep == '\0' && + !(errno == ERANGE && + (lval == LONG_MAX || lval == LONG_MIN)) && + lval < INT_MAX && lval > INT_MIN) { + details->closefrom = (int)lval; + } + break; + } + break; + case 'l': + SET_STRING("login_class=", login_class) + break; + case 'n': + /* XXX - bounds check -NZERO to NZERO (inclusive). */ + if (strncmp("nice=", info[i], sizeof("nice=") - 1) == 0) { + cp = info[i] + sizeof("nice=") - 1; + if (*cp == '\0') + break; + errno = 0; + lval = strtol(cp, &ep, 0); + if (*cp != '\0' && *ep == '\0' && + !(errno == ERANGE && + (lval == LONG_MAX || lval == LONG_MIN)) && + lval < INT_MAX && lval > INT_MIN) { + details->priority = (int)lval; + SET(details->flags, CD_SET_PRIORITY); + } + break; + } + if (strncmp("noexec=", info[i], sizeof("noexec=") - 1) == 0) { + if (atobool(info[i] + sizeof("noexec=") - 1) == TRUE) + SET(details->flags, CD_NOEXEC); + break; + } + /* XXX - deprecated */ + if (strncmp("noexec_file=", info[i], sizeof("noexec_file=") - 1) == 0) { + noexec_path = info[i] + sizeof("noexec_file=") - 1; + break; + } + break; + case 'p': + if (strncmp("preserve_groups=", info[i], sizeof("preserve_groups=") - 1) == 0) { + if (atobool(info[i] + sizeof("preserve_groups=") - 1) == TRUE) + SET(details->flags, CD_PRESERVE_GROUPS); + break; + } + break; + case 'r': + if (strncmp("runas_egid=", info[i], sizeof("runas_egid=") - 1) == 0) { + cp = info[i] + sizeof("runas_egid=") - 1; + if (*cp == '\0') + break; + errno = 0; + ulval = strtoul(cp, &ep, 0); + if (*cp != '\0' && *ep == '\0' && + (errno != ERANGE || ulval != ULONG_MAX)) { + details->egid = (gid_t)ulval; + SET(details->flags, CD_SET_EGID); + } + break; + } + if (strncmp("runas_euid=", info[i], sizeof("runas_euid=") - 1) == 0) { + cp = info[i] + sizeof("runas_euid=") - 1; + if (*cp == '\0') + break; + errno = 0; + ulval = strtoul(cp, &ep, 0); + if (*cp != '\0' && *ep == '\0' && + (errno != ERANGE || ulval != ULONG_MAX)) { + details->euid = (uid_t)ulval; + SET(details->flags, CD_SET_EUID); + } + break; + } + if (strncmp("runas_gid=", info[i], sizeof("runas_gid=") - 1) == 0) { + cp = info[i] + sizeof("runas_gid=") - 1; + if (*cp == '\0') + break; + errno = 0; + ulval = strtoul(cp, &ep, 0); + if (*cp != '\0' && *ep == '\0' && + (errno != ERANGE || ulval != ULONG_MAX)) { + details->gid = (gid_t)ulval; + SET(details->flags, CD_SET_GID); + } + break; + } + if (strncmp("runas_groups=", info[i], sizeof("runas_groups=") - 1) == 0) { + int j; + + /* count groups, alloc and fill in */ + cp = info[i] + sizeof("runas_groups=") - 1; + if (*cp == '\0') + break; + for (;;) { + details->ngroups++; + if ((cp = strchr(cp, ',')) == NULL) + break; + cp++; + } + if (details->ngroups != 0) { + details->groups = + emalloc2(details->ngroups, sizeof(GETGROUPS_T)); + cp = info[i] + sizeof("runas_groups=") - 1; + for (j = 0; j < details->ngroups;) { + errno = 0; + ulval = strtoul(cp, &ep, 0); + if (*cp == '\0' || (*ep != ',' && *ep != '\0') || + (ulval == ULONG_MAX && errno == ERANGE)) { + break; + } + details->groups[j++] = (gid_t)ulval; + cp = ep + 1; + } + details->ngroups = j; + } + break; + } + if (strncmp("runas_uid=", info[i], sizeof("runas_uid=") - 1) == 0) { + cp = info[i] + sizeof("runas_uid=") - 1; + if (*cp == '\0') + break; + errno = 0; + ulval = strtoul(cp, &ep, 0); + if (*cp != '\0' && *ep == '\0' && + (errno != ERANGE || ulval != ULONG_MAX)) { + details->uid = (uid_t)ulval; + SET(details->flags, CD_SET_UID); + } + break; + } + break; + case 's': + SET_STRING("selinux_role=", selinux_role) + SET_STRING("selinux_type=", selinux_type) + if (strncmp("set_utmp=", info[i], sizeof("set_utmp=") - 1) == 0) { + if (atobool(info[i] + sizeof("set_utmp=") - 1) == TRUE) + SET(details->flags, CD_SET_UTMP); + break; + } + if (strncmp("sudoedit=", info[i], sizeof("sudoedit=") - 1) == 0) { + if (atobool(info[i] + sizeof("sudoedit=") - 1) == TRUE) + SET(details->flags, CD_SUDOEDIT); + break; + } + break; + case 't': + if (strncmp("timeout=", info[i], sizeof("timeout=") - 1) == 0) { + cp = info[i] + sizeof("timeout=") - 1; + if (*cp == '\0') + break; + errno = 0; + lval = strtol(cp, &ep, 0); + if (*cp != '\0' && *ep == '\0' && + !(errno == ERANGE && + (lval == LONG_MAX || lval == LONG_MIN)) && + lval <= INT_MAX && lval >= 0) { + details->timeout = (int)lval; + SET(details->flags, CD_SET_TIMEOUT); + } + break; + } + break; + case 'u': + if (strncmp("umask=", info[i], sizeof("umask=") - 1) == 0) { + cp = info[i] + sizeof("umask=") - 1; + if (*cp == '\0') + break; + errno = 0; + ulval = strtoul(cp, &ep, 8); + if (*cp != '\0' && *ep == '\0' && + (errno != ERANGE || ulval != ULONG_MAX)) { + details->umask = (uid_t)ulval; + SET(details->flags, CD_SET_UMASK); + } + break; + } + if (strncmp("use_pty=", info[i], sizeof("use_pty=") - 1) == 0) { + if (atobool(info[i] + sizeof("use_pty=") - 1) == TRUE) + SET(details->flags, CD_USE_PTY); + break; + } + SET_STRING("utmp_user=", utmp_user) + break; + } + } + + if (!ISSET(details->flags, CD_SET_EUID)) + details->euid = details->uid; + +#ifdef HAVE_SELINUX + if (details->selinux_role != NULL && is_selinux_enabled() > 0) + SET(details->flags, CD_RBAC_ENABLED); +#endif +} + +/* + * Disable core dumps to avoid dropping a core with user password in it. + * We will reset this limit before executing the command. + * Not all operating systems disable core dumps for setuid processes. + */ +static void +disable_coredumps(void) +{ +#if defined(__linux__) || (defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)) + struct rlimit rl; +#endif + +#if defined(__linux__) + /* + * Unlimit the number of processes since Linux's setuid() will + * apply resource limits when changing uid and return EAGAIN if + * nproc would be violated by the uid switch. + */ + (void) getrlimit(RLIMIT_NPROC, &nproclimit); + rl.rlim_cur = rl.rlim_max = RLIM_INFINITY; + if (setrlimit(RLIMIT_NPROC, &rl)) { + memcpy(&rl, &nproclimit, sizeof(struct rlimit)); + rl.rlim_cur = rl.rlim_max; + (void)setrlimit(RLIMIT_NPROC, &rl); + } +#endif /* __linux__ */ +#if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL) + /* + * Turn off core dumps. + */ + (void) getrlimit(RLIMIT_CORE, &corelimit); + memcpy(&rl, &corelimit, sizeof(struct rlimit)); + rl.rlim_cur = 0; + (void) setrlimit(RLIMIT_CORE, &rl); +#endif /* RLIMIT_CORE && !SUDO_DEVEL */ +} + +#ifdef HAVE_PROJECT_H +static void +set_project(struct passwd *pw) +{ + struct project proj; + char buf[PROJECT_BUFSZ]; + int errval; + + /* + * Collect the default project for the user and settaskid + */ + setprojent(); + if (getdefaultproj(pw->pw_name, &proj, buf, sizeof(buf)) != NULL) { + errval = setproject(proj.pj_name, pw->pw_name, TASK_NORMAL); + switch(errval) { + case 0: + break; + case SETPROJ_ERR_TASK: + switch (errno) { + case EAGAIN: + warningx("resource control limit has been reached"); + break; + case ESRCH: + warningx("user \"%s\" is not a member of project \"%s\"", + pw->pw_name, proj.pj_name); + break; + case EACCES: + warningx("the invoking task is final"); + break; + default: + warningx("could not join project \"%s\"", proj.pj_name); + } + case SETPROJ_ERR_POOL: + switch (errno) { + case EACCES: + warningx("no resource pool accepting default bindings " + "exists for project \"%s\"", proj.pj_name); + break; + case ESRCH: + warningx("specified resource pool does not exist for " + "project \"%s\"", proj.pj_name); + break; + default: + warningx("could not bind to default resource pool for " + "project \"%s\"", proj.pj_name); + } + break; + default: + if (errval <= 0) { + warningx("setproject failed for project \"%s\"", proj.pj_name); + } else { + warningx("warning, resource control assignment failed for " + "project \"%s\"", proj.pj_name); + } + } + } else { + warning("getdefaultproj"); + } + endprojent(); +} +#endif /* HAVE_PROJECT_H */ + +/* + * Disable execution of child processes in the command we are about + * to run. On systems with privilege sets, we can remove the exec + * privilege. On other systems we use LD_PRELOAD and the like. + */ +static void +disable_execute(struct command_details *details) +{ + char *cp, **ev, **nenvp; + int env_len = 0, env_size = 128; + +#ifdef HAVE_PRIV_SET + /* Solaris privileges, remove PRIV_PROC_EXEC post-execve. */ + if (priv_set(PRIV_OFF, PRIV_LIMIT, "PRIV_PROC_EXEC", NULL) == 0) + return; + warning("unable to remove PRIV_PROC_EXEC from PRIV_LIMIT"); +#endif /* HAVE_PRIV_SET */ + + nenvp = emalloc2(env_size, sizeof(char *)); + for (ev = details->envp; *ev != NULL; ev++) { + if (env_len + 2 > env_size) { + env_size += 128; + nenvp = erealloc3(nenvp, env_size, sizeof(char *)); + } + /* + * Prune out existing preloaded libraries. + * XXX - should save and append instead of replacing. + */ +#if defined(__darwin__) || defined(__APPLE__) + if (strncmp(*ev, "DYLD_INSERT_LIBRARIES=", sizeof("DYLD_INSERT_LIBRARIES=") - 1) == 0) + continue; + if (strncmp(*ev, "DYLD_FORCE_FLAT_NAMESPACE=", sizeof("DYLD_INSERT_LIBRARIES=") - 1) == 0) + continue; +#elif defined(__osf__) || defined(__sgi) + if (strncmp(*ev, "_RLD_LIST=", sizeof("_RLD_LIST=") - 1) == 0) + continue; +#elif defined(_AIX) + if (strncmp(*ev, "LDR_PRELOAD=", sizeof("LDR_PRELOAD=") - 1) == 0) + continue; +#else + if (strncmp(*ev, "LD_PRELOAD=", sizeof("LD_PRELOAD=") - 1) == 0) + continue; +#endif + nenvp[env_len++] = *ev; + } + + /* + * Preload a noexec file? For a list of LD_PRELOAD-alikes, see + * http://www.fortran-2000.com/ArnaudRecipes/sharedlib.html + * XXX - need to support 32-bit and 64-bit variants + */ +#if defined(__darwin__) || defined(__APPLE__) + nenvp[env_len++] = "DYLD_FORCE_FLAT_NAMESPACE="; + cp = fmt_string("DYLD_INSERT_LIBRARIES", noexec_path); +#elif defined(__osf__) || defined(__sgi) + easprintf(&cp, "_RLD_LIST=%s:DEFAULT", noexec_path); +#elif defined(_AIX) + cp = fmt_string("LDR_PRELOAD", noexec_path); +#else + cp = fmt_string("LD_PRELOAD", noexec_path); +#endif + if (cp == NULL) + error(1, NULL); + nenvp[env_len++] = cp; + nenvp[env_len] = NULL; + + details->envp = nenvp; +} + +/* + * Setup the execution environment immediately prior to the call to execve() + * Returns TRUE on success and FALSE on failure. + */ +int +exec_setup(struct command_details *details, const char *ptyname, int ptyfd) +{ + int rval = FALSE; + struct passwd *pw; + +#ifdef HAVE_SETAUTHDB + aix_setauthdb(IDtouser(details->euid)); +#endif + pw = getpwuid(details->euid); +#ifdef HAVE_SETAUTHDB + aix_restoreauthdb(); +#endif + + /* + * Call policy plugin's session init before other setup occurs. + * The session init code is expected to print an error as needed. + */ + if (policy_init_session(&policy_plugin, pw) != TRUE) + goto done; + +#ifdef HAVE_SELINUX + if (ISSET(details->flags, CD_RBAC_ENABLED)) { + if (selinux_setup(details->selinux_role, details->selinux_type, + ptyname ? ptyname : user_details.tty, ptyfd) == -1) + goto done; + } +#endif + + if (pw != NULL) { +#ifdef HAVE_PROJECT_H + set_project(pw); +#endif +#ifdef HAVE_GETUSERATTR + aix_prep_user(pw->pw_name, ptyname ? ptyname : user_details.tty); +#endif +#ifdef HAVE_LOGIN_CAP_H + if (details->login_class) { + int flags; + login_cap_t *lc; + + /* + * We only use setusercontext() to set the nice value and rlimits. + */ + lc = login_getclass((char *)details->login_class); + if (!lc) { + warningx("unknown login class %s", details->login_class); + errno = ENOENT; + goto done; + } + flags = LOGIN_SETRESOURCES|LOGIN_SETPRIORITY; + if (setusercontext(lc, pw, pw->pw_uid, flags)) { + if (pw->pw_uid != ROOT_UID) { + warning("unable to set user context"); + goto done; + } else + warning("unable to set user context"); + } + } +#endif /* HAVE_LOGIN_CAP_H */ + } + + /* + * Set groups, including supplementary group vector. + */ +#ifdef HAVE_SETEUID + if (ISSET(details->flags, CD_SET_EGID) && setegid(details->egid)) { + warning("unable to set egid to runas gid %u", details->egid); + goto done; + } +#endif + if (ISSET(details->flags, CD_SET_GID) && setgid(details->gid)) { + warning("unable to set gid to runas gid %u", details->gid); + goto done; + } + + if (!ISSET(details->flags, CD_PRESERVE_GROUPS)) { +#ifdef HAVE_GETGROUPS + if (details->ngroups >= 0) { + if (setgroups(details->ngroups, details->groups) < 0) { + warning("unable to set supplementary group IDs"); + goto done; + } + } +#else + if (pw && initgroups(pw->pw_name, pw->pw_gid) < 0) { + warning("unable to set supplementary group IDs"); + goto done; + } +#endif + } + + if (ISSET(details->flags, CD_SET_PRIORITY)) { + if (setpriority(PRIO_PROCESS, 0, details->priority) != 0) { + warning("unable to set process priority"); + goto done; + } + } + if (ISSET(details->flags, CD_SET_UMASK)) + (void) umask(details->umask); + if (details->chroot) { + if (chroot(details->chroot) != 0 || chdir("/") != 0) { + warning("unable to change root to %s", details->chroot); + goto done; + } + } + + if (ISSET(details->flags, CD_NOEXEC)) + disable_execute(details); + +#ifdef HAVE_SETRESUID + if (setresuid(details->uid, details->euid, details->euid) != 0) { + warning("unable to change to runas uid (%u, %u)", details->uid, + details->euid); + goto done; + } +#elif HAVE_SETREUID + if (setreuid(details->uid, details->euid) != 0) { + warning("unable to change to runas uid (%u, %u)", details->uid, + details->euid); + goto done; + } +#else + if (seteuid(details->euid) != 0 || setuid(details->euid) != 0) { + warning("unable to change to runas uid (%u, %u)", details->uid, + details->euid); + goto done; + } +#endif /* !HAVE_SETRESUID && !HAVE_SETREUID */ + + /* + * Only change cwd if we have chroot()ed or the policy modules + * specifies a different cwd. Must be done after uid change. + */ + if (details->cwd) { + if (details->chroot || strcmp(details->cwd, user_details.cwd) != 0) { + /* Note: cwd is relative to the new root, if any. */ + if (chdir(details->cwd) != 0) { + warning("unable to change directory to %s", details->cwd); + goto done; + } + } + } + + /* + * Restore nproc resource limit if pam_limits didn't do it for us. + * We must do this *after* the uid change to avoid potential EAGAIN + * from setuid(). + */ +#if defined(__linux__) + { + struct rlimit rl; + if (getrlimit(RLIMIT_NPROC, &rl) == 0) { + if (rl.rlim_cur == RLIM_INFINITY && rl.rlim_max == RLIM_INFINITY) + (void) setrlimit(RLIMIT_NPROC, &nproclimit); + } + } +#endif + + rval = TRUE; + +done: + return rval; +} + +/* + * Escape any non-alpha numeric or blank characters to make sure + * they are not interpreted specially by the shell. + */ +static char * +escape_cmnd(const char *src) +{ + char *cmnd, *dst; + + /* Worst case scenario, we have to escape everything. */ + cmnd = dst = emalloc((2 * strlen(src)) + 1); + while (*src != '\0') { + if (!isalnum((unsigned char)*src) && !isspace((unsigned char)*src) && + *src != '_' && *src != '-') { + /* quote potential meta character */ + *dst++ = '\\'; + } + *dst++ = *src++; + } + *dst++ = '\0'; + + return cmnd; +} + +/* + * Run the command and wait for it to complete. + */ +int +run_command(struct command_details *details) +{ + struct plugin_container *plugin; + struct command_status cstat; + int exitcode = 1; + + cstat.type = CMD_INVALID; + cstat.val = 0; + + sudo_execve(details, &cstat); + + switch (cstat.type) { + case CMD_ERRNO: + /* exec_setup() or execve() returned an error. */ + sudo_debug(9, "calling policy close with errno"); + policy_close(&policy_plugin, 0, cstat.val); + tq_foreach_fwd(&io_plugins, plugin) { + sudo_debug(9, "calling I/O close with errno"); + iolog_close(plugin, 0, cstat.val); + } + exitcode = 1; + break; + case CMD_WSTATUS: + /* Command ran, exited or was killed. */ + sudo_debug(9, "calling policy close with wait status"); + policy_close(&policy_plugin, cstat.val, 0); + tq_foreach_fwd(&io_plugins, plugin) { + sudo_debug(9, "calling I/O close with wait status"); + iolog_close(plugin, cstat.val, 0); + } + if (WIFEXITED(cstat.val)) + exitcode = WEXITSTATUS(cstat.val); + else if (WIFSIGNALED(cstat.val)) + exitcode = WTERMSIG(cstat.val) | 128; + break; + default: + warningx("unexpected child termination condition: %d", cstat.type); + break; + } + return exitcode; +} + +static int +policy_open(struct plugin_container *plugin, char * const settings[], + char * const user_info[], char * const user_env[]) +{ + return plugin->u.policy->open(SUDO_API_VERSION, sudo_conversation, + _sudo_printf, settings, user_info, user_env); +} + +static void +policy_close(struct plugin_container *plugin, int exit_status, int error) +{ + plugin->u.policy->close(exit_status, error); +} + +static int +policy_show_version(struct plugin_container *plugin, int verbose) +{ + return plugin->u.policy->show_version(verbose); +} + +static int +policy_check(struct plugin_container *plugin, int argc, char * const argv[], + char *env_add[], char **command_info[], char **argv_out[], + char **user_env_out[]) +{ + return plugin->u.policy->check_policy(argc, argv, env_add, command_info, + argv_out, user_env_out); +} + +static int +policy_list(struct plugin_container *plugin, int argc, char * const argv[], + int verbose, const char *list_user) +{ + if (plugin->u.policy->list == NULL) { + warningx("policy plugin %s does not support listing privileges", + plugin->name); + return FALSE; + } + return plugin->u.policy->list(argc, argv, verbose, list_user); +} + +static int +policy_validate(struct plugin_container *plugin) +{ + if (plugin->u.policy->validate == NULL) { + warningx("policy plugin %s does not support the -v flag", + plugin->name); + return FALSE; + } + return plugin->u.policy->validate(); +} + +static void +policy_invalidate(struct plugin_container *plugin, int remove) +{ + if (plugin->u.policy->invalidate == NULL) { + errorx(1, "policy plugin %s does not support the -k/-K flags", + plugin->name); + } + plugin->u.policy->invalidate(remove); +} + +static int +policy_init_session(struct plugin_container *plugin, struct passwd *pwd) +{ + if (plugin->u.policy->init_session) + return plugin->u.policy->init_session(pwd); + return TRUE; +} + +static int +iolog_open(struct plugin_container *plugin, char * const settings[], + char * const user_info[], char * const command_info[], + int argc, char * const argv[], char * const user_env[]) +{ + int rval; + + /* + * Backwards compatibility for API major 1, minor 0 + */ + switch (plugin->u.generic->version) { + case SUDO_API_MKVERSION(1, 0): + rval = plugin->u.io_1_0->open(plugin->u.io_1_0->version, + sudo_conversation, _sudo_printf, settings, user_info, argc, argv, + user_env); + break; + default: + rval = plugin->u.io->open(SUDO_API_VERSION, sudo_conversation, + _sudo_printf, settings, user_info, command_info, argc, argv, + user_env); + } + return rval; +} + +static void +iolog_close(struct plugin_container *plugin, int exit_status, int error) +{ + plugin->u.io->close(exit_status, error); +} + +static int +iolog_show_version(struct plugin_container *plugin, int verbose) +{ + return plugin->u.io->show_version(verbose); +} + +/* + * Simple debugging/logging. + */ +void +sudo_debug(int level, const char *fmt, ...) +{ + va_list ap; + char *fmt2; + + if (level > debug_level) + return; + + /* Backet fmt with program name and a newline to make it a single write */ + easprintf(&fmt2, "%s: %s\n", getprogname(), fmt); + va_start(ap, fmt); + vfprintf(stderr, fmt2, ap); + va_end(ap); + efree(fmt2); +} diff --git a/src/sudo.h b/src/sudo.h new file mode 100644 index 0000000..46a68f1 --- /dev/null +++ b/src/sudo.h @@ -0,0 +1,233 @@ +/* + * Copyright (c) 1993-1996, 1998-2005, 2007-2011 + * Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + * + * $Sudo: sudo.h,v 1.290 2009/12/12 16:12:26 millert Exp $ + */ + +#ifndef _SUDO_SUDO_H +#define _SUDO_SUDO_H + +#include + +#include +#include "missing.h" +#include "alloc.h" +#include "error.h" +#include "fileops.h" +#include "list.h" + +#ifdef __TANDEM +# define ROOT_UID 65535 +#else +# define ROOT_UID 0 +#endif + +/* + * Pseudo-boolean values + */ +#undef TRUE +#define TRUE 1 +#undef FALSE +#define FALSE 0 + +/* + * Various modes sudo can be in (based on arguments) in hex + */ +#define MODE_RUN 0x00000001 +#define MODE_EDIT 0x00000002 +#define MODE_VALIDATE 0x00000004 +#define MODE_INVALIDATE 0x00000008 +#define MODE_KILL 0x00000010 +#define MODE_VERSION 0x00000020 +#define MODE_HELP 0x00000040 +#define MODE_LIST 0x00000080 +#define MODE_CHECK 0x00000100 +#define MODE_MASK 0x0000ffff + +/* Mode flags */ +/* XXX - prune this */ +#define MODE_BACKGROUND 0x00010000 +#define MODE_SHELL 0x00020000 +#define MODE_LOGIN_SHELL 0x00040000 +#define MODE_IMPLIED_SHELL 0x00080000 +#define MODE_RESET_HOME 0x00100000 +#define MODE_PRESERVE_GROUPS 0x00200000 +#define MODE_PRESERVE_ENV 0x00400000 +#define MODE_NONINTERACTIVE 0x00800000 +#define MODE_LONG_LIST 0x01000000 + +/* + * We used to use the system definition of PASS_MAX or _PASSWD_LEN, + * but that caused problems with various alternate authentication + * methods. So, we just define our own and assume that it is >= the + * system max. + */ +#define SUDO_PASS_MAX 256 + +/* + * Flags for tgetpass() + */ +#define TGP_NOECHO 0x00 /* turn echo off reading pw (default) */ +#define TGP_ECHO 0x01 /* leave echo on when reading passwd */ +#define TGP_STDIN 0x02 /* read from stdin, not /dev/tty */ +#define TGP_ASKPASS 0x04 /* read from askpass helper program */ +#define TGP_MASK 0x08 /* mask user input when reading */ +#define TGP_NOECHO_TRY 0x10 /* turn off echo if possible */ + +struct user_details { + uid_t uid; + uid_t euid; + uid_t gid; + uid_t egid; + const char *username; + const char *cwd; + const char *tty; + const char *host; + const char *shell; + GETGROUPS_T *groups; + int ngroups; + int ts_cols; + int ts_lines; +}; + +#define CD_SET_UID 0x0001 +#define CD_SET_EUID 0x0002 +#define CD_SET_GID 0x0004 +#define CD_SET_EGID 0x0008 +#define CD_PRESERVE_GROUPS 0x0010 +#define CD_NOEXEC 0x0020 +#define CD_SET_PRIORITY 0x0040 +#define CD_SET_UMASK 0x0080 +#define CD_SET_TIMEOUT 0x0100 +#define CD_SUDOEDIT 0x0200 +#define CD_BACKGROUND 0x0400 +#define CD_RBAC_ENABLED 0x0800 +#define CD_USE_PTY 0x1000 +#define CD_SET_UTMP 0x2000 + +struct command_details { + uid_t uid; + uid_t euid; + gid_t gid; + gid_t egid; + mode_t umask; + int priority; + int timeout; + int ngroups; + int closefrom; + int flags; + GETGROUPS_T *groups; + const char *command; + const char *cwd; + const char *login_class; + const char *chroot; + const char *selinux_role; + const char *selinux_type; + const char *utmp_user; + char **argv; + char **envp; +}; + +/* Status passed between parent and child via socketpair */ +struct command_status { +#define CMD_INVALID 0 +#define CMD_ERRNO 1 +#define CMD_WSTATUS 2 +#define CMD_SIGNO 3 + int type; + int val; +}; + +struct timeval; + +/* For error() and errorx() (XXX - needed?) */ +void cleanup(int); + +/* tgetpass.c */ +char *tgetpass(const char *, int, int); +int tty_present(void); +extern const char *askpass_path; +extern const char *noexec_path; + +/* zero_bytes.c */ +void zero_bytes(volatile void *, size_t); + +/* exec.c */ +int sudo_execve(struct command_details *details, struct command_status *cstat); +void save_signals(void); +void restore_signals(void); + +/* term.c */ +int term_cbreak(int); +int term_copy(int, int); +int term_noecho(int); +int term_raw(int, int); +int term_restore(int, int); + +/* fmt_string.h */ +char *fmt_string(const char *var, const char *value); + +/* atobool.c */ +int atobool(const char *str); + +/* parse_args.c */ +int parse_args(int argc, char **argv, int *nargc, char ***nargv, + char ***settingsp, char ***env_addp); +extern int tgetpass_flags; + +/* get_pty.c */ +int get_pty(int *master, int *slave, char *name, size_t namesz, uid_t uid); + +/* ttysize.c */ +void get_ttysize(int *rowp, int *colp); + +/* sudo.c */ +int exec_setup(struct command_details *details, const char *ptyname, int ptyfd); +int run_command(struct command_details *details); +void sudo_debug(int level, const char *format, ...) __printflike(2, 3); +extern int debug_level; +extern const char *list_user, *runas_user, *runas_group; +extern struct user_details user_details; + +/* sudo_edit.c */ +int sudo_edit(struct command_details *details); + +/* parse_args.c */ +void usage(int); + +/* selinux.c */ +int selinux_restore_tty(void); +int selinux_setup(const char *role, const char *type, const char *ttyn, + int ttyfd); +void selinux_execve(const char *path, char *argv[], char *envp[]); + +/* aix.c */ +void aix_prep_user(char *user, const char *tty); +void aix_restoreauthdb(void); +void aix_setauthdb(char *user); + +/* interfaces.c */ +int get_net_ifs(char **addrinfo); + +#ifndef errno +extern int errno; +#endif + +#endif /* _SUDO_SUDO_H */ diff --git a/sudo_edit.c b/src/sudo_edit.c similarity index 66% rename from sudo_edit.c rename to src/sudo_edit.c index f8666d9..0be9d31 100644 --- a/sudo_edit.c +++ b/src/sudo_edit.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2008, 2010 Todd C. Miller + * Copyright (c) 2004-2008, 2010-2011 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -54,26 +54,43 @@ #include "sudo.h" -static char *find_editor __P((int *argc_out, char ***argv_out)); +static void +switch_user(uid_t euid, gid_t egid, int ngroups, GETGROUPS_T *groups) +{ + int serrno = errno; + + /* When restoring root, change euid first; otherwise change it last. */ + if (euid == ROOT_UID) { + if (seteuid(ROOT_UID) != 0) + error(1, "seteuid(ROOT_UID)"); + } + if (ngroups != -1) { + if (setgroups(ngroups, groups) != 0) + error(1, "setgroups"); + } + if (setegid(egid) != 0) + error(1, "setegid(%d)", (int)egid); + if (euid != ROOT_UID) { + if (seteuid(euid) != 0) + error(1, "seteuid(%d)", (int)euid); + } -extern char **NewArgv; /* XXX */ + errno = serrno; +} /* * Wrapper to allow users to edit privileged files with their own uid. */ int -sudo_edit(argc, argv, envp) - int argc; - char *argv[]; - char *envp[]; +sudo_edit(struct command_details *command_details) { + struct command_details editor_details; ssize_t nread, nwritten; const char *tmpdir; - char *cp, *suff, **nargv, *editor, **files; - char **editor_argv = NULL; + char *cp, *suff, **nargv, **ap, **files = NULL; char buf[BUFSIZ]; - int rc, i, j, ac, ofd, tfd, nargc, rval, nfiles, tmplen; - int editor_argc = 0; + int rc, i, j, ac, ofd, tfd, nargc, rval, tmplen; + int editor_argc = 0, nfiles = 0; struct stat sb; struct timeval tv, tv1, tv2; struct tempfile { @@ -83,10 +100,14 @@ sudo_edit(argc, argv, envp) off_t osize; } *tf; - /* Determine user's editor. */ - editor = find_editor(&editor_argc, &editor_argv); - if (editor == NULL) + /* + * Set real, effective and saved uids to root. + * We will change the euid as needed below. + */ + if (setuid(ROOT_UID) != 0) { + warning("unable to change to uid to root (%u)", ROOT_UID); return 1; + } /* * Find our temporary directory, one of /var/tmp, /usr/tmp, or /tmp @@ -103,17 +124,33 @@ sudo_edit(argc, argv, envp) while (tmplen > 0 && tmpdir[tmplen - 1] == '/') tmplen--; + /* + * The user's editor must be separated from the files to be + * edited by a "--" option. + */ + for (ap = command_details->argv; *ap != NULL; ap++) { + if (files) + nfiles++; + else if (strcmp(*ap, "--") == 0) + files = ap + 1; + else + editor_argc++; + } + if (nfiles == 0) { + warningx("plugin error: missing file list for sudoedit"); + return 1; + } + /* * For each file specified by the user, make a temporary version * and copy the contents of the original to it. */ - files = argv + 1; - nfiles = argc - 1; tf = emalloc2(nfiles, sizeof(*tf)); zero_bytes(tf, nfiles * sizeof(*tf)); for (i = 0, j = 0; i < nfiles; i++) { rc = -1; - set_perms(PERM_RUNAS); + switch_user(command_details->euid, command_details->egid, + command_details->ngroups, command_details->groups); if ((ofd = open(files[i], O_RDONLY, 0644)) != -1 || errno == ENOENT) { if (ofd == -1) { zero_bytes(&sb, sizeof(sb)); /* new file */ @@ -126,7 +163,8 @@ sudo_edit(argc, argv, envp) #endif } } - set_perms(PERM_ROOT); + switch_user(ROOT_UID, user_details.egid, + user_details.ngroups, user_details.groups); if (rc || (ofd != -1 && !S_ISREG(sb.st_mode))) { if (rc) warning("%s", files[i]); @@ -145,13 +183,16 @@ sudo_edit(argc, argv, envp) cp = tf[j].ofile; suff = strrchr(cp, '.'); if (suff != NULL) { - easprintf(&tf[j].tfile, "%.*s/%.*sXXXXXXXX%s", tmplen, tmpdir, (int)(size_t)(suff - cp), cp, suff); + easprintf(&tf[j].tfile, "%.*s/%.*sXXXXXXXX%s", tmplen, tmpdir, + (int)(size_t)(suff - cp), cp, suff); } else { easprintf(&tf[j].tfile, "%.*s/%s.XXXXXXXX", tmplen, tmpdir, cp); } - set_perms(PERM_USER); + if (seteuid(user_details.uid) != 0) + error(1, "seteuid(%d)", (int)user_details.uid); tfd = mkstemps(tf[j].tfile, suff ? strlen(suff) : 0); - set_perms(PERM_ROOT); + if (seteuid(ROOT_UID) != 0) + error(1, "seteuid(ROOT_UID)"); if (tfd == -1) { warning("mkstemps"); goto cleanup; @@ -193,13 +234,11 @@ sudo_edit(argc, argv, envp) * Allocate space for the new argument vector and fill it in. * We concatenate the editor with its args and the file list * to create a new argv. - * We allocate an extra slot to be used if execve() fails. */ nargc = editor_argc + nfiles; - nargv = (char **) emalloc2(1 + nargc + 1, sizeof(char *)); - nargv++; + nargv = (char **) emalloc2(nargc + 1, sizeof(char *)); for (ac = 0; ac < editor_argc; ac++) - nargv[ac] = editor_argv[ac]; + nargv[ac] = command_details->argv[ac]; for (i = 0; i < nfiles && ac < nargc; ) nargv[ac++] = tf[i++].tfile; nargv[ac] = NULL; @@ -208,14 +247,23 @@ sudo_edit(argc, argv, envp) * Run the editor with the invoking user's creds, * keeping track of the time spent in the editor. */ - gettime(&tv1); - rval = run_command(editor, nargv, envp, user_uid, TRUE); - gettime(&tv2); + gettimeofday(&tv1, NULL); + memcpy(&editor_details, command_details, sizeof(editor_details)); + editor_details.uid = user_details.uid; + editor_details.euid = user_details.uid; + editor_details.gid = user_details.gid; + editor_details.egid = user_details.gid; + editor_details.ngroups = user_details.ngroups; + editor_details.groups = user_details.groups; + editor_details.argv = nargv; + rval = run_command(&editor_details); + gettimeofday(&tv2, NULL); /* Copy contents of temp files to real ones */ for (i = 0; i < nfiles; i++) { rc = -1; - set_perms(PERM_USER); + if (seteuid(user_details.uid) != 0) + error(1, "seteuid(%d)", (int)user_details.uid); if ((tfd = open(tf[i].tfile, O_RDONLY, 0644)) != -1) { #ifdef HAVE_FSTAT rc = fstat(tfd, &sb); @@ -223,7 +271,8 @@ sudo_edit(argc, argv, envp) rc = stat(tf[i].tfile, &sb); #endif } - set_perms(PERM_ROOT); + if (seteuid(ROOT_UID) != 0) + error(1, "seteuid(ROOT_UID)"); if (rc || !S_ISREG(sb.st_mode)) { if (rc) warning("%s", tf[i].tfile); @@ -248,9 +297,11 @@ sudo_edit(argc, argv, envp) continue; } } - set_perms(PERM_RUNAS); + switch_user(command_details->euid, command_details->egid, + command_details->ngroups, command_details->groups); ofd = open(tf[i].ofile, O_WRONLY|O_TRUNC|O_CREAT, 0644); - set_perms(PERM_ROOT); + switch_user(ROOT_UID, user_details.egid, + user_details.ngroups, user_details.groups); if (ofd == -1) { warning("unable to write to %s", tf[i].ofile); warningx("contents of edit session left in %s", tf[i].tfile); @@ -289,106 +340,13 @@ cleanup: return 1; } -static char * -resolve_editor(editor, argc_out, argv_out) - char *editor; - int *argc_out; - char ***argv_out; -{ - char *cp, **nargv, *editor_path = NULL; - int ac, nargc, wasblank; - - editor = estrdup(editor); /* becomes part of argv_out */ - - /* - * Split editor into an argument vector; editor is reused (do not free). - * The EDITOR and VISUAL environment variables may contain command - * line args so look for those and alloc space for them too. - */ - nargc = 1; - for (wasblank = FALSE, cp = editor; *cp != '\0'; cp++) { - if (isblank((unsigned char) *cp)) - wasblank = TRUE; - else if (wasblank) { - wasblank = FALSE; - nargc++; - } - } - /* If we can't find the editor in the user's PATH, give up. */ - cp = strtok(editor, " \t"); - if (cp == NULL || - find_path(cp, &editor_path, NULL, getenv("PATH"), 0) != FOUND) { - efree(editor); - return NULL; - } - nargv = (char **) emalloc2(nargc + 1, sizeof(char *)); - for (ac = 0; cp != NULL && ac < nargc; ac++) { - nargv[ac] = cp; - cp = strtok(NULL, " \t"); - } - nargv[ac] = NULL; - - *argc_out = nargc; - *argv_out = nargv; - return editor_path; -} - -/* - * Determine which editor to use. We don't need to worry about restricting - * this to a "safe" editor since it runs with the uid of the invoking user, - * not the runas (privileged) user. - * Fills in argv_out with an argument vector suitable for execve() that - * includes the editor with the specified files. - */ -static char * -find_editor(argc_out, argv_out) - int *argc_out; - char ***argv_out; -{ - char *cp, *editor, *editor_path = NULL, **ev, *ev0[4]; - - /* - * If any of SUDO_EDITOR, VISUAL or EDITOR are set, choose the first one. - */ - ev0[0] = "SUDO_EDITOR"; - ev0[1] = "VISUAL"; - ev0[2] = "EDITOR"; - ev0[3] = NULL; - for (ev = ev0; *ev != NULL; ev++) { - if ((editor = getenv(*ev)) != NULL && *editor != '\0') { - editor_path = resolve_editor(editor, argc_out, argv_out); - if (editor_path != NULL) - break; - } - } - if (editor_path == NULL) { - /* def_editor could be a path, split it up */ - editor = estrdup(def_editor); - cp = strtok(editor, ":"); - while (cp != NULL && editor_path == NULL) { - editor_path = resolve_editor(cp, argc_out, argv_out); - cp = strtok(NULL, ":"); - } - if (editor_path) - efree(editor); - } - if (!editor_path) { - audit_failure(NewArgv, "%s: command not found", editor); - warningx("%s: command not found", editor); - } - return editor_path; -} - #else /* HAVE_SETRESUID || HAVE_SETREUID || HAVE_SETEUID */ /* * Must have the ability to change the effective uid to use sudoedit. */ int -sudo_edit(argc, argv, envp) - int argc; - char *argv[]; - char *envp[]; +sudo_edit(struct command_details *command_details) { return 1; } diff --git a/sudo_exec.h b/src/sudo_exec.h similarity index 59% rename from sudo_exec.h rename to src/sudo_exec.h index ea43d55..744dd6a 100644 --- a/sudo_exec.h +++ b/src/sudo_exec.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010 Todd C. Miller + * Copyright (c) 2010-2011 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -28,18 +28,23 @@ */ /* exec.c */ -int my_execve __P((const char *path, char *argv[], char *envp[])); -int pipe_nonblock __P((int fds[2])); +int my_execve(const char *path, char *const argv[], char *const envp[]); +int pipe_nonblock(int fds[2]); /* exec_pty.c */ -int fork_pty __P((const char *path, char *argv[], char *envp[], int sv[], - int rbac_enabled, int *maxfd)); -int perform_io __P((fd_set *fdsr, fd_set *fdsw, struct command_status *cstat)); -int suspend_parent __P((int signo)); -void fd_set_iobs __P((fd_set *fdsr, fd_set *fdsw)); -RETSIGTYPE handler __P((int s)); -void pty_close __P((struct command_status *cstat)); -void pty_setup __P((uid_t uid)); +int fork_pty(struct command_details *details, int sv[], int *maxfd); +int perform_io(fd_set *fdsr, fd_set *fdsw, struct command_status *cstat); +int suspend_parent(int signo); +void fd_set_iobs(fd_set *fdsr, fd_set *fdsw); +void handler(int s); +void pty_close(struct command_status *cstat); +void pty_setup(uid_t uid, const char *tty, const char *utmp_user); +void terminate_child(pid_t pid, int use_pgrp); extern int signal_pipe[2]; +/* utmp.c */ +int utmp_login(const char *from_line, const char *to_line, int ttyfd, + const char *user); +int utmp_logout(const char *line, int status); + #endif /* _SUDO_EXEC_H */ diff --git a/sudo_noexec.c b/src/sudo_noexec.c similarity index 84% rename from sudo_noexec.c rename to src/sudo_noexec.c index ba180b5..2c18c60 100644 --- a/sudo_noexec.c +++ b/src/sudo_noexec.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004-2005 Todd C. Miller + * Copyright (c) 2004-2005, 2010-2011 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -22,11 +22,7 @@ #ifndef HAVE_TIMESPEC # include #endif -#ifdef __STDC__ -# include -#else -# include -#endif +#include #include "missing.h" @@ -48,8 +44,6 @@ extern int errno; return -1; \ } -#ifdef __STDC__ - #define DUMMY2(fn, t1, t2) \ int \ fn(t1 a1, t2 a2) \ @@ -65,28 +59,6 @@ int \ fn(t1 a1, t2 a2, ...) \ DUMMY_BODY -#else /* !__STDC__ */ - -#define DUMMY2(fn, t1, t2) \ -int \ -fn(a1, a2) \ -t1 a1; t2 a2; \ -DUMMY_BODY - -#define DUMMY3(fn, t1, t2, t3) \ -int \ -fn(a1, a2, a3) \ -t1 a1; t2 a2; t3 a3; \ -DUMMY_BODY - -#define DUMMY_VA(fn, t1, t2) \ -int \ -fn(a1, a2, va_alist) \ -t1 a1; t2 a2; va_dcl \ -DUMMY_BODY - -#endif /* !__STDC__ */ - DUMMY_VA(execl, const char *, const char *) DUMMY_VA(_execl, const char *, const char *) DUMMY_VA(__execl, const char *, const char *) diff --git a/src/sudo_plugin_int.h b/src/sudo_plugin_int.h new file mode 100644 index 0000000..772cde9 --- /dev/null +++ b/src/sudo_plugin_int.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2010-2011 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#ifndef _SUDO_PLUGIN_INT_H +#define _SUDO_PLUGIN_INT_H + +/* + * All plugin structures start with a type and a version. + */ +struct generic_plugin { + unsigned int type; + unsigned int version; + /* the rest depends on the type... */ +}; + +/* + * Backwards-compatible structures for API bumps. + */ +struct io_plugin_1_0 { + unsigned int type; + unsigned int version; + int (*open)(unsigned int version, sudo_conv_t conversation, + sudo_printf_t sudo_printf, char * const settings[], + char * const user_info[], int argc, char * const argv[], + char * const user_env[]); + void (*close)(int exit_status, int error); + int (*show_version)(int verbose); + int (*log_ttyin)(const char *buf, unsigned int len); + int (*log_ttyout)(const char *buf, unsigned int len); + int (*log_stdin)(const char *buf, unsigned int len); + int (*log_stdout)(const char *buf, unsigned int len); + int (*log_stderr)(const char *buf, unsigned int len); +}; + +/* + * Sudo plugin internals. + */ + +struct plugin_info { + struct plugin_info *prev; /* required */ + struct plugin_info *next; /* required */ + const char *path; + const char *symbol_name; +}; +TQ_DECLARE(plugin_info) + +struct plugin_container { + struct plugin_container *prev; /* required */ + struct plugin_container *next; /* required */ + const char *name; + void *handle; + union { + struct generic_plugin *generic; + struct policy_plugin *policy; + struct io_plugin *io; + struct io_plugin_1_0 *io_1_0; + } u; +}; +TQ_DECLARE(plugin_container) + +extern struct plugin_container_list policy_plugins; +extern struct plugin_container_list io_plugins; + +int sudo_conversation(int num_msgs, const struct sudo_conv_message msgs[], + struct sudo_conv_reply replies[]); +int _sudo_printf(int msg_type, const char *fmt, ...); + +int sudo_load_plugins(const char *conf_file, + struct plugin_container *policy_plugin, + struct plugin_container_list *io_plugins); + +#endif /* _SUDO_PLUGIN_INT_H */ diff --git a/sudo_usage.h.in b/src/sudo_usage.h.in similarity index 66% rename from sudo_usage.h.in rename to src/sudo_usage.h.in index b26e3ec..4f6288b 100644 --- a/sudo_usage.h.in +++ b/src/sudo_usage.h.in @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007-2009 Todd C. Miller + * Copyright (c) 2007-2010 Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -19,18 +19,15 @@ #ifndef _SUDO_USAGE_H #define _SUDO_USAGE_H -void help __P((void)) __attribute__((__noreturn__)); -void usage __P((int)); - /* * Usage strings for sudo. These are here because we * need to be able to substitute values from configure. */ -#define SUDO_USAGE1 " -h | -K | -k | -L | -V" -#define SUDO_USAGE2 " -v [-AknS] @BSDAUTH_USAGE@[-g groupname|#gid] [-p prompt] [-u user name|#uid]" -#define SUDO_USAGE3 " -l[l] [-AknS] @BSDAUTH_USAGE@[-g groupname|#gid] [-p prompt] [-U user name] [-u user name|#uid] [-g groupname|#gid] [command]" -#define SUDO_USAGE4 " [-AbEHknPS] @BSDAUTH_USAGE@@SELINUX_USAGE@[-C fd] @LOGINCAP_USAGE@[-g groupname|#gid] [-p prompt] [-u user name|#uid] [-g groupname|#gid] [VAR=value] [-i|-s] []" -#define SUDO_USAGE5 " -e [-AknS] @BSDAUTH_USAGE@@SELINUX_USAGE@[-C fd] @LOGINCAP_USAGE@[-g groupname|#gid] [-p prompt] [-u user name|#uid] file ..." +#define SUDO_USAGE1 " [-D level] -h | -K | -k | -V" +#define SUDO_USAGE2 " -v [-AknS] @BSDAUTH_USAGE@[-D level] [-g groupname|#gid] [-p prompt] [-u user name|#uid]" +#define SUDO_USAGE3 " -l[l] [-AknS] @BSDAUTH_USAGE@[-D level] [-g groupname|#gid] [-p prompt] [-U user name] [-u user name|#uid] [-g groupname|#gid] [command]" +#define SUDO_USAGE4 " [-AbEHknPS] @BSDAUTH_USAGE@@SELINUX_USAGE@[-C fd] [-D level] @LOGINCAP_USAGE@[-g groupname|#gid] [-p prompt] [-u user name|#uid] [-g groupname|#gid] [VAR=value] [-i|-s] []" +#define SUDO_USAGE5 " -e [-AknS] @BSDAUTH_USAGE@@SELINUX_USAGE@[-C fd] [-D level] @LOGINCAP_USAGE@[-g groupname|#gid] [-p prompt] [-u user name|#uid] file ..." /* * Configure script arguments used to build sudo. diff --git a/tgetpass.c b/src/tgetpass.c similarity index 80% rename from tgetpass.c rename to src/tgetpass.c index b64bb8d..bbd5652 100644 --- a/tgetpass.c +++ b/src/tgetpass.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 1998-2005, 2007-2010 + * Copyright (c) 1996, 1998-2005, 2007-2011 * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any @@ -57,30 +57,53 @@ static volatile sig_atomic_t signo[NSIG]; -static RETSIGTYPE handler __P((int)); -static char *getln __P((int, char *, size_t, int)); -static char *sudo_askpass __P((const char *)); +static void handler(int); +static char *getln(int, char *, size_t, int); +static char *sudo_askpass(const char *, const char *); + +#ifdef _PATH_SUDO_ASKPASS +const char *askpass_path = _PATH_SUDO_ASKPASS; +#else +const char *askpass_path; +#endif /* * Like getpass(3) but with timeout and echo flags. */ char * -tgetpass(prompt, timeout, flags) - const char *prompt; - int timeout; - int flags; +tgetpass(const char *prompt, int timeout, int flags) { sigaction_t sa, savealrm, saveint, savehup, savequit, saveterm; sigaction_t savetstp, savettin, savettou, savepipe; char *pass; + static const char *askpass; static char buf[SUDO_PASS_MAX + 1]; int i, input, output, save_errno, neednl = 0, need_restart; (void) fflush(stdout); + if (askpass == NULL) { + askpass = getenv("SUDO_ASKPASS"); + if (askpass == NULL || *askpass == '\0') + askpass = askpass_path; + } + + /* If no tty present and we need to disable echo, try askpass. */ + if (!ISSET(flags, TGP_STDIN|TGP_ECHO|TGP_ASKPASS|TGP_NOECHO_TRY) && + !tty_present()) { + if (askpass == NULL || getenv("DISPLAY") == NULL) { + warningx("no tty present and no askpass program specified"); + return NULL; + } + SET(flags, TGP_ASKPASS); + } + /* If using a helper program to get the password, run it instead. */ - if (ISSET(flags, TGP_ASKPASS) && user_askpass) - return sudo_askpass(prompt); + if (ISSET(flags, TGP_ASKPASS)) { + if (askpass == NULL || *askpass == '\0') + errorx(1, "no askpass program specified, try setting SUDO_ASKPASS"); + return sudo_askpass(askpass, prompt); + } restart: for (i = 0; i < NSIG; i++) @@ -100,7 +123,7 @@ restart: * generate SIGTTOU, so do it *before* installing the signal handlers. */ if (!ISSET(flags, TGP_ECHO)) { - if (def_pwfeedback) + if (ISSET(flags, TGP_MASK)) neednl = term_cbreak(input); else neednl = term_noecho(input); @@ -134,7 +157,7 @@ restart: if (timeout > 0) alarm(timeout); - pass = getln(input, buf, sizeof(buf), def_pwfeedback); + pass = getln(input, buf, sizeof(buf), ISSET(flags, TGP_MASK)); alarm(0); save_errno = errno; @@ -187,8 +210,7 @@ restore: * Fork a child and exec sudo-askpass to get the password from the user. */ static char * -sudo_askpass(prompt) - const char *prompt; +sudo_askpass(const char *askpass, const char *prompt) { static char buf[SUDO_PASS_MAX + 1], *pass; sigaction_t sa, saved_sa_pipe; @@ -207,11 +229,18 @@ sudo_askpass(prompt) warning("dup2"); _exit(255); } - (void) dup2(pfd[1], STDOUT_FILENO); - set_perms(PERM_FULL_USER); + (void) setuid(ROOT_UID); + if (setgid(user_details.gid)) { + warning("unable to set gid to %u", (unsigned int)user_details.gid); + _exit(255); + } + if (setuid(user_details.uid)) { + warning("unable to set uid to %u", (unsigned int)user_details.uid); + _exit(255); + } closefrom(STDERR_FILENO + 1); - execl(user_askpass, user_askpass, prompt, (char *)NULL); - warning("unable to run %s", user_askpass); + execl(askpass, askpass, prompt, (char *)NULL); + warning("unable to run %s", askpass); _exit(255); } @@ -234,11 +263,7 @@ sudo_askpass(prompt) extern int term_erase, term_kill; static char * -getln(fd, buf, bufsiz, feedback) - int fd; - char *buf; - size_t bufsiz; - int feedback; +getln(int fd, char *buf, size_t bufsiz, int feedback) { size_t left = bufsiz; ssize_t nr = -1; @@ -290,16 +315,15 @@ getln(fd, buf, bufsiz, feedback) return nr == 1 ? buf : NULL; } -static RETSIGTYPE -handler(s) - int s; +static void +handler(int s) { if (s != SIGALRM) signo[s] = 1; } int -tty_present() +tty_present(void) { int fd; diff --git a/src/ttysize.c b/src/ttysize.c new file mode 100644 index 0000000..81972d1 --- /dev/null +++ b/src/ttysize.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2010 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#include + +#include "missing.h" + +/* Compatibility with older tty systems. */ +#if !defined(TIOCGWINSZ) && defined(TIOCGSIZE) +# define TIOCGWINSZ TIOCGSIZE +# define winsize ttysize +# define ws_col ts_cols +# define ws_row ts_lines +#endif + +void +get_ttysize(int *rowp, int *colp) +{ + char *p; +#ifdef TIOCGWINSZ + struct winsize wsize; + + if (ioctl(STDERR_FILENO, TIOCGWINSZ, &wsize) == 0 && + wsize.ws_row != 0 && wsize.ws_col != 0) { + *rowp = wsize.ws_row; + *colp = wsize.ws_col; + return; + } +#endif + + /* Fall back on $LINES and $COLUMNS. */ + if ((p = getenv("LINES")) == NULL || (*rowp = atoi(p)) <= 0) + *rowp = 24; + if ((p = getenv("COLUMNS")) == NULL || (*colp = atoi(p)) <= 0) + *colp = 80; +} diff --git a/src/utmp.c b/src/utmp.c new file mode 100644 index 0000000..dc6d45f --- /dev/null +++ b/src/utmp.c @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2011 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +#include +#include +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS) +# include +# endif +# include +#endif /* HAVE_STRING_H */ +#ifdef HAVE_STRINGS_H +# include +#endif /* HAVE_STRINGS_H */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#if TIME_WITH_SYS_TIME +# include +#endif +#ifdef HAVE_UTMPX_H +# include +#else +# include +#endif /* HAVE_UTMPX_H */ +#ifdef HAVE_GETTTYENT +# include +#endif +#include + +#include "sudo.h" +#include "sudo_exec.h" + +/* + * Simplify handling of utmp vs. utmpx + */ +#if !defined(HAVE_GETUTXID) && defined(HAVE_GETUTID) +# define getutxline(u) getutline(u) +# define pututxline(u) pututline(u) +# define setutxent setutent(u) +# define endutxent endutent(u) +#endif /* !HAVE_GETUTXID && HAVE_GETUTID */ + +#ifdef HAVE_GETUTXID +typedef struct utmpx sudo_utmp_t; +#else +typedef struct utmp sudo_utmp_t; +/* Older systems have ut_name, not us_user */ +# if !defined(HAVE_STRUCT_UTMP_UT_USER) && !defined(ut_user) +# define ut_user ut_name +# endif +#endif + +/* HP-UX has __e_termination and __e_exit, others lack the __ */ +#if defined(HAVE_STRUCT_UTMPX_UT_EXIT_E_TERMINATION) || defined(HAVE_STRUCT_UTMP_UT_EXIT_E_TERMINATION) +# undef __e_termination +# define __e_termination e_termination +# undef __e_exit +# define __e_exit e_exit +#endif + +#if defined(HAVE_GETUTXID) || defined(HAVE_GETUTID) +/* + * Create ut_id from the new ut_line and the old ut_id. + */ +static void +utmp_setid(sudo_utmp_t *old, sudo_utmp_t *new) +{ + const char *line = new->ut_line; + size_t idlen; + + /* Skip over "tty" in the id if old entry did too. */ + if (strncmp(line, "tty", 3) == 0) { + idlen = MIN(sizeof(old->ut_id), 3); + if (strncmp(old->ut_id, "tty", idlen) != 0) + line += 3; + } + + /* Store as much as will fit, skipping parts of the beginning as needed. */ + idlen = strlen(line); + if (idlen > sizeof(new->ut_id)) { + line += idlen - sizeof(new->ut_id); + idlen = sizeof(new->ut_id); + } + strncpy(new->ut_id, line, idlen); +} +#endif /* HAVE_GETUTXID || HAVE_GETUTID */ + +/* + * Store time in utmp structure. + */ +static void +utmp_settime(sudo_utmp_t *ut) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + +#if defined(HAVE_STRUCT_UTMP_UT_TV) || defined(HAVE_STRUCT_UTMPX_UT_TV) + ut->ut_tv.tv_sec = tv.tv_sec; + ut->ut_tv.tv_usec = tv.tv_usec; +#else + ut->ut_time = tv.tv_sec; +#endif +} + +/* + * Fill in a utmp entry, using an old entry as a template if there is one. + */ +static void +utmp_fill(const char *line, const char *user, sudo_utmp_t *ut_old, + sudo_utmp_t *ut_new) +{ + if (ut_old == NULL) { + memset(ut_new, 0, sizeof(*ut_new)); + if (user == NULL) { + strncpy(ut_new->ut_user, user_details.username, + sizeof(ut_new->ut_user)); + } + } else if (ut_old != ut_new) { + memcpy(ut_new, ut_old, sizeof(*ut_new)); + } + if (user != NULL) + strncpy(ut_new->ut_user, user, sizeof(ut_new->ut_user)); + strncpy(ut_new->ut_line, line, sizeof(ut_new->ut_line)); +#if defined(HAVE_STRUCT_UTMPX_UT_ID) || defined(HAVE_STRUCT_UTMP_UT_ID) + utmp_setid(ut_old, ut_new); +#endif +#if defined(HAVE_STRUCT_UTMPX_UT_PID) || defined(HAVE_STRUCT_UTMP_UT_PID) + ut_new->ut_pid = getpid(); +#endif + utmp_settime(ut_new); +#if defined(HAVE_STRUCT_UTMPX_UT_TYPE) || defined(HAVE_STRUCT_UTMP_UT_TYPE) + ut_new->ut_type = USER_PROCESS; +#endif +} + +/* + * There are two basic utmp file types: + * + * POSIX: sequential access with new entries appended to the end. + * Manipulated via {get,put}utent()/{get,put}getutxent(). + * + * Legacy: sparse file indexed by ttyslot() * sizeof(struct utmp) + */ +#if defined(HAVE_GETUTXID) || defined(HAVE_GETUTID) +int +utmp_login(const char *from_line, const char *to_line, int ttyfd, + const char *user) +{ + sudo_utmp_t utbuf, *ut_old = NULL; + int rval = FALSE; + + /* Strip off /dev/ prefix from line as needed. */ + if (strncmp(to_line, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) + to_line += sizeof(_PATH_DEV) - 1; + setutxent(); + if (from_line != NULL) { + if (strncmp(from_line, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) + from_line += sizeof(_PATH_DEV) - 1; + + /* Lookup old line. */ + memset(&utbuf, 0, sizeof(utbuf)); + strncpy(utbuf.ut_line, from_line, sizeof(utbuf.ut_line)); + ut_old = getutxline(&utbuf); + } + utmp_fill(to_line, user, ut_old, &utbuf); + if (pututxline(&utbuf) != NULL) + rval = TRUE; + endutxent(); + + return rval; +} + +int +utmp_logout(const char *line, int status) +{ + int rval = FALSE; + sudo_utmp_t *ut, utbuf; + + /* Strip off /dev/ prefix from line as needed. */ + if (strncmp(line, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) + line += sizeof(_PATH_DEV) - 1; + + memset(&utbuf, 0, sizeof(utbuf)); + strncpy(utbuf.ut_line, line, sizeof(utbuf.ut_line)); + if ((ut = getutxline(&utbuf)) != NULL) { + memset(ut->ut_user, 0, sizeof(ut->ut_user)); +# if defined(HAVE_STRUCT_UTMPX_UT_TYPE) || defined(HAVE_STRUCT_UTMP_UT_TYPE) + ut->ut_type = DEAD_PROCESS; +# endif +# if defined(HAVE_STRUCT_UTMPX_UT_EXIT) || defined(HAVE_STRUCT_UTMP_UT_EXIT) + ut->ut_exit.__e_exit = WEXITSTATUS(status); + ut->ut_exit.__e_termination = WIFEXITED(status) ? WEXITSTATUS(status) : 0; +# endif + utmp_settime(ut); + if (pututxline(ut) != NULL) + rval = TRUE; + } + return rval; +} + +#else /* !HAVE_GETUTXID && !HAVE_GETUTID */ + +/* + * Find the slot for the specified line (tty name and file descriptor). + * Returns a slot suitable for seeking into utmp on success or <= 0 on error. + * If getttyent() is available we can use that to compute the slot. + */ +# ifdef HAVE_GETTTYENT +static int +utmp_slot(const char *line, int ttyfd) +{ + int slot = 1; + struct ttyent *tty; + + setttyent(); + while ((tty = getttyent()) != NULL) { + if (strcmp(line, tty->ty_name) == 0) + break; + slot++; + } + endttyent(); + return tty ? slot : 0; +} +# else +static int +utmp_slot(const char *line, int ttyfd) +{ + int sfd, slot; + + /* + * Temporarily point stdin to the tty since ttyslot() + * doesn't take an argument. + */ + if ((sfd = dup(STDIN_FILENO)) == -1) + error(1, "Can't save stdin"); + if (dup2(ttyfd, STDIN_FILENO) == -1) + error(1, "Can't dup2 stdin"); + slot = ttyslot(); + if (dup2(sfd, STDIN_FILENO) == -1) + error(1, "Can't restore stdin"); + close(sfd); + + return slot; +} +# endif /* HAVE_GETTTYENT */ + +int +utmp_login(const char *from_line, const char *to_line, int ttyfd, + const char *user) +{ + sudo_utmp_t utbuf, *ut_old = NULL; + int slot, rval = FALSE; + FILE *fp; + + /* Strip off /dev/ prefix from line as needed. */ + if (strncmp(to_line, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) + to_line += sizeof(_PATH_DEV) - 1; + + /* Find slot for new entry. */ + slot = utmp_slot(to_line, ttyfd); + if (slot <= 0) + goto done; + + if ((fp = fopen(_PATH_UTMP, "r+")) == NULL) + goto done; + + if (from_line != NULL) { + if (strncmp(from_line, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) + from_line += sizeof(_PATH_DEV) - 1; + + /* Lookup old line. */ + while (fread(&utbuf, sizeof(utbuf), 1, fp) == 1) { +# ifdef HAVE_STRUCT_UTMP_UT_ID + if (utbuf.ut_type != LOGIN_PROCESS && utbuf.ut_type != USER_PROCESS) + continue; +# endif + if (utbuf.ut_user[0] && + !strncmp(utbuf.ut_line, from_line, sizeof(utbuf.ut_line))) { + ut_old = &utbuf; + break; + } + } + } + utmp_fill(to_line, user, ut_old, &utbuf); + if (fseek(fp, slot * (long)sizeof(utbuf), SEEK_SET) == 0) { + if (fwrite(&utbuf, sizeof(utbuf), 1, fp) == 1) + rval = TRUE; + } + fclose(fp); + +done: + return rval; +} + +int +utmp_logout(const char *line, int status) +{ + sudo_utmp_t utbuf; + int rval = FALSE; + FILE *fp; + + if ((fp = fopen(_PATH_UTMP, "r+")) == NULL) + return rval; + + /* Strip off /dev/ prefix from line as needed. */ + if (strncmp(line, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) + line += sizeof(_PATH_DEV) - 1; + + while (fread(&utbuf, sizeof(utbuf), 1, fp) == 1) { + if (!strncmp(utbuf.ut_line, line, sizeof(utbuf.ut_line))) { + memset(utbuf.ut_user, 0, sizeof(utbuf.ut_user)); +# if defined(HAVE_STRUCT_UTMP_UT_TYPE) + utbuf.ut_type = DEAD_PROCESS; +# endif + utmp_settime(&utbuf); + /* Back up and overwrite record. */ + if (fseek(fp, 0L - (long)sizeof(utbuf), SEEK_CUR) == 0) { + if (fwrite(&utbuf, sizeof(utbuf), 1, fp) == 1) + rval = TRUE; + } + break; + } + } + fclose(fp); + + return rval; +} +#endif /* HAVE_GETUTXID || HAVE_GETUTID */ diff --git a/strcasecmp.c b/strcasecmp.c deleted file mode 100644 index 9ab451c..0000000 --- a/strcasecmp.c +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2004-2005 Todd C. Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - */ - -#include - -#include - -#include "missing.h" - -/* - * Case insensitive string compare routines, same semantics as str[n]cmp() - * (assumes ASCII..). - * Derived from a public domain implementation included with the pdksh shell. - */ -static const char ichars[256] = { - 0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, - 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, - 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, - 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, - 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, - 0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g', - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', - 'x', 'y', 'z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, - 0x60, 'a', 'b', 'c', 'd', 'e', 'f', 'g', - 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', - 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', - 'x', 'y', 'z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f, - 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, - 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f, - 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, - 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f, - 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, - 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf, - 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, - 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf, - 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, - 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf, - 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, - 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, - 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, - 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, - 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, - 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff -}; - -int -strcasecmp(s1, s2) - const char *s1; - const char *s2; -{ - const unsigned char *us1 = (const unsigned char *) s1; - const unsigned char *us2 = (const unsigned char *) s2; - - while (ichars[*us1] == ichars[*us2++]) { - if (*us1++ == '\0') - return 0; - } - return ichars[*us1] - ichars[*--us2]; -} - -int -strncasecmp(s1, s2, n) - const char *s1; - const char *s2; - size_t n; -{ - const unsigned char *us1 = (const unsigned char *) s1; - const unsigned char *us2 = (const unsigned char *) s2; - - while (n != 0 && ichars[*us1] == ichars[*us2++]) { - if (*us1++ == '\0') - return 0; - n--; - } - return n ? ichars[*us1] - ichars[*--us2] : 0; -} diff --git a/strerror.c b/strerror.c deleted file mode 100644 index 88b888b..0000000 --- a/strerror.c +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 1999-2005 Todd C. Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Sponsored in part by the Defense Advanced Research Projects - * Agency (DARPA) and Air Force Research Laboratory, Air Force - * Materiel Command, USAF, under agreement number F39502-99-1-0512. - */ - -#include - -#include - -#include -#include - -#include "missing.h" - -/* - * Map errno -> error string. - */ -char * -strerror(n) - int n; -{ - extern int sys_nerr; - extern char *sys_errlist[]; - - if (n > 0 && n < sys_nerr) - return sys_errlist[n]; - errno = EINVAL; - return "Unknown error"; -} diff --git a/sudo.c b/sudo.c deleted file mode 100644 index 0dc2e78..0000000 --- a/sudo.c +++ /dev/null @@ -1,1335 +0,0 @@ -/* - * Copyright (c) 1993-1996, 1998-2010 Todd C. Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Sponsored in part by the Defense Advanced Research Projects - * Agency (DARPA) and Air Force Research Laboratory, Air Force - * Materiel Command, USAF, under agreement number F39502-99-1-0512. - * - * For a brief history of sudo, please see the HISTORY file included - * with this distribution. - */ - -#define _SUDO_MAIN - -#ifdef __TANDEM -# include -#endif - -#include - -#include -#include -#include -#include -#include -#ifdef HAVE_SETRLIMIT -# include -# include -#endif -#include -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif /* STDC_HEADERS */ -#ifdef HAVE_STRING_H -# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS) -# include -# endif -# include -#endif /* HAVE_STRING_H */ -#ifdef HAVE_STRINGS_H -# include -#endif /* HAVE_STRINGS_H */ -#ifdef HAVE_UNISTD_H -# include -#endif /* HAVE_UNISTD_H */ -#include -#include -#include -#include -#include -#include -#if TIME_WITH_SYS_TIME -# include -#endif -#ifdef HAVE_SETLOCALE -# include -#endif -#include -#include -#if defined(HAVE_GETPRPWNAM) && defined(HAVE_SET_AUTH_PARAMETERS) -# ifdef __hpux -# undef MAXINT -# include -# else -# include -# endif /* __hpux */ -# include -#endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */ -#ifdef HAVE_LOGIN_CAP_H -# include -# ifndef LOGIN_DEFROOTCLASS -# define LOGIN_DEFROOTCLASS "daemon" -# endif -#endif -#ifdef HAVE_MBR_CHECK_MEMBERSHIP -# include -#endif - -#include "sudo.h" -#include "lbuf.h" -#include "interfaces.h" -#include - -#ifdef USING_NONUNIX_GROUPS -# include "nonunix.h" -#endif - -#if defined(HAVE_PAM) && !defined(NO_PAM_SESSION) -# define CMND_WAIT TRUE -#else -# define CMND_WAIT FALSE -#endif - -/* - * Prototypes - */ -static void init_vars __P((char **)); -static int set_cmnd __P((int)); -static void initial_setup __P((void)); -static void set_loginclass __P((struct passwd *)); -static void set_runasgr __P((char *)); -static void set_runaspw __P((char *)); -static void show_version __P((void)); -static void create_admin_success_flag __P((void)); -extern int sudo_edit __P((int, char **, char **)); -int run_command __P((const char *path, char *argv[], char *envp[], uid_t uid, int dowait)); /* XXX should be in sudo.h */ - -/* - * Globals - */ -int Argc, NewArgc; -char **Argv, **NewArgv; -char *prev_user; -int user_closefrom = -1; -struct sudo_user sudo_user; -struct passwd *list_pw; -struct interface *interfaces; -int num_interfaces; -int tgetpass_flags; -int long_list; -uid_t timestamp_uid; -extern int errorlineno; -extern int parse_error; -extern char *errorfile; -#if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL) -static struct rlimit corelimit; -#endif /* RLIMIT_CORE && !SUDO_DEVEL */ -#if defined(__linux__) -static struct rlimit nproclimit; -#endif -#ifdef HAVE_LOGIN_CAP_H -login_cap_t *lc; -#endif /* HAVE_LOGIN_CAP_H */ -sigaction_t saved_sa_int, saved_sa_quit, saved_sa_tstp; -char *runas_user; -char *runas_group; -static struct sudo_nss_list *snl; -int sudo_mode; - -/* For getopt(3) */ -extern char *optarg; -extern int optind; - -int -main(argc, argv, envp) - int argc; - char *argv[]; - char *envp[]; -{ - int sources = 0, validated; - int fd, cmnd_status, pwflag, rc = 0; - sigaction_t sa; - struct sudo_nss *nss; -#if defined(SUDO_DEVEL) && defined(__OpenBSD__) - extern char *malloc_options; - malloc_options = "AFGJPR"; -#endif - -#ifdef HAVE_SETLOCALE - setlocale(LC_ALL, ""); -#endif - - Argv = argv; - if ((Argc = argc) < 1) - usage(1); - - /* Must be done as the first thing... */ -#if defined(HAVE_GETPRPWNAM) && defined(HAVE_SET_AUTH_PARAMETERS) - (void) set_auth_parameters(Argc, Argv); -# ifdef HAVE_INITPRIVS - initprivs(); -# endif -#endif /* HAVE_GETPRPWNAM && HAVE_SET_AUTH_PARAMETERS */ - - if (geteuid() != 0) - errorx(1, "must be setuid root"); - - /* - * Signal setup: - * Ignore keyboard-generated signals so the user cannot interrupt - * us at some point and avoid the logging. - * Install handler to wait for children when they exit. - */ - zero_bytes(&sa, sizeof(sa)); - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_RESTART; - sa.sa_handler = SIG_IGN; - (void) sigaction(SIGINT, &sa, &saved_sa_int); - (void) sigaction(SIGQUIT, &sa, &saved_sa_quit); - (void) sigaction(SIGTSTP, &sa, &saved_sa_tstp); - - /* Initialize environment functions (including replacements). */ - env_init(FALSE); - - /* - * Turn off core dumps and make sure fds 0-2 are open. - */ - initial_setup(); - sudo_setpwent(); - sudo_setgrent(); - - /* Parse our arguments. */ - sudo_mode = parse_args(Argc, Argv); - - /* Setup defaults data structures. */ - init_defaults(); - - /* Load the list of local ip addresses and netmasks. */ - load_interfaces(); - - pwflag = 0; - if (ISSET(sudo_mode, MODE_SHELL)) - user_cmnd = "shell"; - else if (ISSET(sudo_mode, MODE_EDIT)) - user_cmnd = "sudoedit"; - else { - switch (sudo_mode) { - case MODE_VERSION: - show_version(); - break; - case MODE_HELP: - help(); - break; - case MODE_VALIDATE: - case MODE_VALIDATE|MODE_INVALIDATE: - user_cmnd = "validate"; - pwflag = I_VERIFYPW; - break; - case MODE_KILL: - case MODE_INVALIDATE: - user_cmnd = "kill"; - pwflag = -1; - break; - case MODE_LISTDEFS: - list_options(); - exit(0); - break; - case MODE_LIST: - case MODE_LIST|MODE_INVALIDATE: - user_cmnd = "list"; - pwflag = I_LISTPW; - break; - case MODE_CHECK: - case MODE_CHECK|MODE_INVALIDATE: - pwflag = I_LISTPW; - break; - } - } - - /* Must have a command to run... */ - if (user_cmnd == NULL && NewArgc == 0) - usage(1); - - init_vars(envp); /* XXX - move this later? */ - -#ifdef USING_NONUNIX_GROUPS - sudo_nonunix_groupcheck_init(); /* initialise nonunix groups impl */ -#endif /* USING_NONUNIX_GROUPS */ - - /* Parse nsswitch.conf for sudoers order. */ - snl = sudo_read_nss(); - - /* Open and parse sudoers, set global defaults */ - tq_foreach_fwd(snl, nss) { - if (nss->open(nss) == 0 && nss->parse(nss) == 0) { - sources++; - if (nss->setdefs(nss) != 0) - log_error(NO_STDERR|NO_EXIT, "problem with defaults entries"); - } - } - if (sources == 0) - log_error(0, "no valid sudoers sources found, quitting"); - - /* XXX - collect post-sudoers parse settings into a function */ - - /* - * 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. - */ - 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); - - if (!update_defaults(SETDEF_RUNAS)) - log_error(NO_STDERR|NO_EXIT, "problem with defaults entries"); - - if (def_fqdn) - set_fqdn(); /* deferred until after sudoers is parsed */ - - /* Set login class if applicable. */ - set_loginclass(sudo_user.pw); - - /* Update initial shell now that runas is set. */ - if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) - NewArgv[0] = estrdup(runas_pw->pw_shell); - - /* 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)); - cleanup(0); - exit(0); - } - - /* Is root even allowed to run sudo? */ - if (user_uid == 0 && !def_root_sudo) { - (void) fprintf(stderr, - "Sorry, %s has been configured to not allow root to run it.\n", - getprogname()); - exit(1); - } - - /* Check for -C overriding def_closefrom. */ - if (user_closefrom >= 0 && user_closefrom != def_closefrom) { - if (!def_closefrom_override) - errorx(1, "you are not permitted to use the -C option"); - else - def_closefrom = user_closefrom; - } - - cmnd_status = set_cmnd(sudo_mode); - -#ifdef HAVE_SETLOCALE - if (!setlocale(LC_ALL, def_sudoers_locale)) { - warningx("unable to set locale to \"%s\", using \"C\"", - def_sudoers_locale); - setlocale(LC_ALL, "C"); - } -#endif - - validated = FLAG_NO_USER | FLAG_NO_HOST; - tq_foreach_fwd(snl, nss) { - validated = nss->lookup(nss, validated, pwflag); - - if (ISSET(validated, VALIDATE_OK)) { - /* Handle "= auth" in netsvc.conf */ - if (nss->ret_if_found) - break; - } else { - /* Handle [NOTFOUND=return] */ - if (nss->ret_if_notfound) - break; - } - } - - if (safe_cmnd == NULL) - safe_cmnd = estrdup(user_cmnd); - -#ifdef HAVE_SETLOCALE - setlocale(LC_ALL, ""); -#endif - - /* 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. - */ - if (def_timestampowner) { - struct passwd *pw; - - if (*def_timestampowner == '#') - pw = sudo_getpwuid(atoi(def_timestampowner + 1)); - else - pw = sudo_getpwnam(def_timestampowner); - if (!pw) - log_error(0, "timestamp owner (%s): No such user", - def_timestampowner); - timestamp_uid = pw->pw_uid; - pw_delref(pw); - } - - /* If given the -P option, set the "preserve_groups" flag. */ - if (ISSET(sudo_mode, MODE_PRESERVE_GROUPS)) - def_preserve_groups = TRUE; - - /* If no command line args and "set_home" is not set, error out. */ - if (ISSET(sudo_mode, MODE_IMPLIED_SHELL) && !def_shell_noargs) - usage(1); - - /* Bail if a tty is required and we don't have one. */ - if (def_requiretty) { - if ((fd = open(_PATH_TTY, O_RDWR|O_NOCTTY)) == -1) { - audit_failure(NewArgv, "no tty"); - log_error(NO_MAIL, "sorry, you must have a tty to run sudo"); - } else - (void) close(fd); - } - - /* Use askpass value from sudoers unless user specified their own. */ - if (def_askpass && !user_askpass) - user_askpass = def_askpass; - - /* - * We don't reset the environment for sudoedit or if the user - * specified the -E command line flag and they have setenv privs. - */ - if (ISSET(sudo_mode, MODE_EDIT) || - (ISSET(sudo_mode, MODE_PRESERVE_ENV) && def_setenv)) - def_env_reset = FALSE; - - /* Build a new environment that avoids any nasty bits. */ - rebuild_env(def_noexec); - - /* Require a password if sudoers says so. */ - if (def_authenticate) - check_user(validated, sudo_mode); - - /* If run as root with SUDO_USER set, set sudo_user.pw to that user. */ - /* XXX - causes confusion when root is not listed in sudoers */ - if (sudo_mode & (MODE_RUN | MODE_EDIT) && prev_user != NULL) { - if (user_uid == 0 && strcmp(prev_user, "root") != 0) { - struct passwd *pw; - - if ((pw = sudo_getpwnam(prev_user)) != NULL) { - if (sudo_user.pw != NULL) - pw_delref(sudo_user.pw); - sudo_user.pw = pw; -#ifdef HAVE_MBR_CHECK_MEMBERSHIP - mbr_uid_to_uuid(user_uid, user_uuid); -#endif - } - } - } - - if (ISSET(validated, VALIDATE_OK)) { - /* Create Ubuntu-style dot file to indicate sudo was successful. */ - create_admin_success_flag(); - - /* Finally tell the user if the command did not exist. */ - if (cmnd_status == NOT_FOUND_DOT) { - audit_failure(NewArgv, "command in current directory"); - errorx(1, "ignoring `%s' found in '.'\nUse `sudo ./%s' if this is the `%s' you wish to run.", user_cmnd, user_cmnd, user_cmnd); - } else if (cmnd_status == NOT_FOUND) { - audit_failure(NewArgv, "%s: command not found", user_cmnd); - errorx(1, "%s: command not found", user_cmnd); - } - - /* If user specified env vars make sure sudoers allows it. */ - if (ISSET(sudo_mode, MODE_RUN) && !def_setenv) { - if (ISSET(sudo_mode, MODE_PRESERVE_ENV)) - log_error(NO_MAIL, - "sorry, you are not allowed to preserve the environment"); - else - validate_env_vars(sudo_user.env_vars); - } - -#ifdef _PATH_SUDO_IO_LOGDIR - /* Get next session ID so we can log it. */ - if (ISSET(sudo_mode, (MODE_RUN | MODE_EDIT)) && (def_log_input || def_log_output)) - io_nextid(); -#endif - log_allowed(validated); - if (ISSET(sudo_mode, MODE_CHECK)) - rc = display_cmnd(snl, list_pw ? list_pw : sudo_user.pw); - else if (ISSET(sudo_mode, MODE_LIST)) - display_privs(snl, list_pw ? list_pw : sudo_user.pw); - - /* Cleanup sudoers sources */ - tq_foreach_fwd(snl, nss) - nss->close(nss); - -#ifdef USING_NONUNIX_GROUPS - /* Finished with the groupcheck code */ - sudo_nonunix_groupcheck_cleanup(); -#endif - - /* Deferred exit due to sudo_ldap_close() */ - if (ISSET(sudo_mode, (MODE_VALIDATE|MODE_CHECK|MODE_LIST))) { - if (list_pw != NULL) - pw_delref(list_pw); - exit(rc); - } - - /* Must audit before uid change. */ - audit_success(NewArgv); - - if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) { - char *p; - - /* Convert /bin/sh -> -sh so shell knows it is a login shell */ - if ((p = strrchr(NewArgv[0], '/')) == NULL) - p = NewArgv[0]; - *p = '-'; - NewArgv[0] = p; - -#if defined(__linux__) || defined(_AIX) - /* Insert system-wide environment variables. */ - read_env_file(_PATH_ENVIRONMENT, TRUE); -#endif - } - - if (ISSET(sudo_mode, MODE_RUN)) { - /* Insert system-wide environment variables. */ - if (def_env_file) - read_env_file(def_env_file, FALSE); - - /* Insert user-specified environment variables. */ - insert_env_vars(sudo_user.env_vars); - } - - /* Restore signal handlers before we exec. */ - (void) sigaction(SIGINT, &saved_sa_int, NULL); - (void) sigaction(SIGQUIT, &saved_sa_quit, NULL); - (void) sigaction(SIGTSTP, &saved_sa_tstp, NULL); - - if (ISSET(sudo_mode, MODE_EDIT)) { - exit(sudo_edit(NewArgc, NewArgv, envp)); - } else { - exit(run_command(safe_cmnd, NewArgv, env_get(), runas_pw->pw_uid, - CMND_WAIT)); - } - } else if (ISSET(validated, FLAG_NO_USER | FLAG_NO_HOST)) { - audit_failure(NewArgv, "No user or host"); - log_denial(validated, 1); - exit(1); - } else { - if (def_path_info) { - /* - * We'd like to not leak path info at all here, but that can - * *really* confuse the users. To really close the leak we'd - * have to say "not allowed to run foo" even when the problem - * is just "no foo in path" since the user can trivially set - * their path to just contain a single dir. - */ - log_denial(validated, - !(cmnd_status == NOT_FOUND_DOT || cmnd_status == NOT_FOUND)); - if (cmnd_status == NOT_FOUND) - warningx("%s: command not found", user_cmnd); - else if (cmnd_status == NOT_FOUND_DOT) - warningx("ignoring `%s' found in '.'\nUse `sudo ./%s' if this is the `%s' you wish to run.", user_cmnd, user_cmnd, user_cmnd); - } else { - /* Just tell the user they are not allowed to run foo. */ - log_denial(validated, 1); - } - audit_failure(NewArgv, "validation failure"); - exit(1); - } - exit(0); /* not reached */ -} - -/* - * Escape any non-alpha numeric or blank characters to make sure - * they are not interpreted specially by the shell. - */ -static char * -escape_cmnd(src) - const char *src; -{ - char *cmnd, *dst; - - /* Worst case scenario, we have to escape everything. */ - cmnd = dst = emalloc((2 * strlen(src)) + 1); - while (*src != '\0') { - if (!isalnum((unsigned char)*src) && !isspace((unsigned char)*src) && - *src != '_' && *src != '-') { - /* quote potential meta character */ - *dst++ = '\\'; - } - *dst++ = *src++; - } - *dst++ = '\0'; - - return cmnd; -} - -/* - * Initialize timezone, set umask, fill in ``sudo_user'' struct and - * load the ``interfaces'' array. - */ -static void -init_vars(envp) - char **envp; -{ - char *p, **ep, thost[MAXHOSTNAMELEN + 1]; - int nohostname; - - /* Sanity check command from user. */ - if (user_cmnd == NULL && strlen(NewArgv[0]) >= PATH_MAX) - errorx(1, "%s: File name too long", NewArgv[0]); - -#ifdef HAVE_TZSET - (void) tzset(); /* set the timezone if applicable */ -#endif /* HAVE_TZSET */ - - /* Default value for cmnd and cwd, overridden later. */ - if (user_cmnd == NULL) - user_cmnd = NewArgv[0]; - (void) strlcpy(user_cwd, "unknown", sizeof(user_cwd)); - - /* - * We avoid gethostbyname() if possible since we don't want - * sudo to block if DNS or NIS is hosed. - * "host" is the (possibly fully-qualified) hostname and - * "shost" is the unqualified form of the hostname. - */ - nohostname = gethostname(thost, sizeof(thost)); - if (nohostname) { - user_host = user_shost = "localhost"; - } else { - thost[sizeof(thost) - 1] = '\0'; - user_host = estrdup(thost); - if ((p = strchr(user_host, '.'))) { - *p = '\0'; - user_shost = estrdup(user_host); - *p = '.'; - } else { - user_shost = user_host; - } - } - - if ((p = ttyname(STDIN_FILENO)) || (p = ttyname(STDOUT_FILENO)) || - (p = ttyname(STDERR_FILENO))) { - user_tty = user_ttypath = estrdup(p); - if (strncmp(user_tty, _PATH_DEV, sizeof(_PATH_DEV) - 1) == 0) - user_tty += sizeof(_PATH_DEV) - 1; - } else - user_tty = "unknown"; - - for (ep = envp; *ep; ep++) { - /* XXX - don't fill in if empty string */ - switch (**ep) { - case 'D': - if (strncmp("DISPLAY=", *ep, 8) == 0) - user_display = *ep + 8; - break; - case 'K': - if (strncmp("KRB5CCNAME=", *ep, 11) == 0) - user_ccname = *ep + 11; - break; - case 'P': - if (strncmp("PATH=", *ep, 5) == 0) - user_path = *ep + 5; - break; - case 'S': - if (strncmp("SHELL=", *ep, 6) == 0) - user_shell = *ep + 6; - else if (!user_prompt && strncmp("SUDO_PROMPT=", *ep, 12) == 0) - user_prompt = *ep + 12; - else if (strncmp("SUDO_USER=", *ep, 10) == 0) - prev_user = *ep + 10; - else if (strncmp("SUDO_ASKPASS=", *ep, 13) == 0) - user_askpass = *ep + 13; - break; - } - } - - /* - * Stash a local copy of the user's struct passwd. - */ - if ((sudo_user.pw = sudo_getpwuid(getuid())) == NULL) { - /* Need to make a fake struct passwd for logging to work. */ - struct passwd pw; - char pw_name[MAX_UID_T_LEN + 1]; - - pw.pw_uid = getuid(); - (void) snprintf(pw_name, sizeof(pw_name), "%u", - (unsigned int) pw.pw_uid); - pw.pw_name = pw_name; - sudo_user.pw = &pw; - - /* - * If we are in -k/-K mode, just spew to stderr. It is not unusual for - * users to place "sudo -k" in a .logout file which can cause sudo to - * be run during reboot after the YP/NIS/NIS+/LDAP/etc daemon has died. - */ - if (sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE) - errorx(1, "unknown uid: %s", pw_name); - log_error(0, "unknown uid: %s", pw_name); - } -#ifdef HAVE_MBR_CHECK_MEMBERSHIP - mbr_uid_to_uuid(user_uid, user_uuid); -#endif - if (user_shell == NULL || *user_shell == '\0') - user_shell = estrdup(sudo_user.pw->pw_shell); - - /* It is now safe to use log_error() and set_perms() */ - -#ifdef HAVE_GETGROUPS - if ((user_ngroups = getgroups(0, NULL)) > 0) { - user_groups = emalloc2(user_ngroups, sizeof(GETGROUPS_T)); - if (getgroups(user_ngroups, user_groups) < 0) - log_error(USE_ERRNO|MSG_ONLY, "can't get group vector"); - } -#endif - - if (nohostname) - log_error(USE_ERRNO|MSG_ONLY, "can't get hostname"); - - /* - * Get current working directory. Try as user, fall back to root. - */ - set_perms(PERM_USER); - if (!getcwd(user_cwd, sizeof(user_cwd))) { - set_perms(PERM_ROOT); - if (!getcwd(user_cwd, sizeof(user_cwd))) { - warningx("cannot get working directory"); - (void) strlcpy(user_cwd, "unknown", sizeof(user_cwd)); - } - } else - set_perms(PERM_ROOT); - - /* - * If in shell or edit mode, or if running a pseudo-command - * such as "list", we need to redo NewArgv and NewArgc. - */ - if (ISSET(sudo_mode, MODE_SHELL)) { - char **av; - - /* Allocate an extra slot for execve() failure (ENOEXEC). */ - av = (char **) emalloc2(5, sizeof(char *)); - av++; - - av[0] = user_shell; /* may be updated later */ - if (NewArgc > 0) { - size_t cmnd_size; - char *cmnd, *src, *dst, *end; - cmnd_size = (size_t) (NewArgv[NewArgc - 1] - NewArgv[0]) + - strlen(NewArgv[NewArgc - 1]) + 1; - cmnd = dst = emalloc(cmnd_size); - src = NewArgv[0]; - for (end = src + cmnd_size - 1; src < end; src++, dst++) - *dst = *src == '\0' ? ' ' : *src; - *dst = '\0'; - av[1] = "-c"; - av[2] = cmnd; - NewArgc = 2; - } - av[++NewArgc] = NULL; - NewArgv = av; - } else if (ISSET(sudo_mode, MODE_EDIT) || NewArgc == 0) { - NewArgv--; - NewArgc++; - NewArgv[0] = user_cmnd; - } -} - -/* - * Fill in user_cmnd, user_args, user_base and user_stat variables - * and apply any command-specific defaults entries. - */ -static int -set_cmnd(sudo_mode) - int sudo_mode; -{ - int rval; - char *path = user_path; - - /* Resolve the path and return. */ - rval = FOUND; - user_stat = emalloc(sizeof(struct stat)); - if (sudo_mode & (MODE_RUN | MODE_EDIT | MODE_CHECK)) { - if (ISSET(sudo_mode, MODE_RUN | MODE_CHECK)) { - if (def_secure_path && !user_is_exempt()) - path = def_secure_path; - set_perms(PERM_RUNAS); - rval = find_path(NewArgv[0], &user_cmnd, user_stat, path, - def_ignore_dot); - set_perms(PERM_ROOT); - if (rval != FOUND) { - /* Failed as root, try as invoking user. */ - set_perms(PERM_USER); - rval = find_path(NewArgv[0], &user_cmnd, user_stat, path, - def_ignore_dot); - set_perms(PERM_ROOT); - } - } - - /* set user_args */ - if (NewArgc > 1) { - char *to, **from; - size_t size, n; - - /* If we didn't realloc NewArgv it is contiguous so just count. */ - if (!ISSET(sudo_mode, MODE_SHELL)) { - size = (size_t) (NewArgv[NewArgc-1] - NewArgv[1]) + - strlen(NewArgv[NewArgc-1]) + 1; - } else { - for (size = 0, from = NewArgv + 1; *from; from++) - size += strlen(*from) + 1; - } - - /* Alloc and build up user_args. */ - user_args = (char *) emalloc(size); - for (to = user_args, from = NewArgv + 1; *from; from++) { - n = strlcpy(to, *from, size - (to - user_args)); - if (n >= size - (to - user_args)) - errorx(1, "internal error, init_vars() overflow"); - to += n; - *to++ = ' '; - } - *--to = '\0'; - } - } - if ((user_base = strrchr(user_cmnd, '/')) != NULL) - user_base++; - else - user_base = user_cmnd; - - if (!update_defaults(SETDEF_CMND)) - log_error(NO_STDERR|NO_EXIT, "problem with defaults entries"); - - if (!runas_user && !runas_group) - set_runaspw(def_runas_default); /* may have been updated above */ - - return rval; -} - -/* - * Setup the execution environment immediately prior to the call to execve() - * Returns TRUE on success and FALSE on failure. - */ -int -exec_setup(rbac_enabled, ttyname, ttyfd) - int rbac_enabled; - const char *ttyname; - int ttyfd; -{ - int rval = FALSE; - -#ifdef HAVE_SELINUX - if (rbac_enabled) { - if (selinux_setup(user_role, user_type, ttyname, ttyfd) == -1) - goto done; - } -#endif - - /* - * For sudoedit, the command runas a the user with no additional setup. - */ - if (ISSET(sudo_mode, MODE_EDIT)) { - set_perms(PERM_FULL_USER); - rval = TRUE; - goto done; - } - - /* - * Set umask based on sudoers. - * If user's umask is more restrictive, OR in those bits too - * unless umask_override is set. - */ - if (def_umask != 0777) { - if (def_umask_override) { - umask(def_umask); - } else { - mode_t mask = umask(def_umask); - mask |= def_umask; - if (mask != def_umask) - umask(mask); - } - } - - /* Restore coredumpsize resource limit. */ -#if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL) - (void) setrlimit(RLIMIT_CORE, &corelimit); -#endif /* RLIMIT_CORE && !SUDO_DEVEL */ - - if (ISSET(sudo_mode, MODE_RUN)) - set_perms(PERM_FULL_RUNAS); - - if (ISSET(sudo_mode, MODE_LOGIN_SHELL)) { - /* Change to target user's homedir. */ - if (chdir(runas_pw->pw_dir) == -1) { - warning("unable to change directory to %s", runas_pw->pw_dir); - goto done; - } - } - - /* - * Restore nproc resource limit if pam_limits didn't do it for us. - * We must do this *after* the uid change to avoid potential EAGAIN - * from setuid(). - */ -#if defined(__linux__) - { - struct rlimit rl; - if (getrlimit(RLIMIT_NPROC, &rl) == 0) { - if (rl.rlim_cur == RLIM_INFINITY && rl.rlim_max == RLIM_INFINITY) - (void) setrlimit(RLIMIT_NPROC, &nproclimit); - } - } -#endif - - /* Close the password and group files and free up memory. */ - sudo_endpwent(); - sudo_endgrent(); - pw_delref(sudo_user.pw); - pw_delref(runas_pw); - if (runas_gr != NULL) - gr_delref(runas_gr); - - rval = TRUE; - -done: - return rval; -} - -/* - * Run the command and wait for it to complete. - */ -int -run_command(path, argv, envp, uid, dowait) - const char *path; - char *argv[]; - char *envp[]; - uid_t uid; - int dowait; -{ - struct command_status cstat; - int exitcode = 1; - -#ifdef PROFILING - exit(0); -#endif - - cstat.type = CMD_INVALID; - cstat.val = 0; - - /* Escape meta chars if running a shell with args. */ - if (ISSET(sudo_mode, MODE_SHELL) && argv[1] != NULL) { - char *cmnd = argv[2]; - argv[2] = escape_cmnd(cmnd); - efree(cmnd); - } - - sudo_execve(path, argv, envp, uid, &cstat, dowait, - ISSET(sudo_mode, MODE_BACKGROUND)); - - switch (cstat.type) { - case CMD_ERRNO: - /* exec_setup() or execve() returned an error. */ - warningx("unable to execute %s: %s", path, strerror(cstat.val)); - exitcode = 127; - break; - case CMD_WSTATUS: - /* Command ran, exited or was killed. */ - if (WIFEXITED(cstat.val)) - exitcode = WEXITSTATUS(cstat.val); - else if (WIFSIGNALED(cstat.val)) - exitcode = WTERMSIG(cstat.val) | 128; - break; - default: - warningx("unexpected child termination condition: %d", cstat.type); - break; - } -#ifdef HAVE_PAM - pam_end_session(); -#endif /* HAVE_PAM */ -#ifdef _PATH_SUDO_IO_LOGDIR - io_log_close(); -#endif - sudo_endpwent(); - sudo_endgrent(); - pw_delref(sudo_user.pw); - pw_delref(runas_pw); - if (runas_gr != NULL) - gr_delref(runas_gr); - return exitcode; -} - -/* - * Open sudoers and sanity check mode/owner/type. - * Returns a handle to the sudoers file or NULL on error. - */ -FILE * -open_sudoers(sudoers, doedit, keepopen) - const char *sudoers; - int doedit; - int *keepopen; -{ - struct stat statbuf; - FILE *fp = NULL; - int rootstat; - - /* - * Fix the mode and group on sudoers file from old default. - * Only works if file system is readable/writable by root. - */ - if ((rootstat = stat_sudoers(sudoers, &statbuf)) == 0 && - SUDOERS_UID == statbuf.st_uid && SUDOERS_MODE != 0400 && - (statbuf.st_mode & 0007777) == 0400) { - - if (chmod(sudoers, SUDOERS_MODE) == 0) { - warningx("fixed mode on %s", sudoers); - SET(statbuf.st_mode, SUDOERS_MODE); - if (statbuf.st_gid != SUDOERS_GID) { - if (chown(sudoers, (uid_t) -1, SUDOERS_GID) == 0) { - warningx("set group on %s", sudoers); - statbuf.st_gid = SUDOERS_GID; - } else - warning("unable to set group on %s", sudoers); - } - } else - warning("unable to fix mode on %s", sudoers); - } - - /* - * Sanity checks on sudoers file. Must be done as sudoers - * file owner. We already did a stat as root, so use that - * data if we can't stat as sudoers file owner. - */ - set_perms(PERM_SUDOERS); - - if (rootstat != 0 && stat_sudoers(sudoers, &statbuf) != 0) - log_error(USE_ERRNO|NO_EXIT, "can't stat %s", sudoers); - else if (!S_ISREG(statbuf.st_mode)) - log_error(NO_EXIT, "%s is not a regular file", sudoers); - else if ((statbuf.st_mode & 07577) != SUDOERS_MODE) - log_error(NO_EXIT, "%s is mode 0%o, should be 0%o", sudoers, - (unsigned int) (statbuf.st_mode & 07777), - (unsigned int) SUDOERS_MODE); - else if (statbuf.st_uid != SUDOERS_UID) - log_error(NO_EXIT, "%s is owned by uid %u, should be %u", sudoers, - (unsigned int) statbuf.st_uid, (unsigned int) SUDOERS_UID); - else if (statbuf.st_gid != SUDOERS_GID) - log_error(NO_EXIT, "%s is owned by gid %u, should be %u", sudoers, - (unsigned int) statbuf.st_gid, (unsigned int) SUDOERS_GID); - else if ((fp = fopen(sudoers, "r")) == NULL) - log_error(USE_ERRNO|NO_EXIT, "can't open %s", sudoers); - else { - /* - * Make sure we can actually read sudoers so we can present the - * user with a reasonable error message (unlike the lexer). - */ - if (statbuf.st_size != 0 && fgetc(fp) == EOF) { - log_error(USE_ERRNO|NO_EXIT, "can't read %s", sudoers); - fclose(fp); - fp = NULL; - } - } - - if (fp != NULL) { - rewind(fp); - (void) fcntl(fileno(fp), F_SETFD, 1); - } - - set_perms(PERM_ROOT); /* change back to root */ - return fp; -} - -/* - * Close all open files (except std*) and turn off core dumps. - * Also sets the set_perms() pointer to the correct function. - */ -static void -initial_setup() -{ - int miss[3], devnull = -1; - sigset_t mask; -#if defined(__linux__) || (defined(RLIMIT_CORE) && !defined(SUDO_DEVEL)) - struct rlimit rl; -#endif - - /* Reset signal mask. */ - (void) sigemptyset(&mask); - (void) sigprocmask(SIG_SETMASK, &mask, NULL); - -#if defined(__linux__) - /* - * Unlimit the number of processes since Linux's setuid() will - * apply resource limits when changing uid and return EAGAIN if - * nproc would be violated by the uid switch. - */ - (void) getrlimit(RLIMIT_NPROC, &nproclimit); - rl.rlim_cur = rl.rlim_max = RLIM_INFINITY; - if (setrlimit(RLIMIT_NPROC, &rl)) { - memcpy(&rl, &nproclimit, sizeof(struct rlimit)); - rl.rlim_cur = rl.rlim_max; - (void)setrlimit(RLIMIT_NPROC, &rl); - } -#endif /* __linux__ */ -#if defined(RLIMIT_CORE) && !defined(SUDO_DEVEL) - /* - * Turn off core dumps. - */ - (void) getrlimit(RLIMIT_CORE, &corelimit); - memcpy(&rl, &corelimit, sizeof(struct rlimit)); - rl.rlim_cur = 0; - (void) setrlimit(RLIMIT_CORE, &rl); -#endif /* RLIMIT_CORE && !SUDO_DEVEL */ - - /* - * stdin, stdout and stderr must be open; set them to /dev/null - * if they are closed and close all other fds. - */ - miss[STDIN_FILENO] = fcntl(STDIN_FILENO, F_GETFL, 0) == -1; - miss[STDOUT_FILENO] = fcntl(STDOUT_FILENO, F_GETFL, 0) == -1; - miss[STDERR_FILENO] = fcntl(STDERR_FILENO, F_GETFL, 0) == -1; - if (miss[STDIN_FILENO] || miss[STDOUT_FILENO] || miss[STDERR_FILENO]) { - if ((devnull = open(_PATH_DEVNULL, O_RDWR, 0644)) == -1) - error(1, "unable to open %s", _PATH_DEVNULL); - if (miss[STDIN_FILENO] && dup2(devnull, STDIN_FILENO) == -1) - error(1, "dup2"); - if (miss[STDOUT_FILENO] && dup2(devnull, STDOUT_FILENO) == -1) - error(1, "dup2"); - if (miss[STDERR_FILENO] && dup2(devnull, STDERR_FILENO) == -1) - error(1, "dup2"); - if (devnull > STDERR_FILENO) - close(devnull); - } -} - -#ifdef HAVE_LOGIN_CAP_H -static void -set_loginclass(pw) - struct passwd *pw; -{ - int errflags; - - /* - * Don't make it a fatal error if the user didn't specify the login - * class themselves. We do this because if login.conf gets - * corrupted we want the admin to be able to use sudo to fix it. - */ - if (login_class) - errflags = NO_MAIL|MSG_ONLY; - else - errflags = NO_MAIL|MSG_ONLY|NO_EXIT; - - if (login_class && strcmp(login_class, "-") != 0) { - 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; - if (!login_class || !*login_class) - login_class = - (pw->pw_uid == 0) ? LOGIN_DEFROOTCLASS : LOGIN_DEFCLASS; - } - - lc = login_getclass(login_class); - if (!lc || !lc->lc_class || strcmp(lc->lc_class, login_class) != 0) { - log_error(errflags, "unknown login class: %s", login_class); - if (!lc) - lc = login_getclass(NULL); /* needed for login_getstyle() later */ - } -} -#else -static void -set_loginclass(pw) - struct passwd *pw; -{ -} -#endif /* HAVE_LOGIN_CAP_H */ - -/* - * Look up the fully qualified domain name and set user_host and user_shost. - */ -void -set_fqdn() -{ -#ifdef HAVE_GETADDRINFO - struct addrinfo *res0, hint; -#else - struct hostent *hp; -#endif - char *p; - -#ifdef HAVE_GETADDRINFO - zero_bytes(&hint, sizeof(hint)); - hint.ai_family = PF_UNSPEC; - hint.ai_flags = AI_CANONNAME; - if (getaddrinfo(user_host, NULL, &hint, &res0) != 0) { -#else - if (!(hp = gethostbyname(user_host))) { -#endif - log_error(MSG_ONLY|NO_EXIT, - "unable to resolve host %s", user_host); - } else { - if (user_shost != user_host) - efree(user_shost); - efree(user_host); -#ifdef HAVE_GETADDRINFO - user_host = estrdup(res0->ai_canonname); - freeaddrinfo(res0); -#else - user_host = estrdup(hp->h_name); -#endif - } - if ((p = strchr(user_host, '.'))) { - *p = '\0'; - user_shost = estrdup(user_host); - *p = '.'; - } else { - user_shost = user_host; - } -} - -/* - * Get passwd entry for the user we are going to run commands as - * and store it in runas_pw. By default, commands run as "root". - */ -static void -set_runaspw(user) - char *user; -{ - if (runas_pw != NULL) - pw_delref(runas_pw); - if (*user == '#') { - if ((runas_pw = sudo_getpwuid(atoi(user + 1))) == NULL) - runas_pw = sudo_fakepwnam(user, runas_gr ? runas_gr->gr_gid : 0); - } else { - if ((runas_pw = sudo_getpwnam(user)) == NULL) { - audit_failure(NewArgv, "unknown user: %s", user); - log_error(NO_MAIL|MSG_ONLY, "unknown user: %s", user); - } - } -} - -/* - * Get group entry for the group we are going to run commands as - * and store it in runas_gr. - */ -static void -set_runasgr(group) - char *group; -{ - if (runas_gr != NULL) - gr_delref(runas_gr); - 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); - } -} - -/* - * Cleanup hook for error()/errorx() - */ -void -cleanup(gotsignal) - int gotsignal; -{ - struct sudo_nss *nss; - - if (!gotsignal) { - if (snl != NULL) { - tq_foreach_fwd(snl, nss) - nss->close(nss); - } -#ifdef USING_NONUNIX_GROUPS - sudo_nonunix_groupcheck_cleanup(); -#endif - sudo_endpwent(); - sudo_endgrent(); -#ifdef _PATH_SUDO_IO_LOGDIR - io_log_close(); -#endif - } - term_restore(STDIN_FILENO, 0); -#ifdef HAVE_SELINUX - selinux_restore_tty(); -#endif -} - -static void -show_version() -{ - (void) printf("Sudo version %s\n", PACKAGE_VERSION); - if (getuid() == 0) { - putchar('\n'); - (void) printf("Configure args: %s\n", CONFIGURE_ARGS); - (void) printf("Sudoers path: %s\n", _PATH_SUDOERS); -#ifdef HAVE_LDAP -# ifdef _PATH_NSSWITCH_CONF - (void) printf("nsswitch path: %s\n", _PATH_NSSWITCH_CONF); -# endif - (void) printf("ldap.conf path: %s\n", _PATH_LDAP_CONF); - (void) printf("ldap.secret path: %s\n", _PATH_LDAP_SECRET); -#endif - dump_auth_methods(); - dump_defaults(); - dump_interfaces(); - } - exit(0); -} - -#ifdef USE_ADMIN_FLAG -static void -create_admin_success_flag() -{ - struct stat statbuf; - char flagfile[PATH_MAX]; - int fd, n; - - /* Check whether the user is in the admin group. */ - if (!user_in_group(sudo_user.pw, "admin")) - return; - - /* Build path to flag file. */ - n = snprintf(flagfile, sizeof(flagfile), "%s/.sudo_as_admin_successful", - user_dir); - if (n <= 0 || n >= sizeof(flagfile)) - return; - - /* Create admin flag file if it doesn't already exist. */ - set_perms(PERM_USER); - if (stat(flagfile, &statbuf) == 0) { - set_perms(PERM_ROOT); - return; - } - - fd = open(flagfile, O_CREAT|O_WRONLY|O_EXCL, 0644); - close(fd); - set_perms(PERM_ROOT); -} -#else /* !USE_ADMIN_FLAG */ -static void -create_admin_success_flag() -{ - /* STUB */ -} -#endif /* USE_ADMIN_FLAG */ diff --git a/sudo.cat b/sudo.cat deleted file mode 100644 index 4cee486..0000000 --- a/sudo.cat +++ /dev/null @@ -1,660 +0,0 @@ - - - -SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) - - -NNAAMMEE - sudo, sudoedit - execute a command as another user - -SSYYNNOOPPSSIISS - ssuuddoo --hh | --KK | --kk | --LL | --VV - - ssuuddoo --vv [--AAkknnSS] [--aa _a_u_t_h___t_y_p_e] [--gg _g_r_o_u_p _n_a_m_e|_#_g_i_d] [--pp _p_r_o_m_p_t] - [--uu _u_s_e_r_n_a_m_e|_#_u_i_d] - - ssuuddoo --ll[[ll]] [--AAkknnSS] [--aa _a_u_t_h___t_y_p_e] [--gg _g_r_o_u_p _n_a_m_e|_#_g_i_d] [--pp _p_r_o_m_p_t] - [--UU _u_s_e_r _n_a_m_e] [--uu _u_s_e_r _n_a_m_e|_#_u_i_d] [_c_o_m_m_a_n_d] - - ssuuddoo [--AAbbEEHHnnPPSS] [--aa _a_u_t_h___t_y_p_e] [--CC _f_d] [--cc _c_l_a_s_s|_-] - [--gg _g_r_o_u_p _n_a_m_e|_#_g_i_d] [--pp _p_r_o_m_p_t] [--rr _r_o_l_e] [--tt _t_y_p_e] - [--uu _u_s_e_r _n_a_m_e|_#_u_i_d] [VVAARR=_v_a_l_u_e] [--ii | --ss] [_c_o_m_m_a_n_d] - - ssuuddooeeddiitt [--AAnnSS] [--aa _a_u_t_h___t_y_p_e] [--CC _f_d] [--cc _c_l_a_s_s|_-] - [--gg _g_r_o_u_p _n_a_m_e|_#_g_i_d] [--pp _p_r_o_m_p_t] [--uu _u_s_e_r _n_a_m_e|_#_u_i_d] file ... - -DDEESSCCRRIIPPTTIIOONN - ssuuddoo allows a permitted user to execute a _c_o_m_m_a_n_d as the superuser or - another user, as specified in the _s_u_d_o_e_r_s file. The real and effective - uid and gid are set to match those of the target user as specified in - the passwd file and the group vector is initialized based on the group - file (unless the --PP option was specified). If the invoking user is - root or if the target user is the same as the invoking user, no - password is required. Otherwise, ssuuddoo requires that users authenticate - themselves with a password by default (NOTE: in the default - configuration this is the user's password, not the root password). - Once a user has been authenticated, a time stamp is updated and the - user may then use sudo without a password for a short period of time (5 - minutes unless overridden in _s_u_d_o_e_r_s). - - When invoked as ssuuddooeeddiitt, the --ee option (described below), is implied. - - ssuuddoo determines who is an authorized user by consulting the file - _/_e_t_c_/_s_u_d_o_e_r_s. By running ssuuddoo with the --vv option, a user can update - the time stamp without running a _c_o_m_m_a_n_d. If a password is required, - ssuuddoo will exit if the user's password is not entered within a - configurable time limit. The default password prompt timeout is 5 - minutes. - - If a user who is not listed in the _s_u_d_o_e_r_s file tries to run a command - via ssuuddoo, mail is sent to the proper authorities, as defined at - configure time or in the _s_u_d_o_e_r_s file (defaults to root). Note that - the mail will not be sent if an unauthorized user tries to run sudo - with the --ll or --vv option. This allows users to determine for - themselves whether or not they are allowed to use ssuuddoo. - - If ssuuddoo is run by root and the SUDO_USER environment variable is set, - ssuuddoo will use this value to determine who the actual user is. This can - be used by a user to log commands through sudo even when a root shell - has been invoked. It also allows the --ee option to remain useful even - when being run via a sudo-run script or program. Note however, that - - - -1.7.6 April 9, 2011 1 - - - - - -SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) - - - the sudoers lookup is still done for root, not the user specified by - SUDO_USER. - - ssuuddoo can log both successful and unsuccessful attempts (as well as - errors) to _s_y_s_l_o_g(3), a log file, or both. By default ssuuddoo will log - via _s_y_s_l_o_g(3) but this is changeable at configure time or via the - _s_u_d_o_e_r_s file. - -OOPPTTIIOONNSS - ssuuddoo accepts the following command line options: - - -A Normally, if ssuuddoo requires a password, it will read it from - the current terminal. If the --AA (_a_s_k_p_a_s_s) option is - specified, a (possibly graphical) helper program is - executed to read the user's password and output the - password to the standard output. If the SUDO_ASKPASS - environment variable is set, it specifies the path to the - helper program. Otherwise, the value specified by the - _a_s_k_p_a_s_s option in _s_u_d_o_e_r_s(4) is used. - - -a _t_y_p_e The --aa (_a_u_t_h_e_n_t_i_c_a_t_i_o_n _t_y_p_e) option causes ssuuddoo to use the - specified authentication type when validating the user, as - allowed by _/_e_t_c_/_l_o_g_i_n_._c_o_n_f. The system administrator may - specify a list of sudo-specific authentication methods by - adding an "auth-sudo" entry in _/_e_t_c_/_l_o_g_i_n_._c_o_n_f. This - option is only available on systems that support BSD - authentication. - - -b The --bb (_b_a_c_k_g_r_o_u_n_d) option tells ssuuddoo to run the given - command in the background. Note that if you use the --bb - option you cannot use shell job control to manipulate the - process. - - -C _f_d Normally, ssuuddoo will close all open file descriptors other - than standard input, standard output and standard error. - The --CC (_c_l_o_s_e _f_r_o_m) 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 _c_l_o_s_e_f_r_o_m___o_v_e_r_r_i_d_e option in _s_u_d_o_e_r_s(4). - - -c _c_l_a_s_s The --cc (_c_l_a_s_s) option causes ssuuddoo to run the specified - command with resources limited by the specified login - class. The _c_l_a_s_s argument can be either a class name as - defined in _/_e_t_c_/_l_o_g_i_n_._c_o_n_f, or a single '-' character. - Specifying a _c_l_a_s_s of - indicates that the command should - be run restricted by the default login capabilities for the - user the command is run as. If the _c_l_a_s_s argument - specifies an existing user class, the command must be run - as root, or the ssuuddoo command must be run from a shell that - is already root. This option is only available on systems - with BSD login classes. - - -E The --EE (_p_r_e_s_e_r_v_e _e_n_v_i_r_o_n_m_e_n_t) option will override the - - - -1.7.6 April 9, 2011 2 - - - - - -SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) - - - _e_n_v___r_e_s_e_t option in _s_u_d_o_e_r_s(4)). It is only available when - either the matching command has the SETENV tag or the - _s_e_t_e_n_v option is set in _s_u_d_o_e_r_s(4). - - -e The --ee (_e_d_i_t) 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 _s_u_d_o_e_r_s file. If the user is authorized by - _s_u_d_o_e_r_s the following steps are taken: - - 1. Temporary copies are made of the files to be edited - with the owner set to the invoking user. - - 2. The editor specified by the SUDO_EDITOR, VISUAL or - EDITOR environment variables is run to edit the - temporary files. If none of SUDO_EDITOR, VISUAL or - EDITOR are set, the first program listed in the _e_d_i_t_o_r - _s_u_d_o_e_r_s variable is used. - - 3. If they have been modified, the temporary files are - copied back to their original location and the - temporary versions are removed. - - If the specified file does not exist, it will be created. - Note that unlike most commands run by ssuuddoo, the editor is - run with the invoking user's environment unmodified. If, - for some reason, ssuuddoo 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. - - -g _g_r_o_u_p Normally, ssuuddoo 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 --gg (_g_r_o_u_p) option causes - ssuuddoo to run the specified command with the primary group - set to _g_r_o_u_p. To specify a _g_i_d instead of a _g_r_o_u_p _n_a_m_e, - use _#_g_i_d. When running commands as a _g_i_d, many shells - require that the '#' be escaped with a backslash ('\'). If - no --uu option is specified, the command will be run as the - invoking user (not root). In either case, the primary - group will be set to _g_r_o_u_p. - - -H The --HH (_H_O_M_E) option sets the HOME environment variable to - the homedir of the target user (root by default) as - specified in _p_a_s_s_w_d(4). The default handling of the HOME - environment variable depends on _s_u_d_o_e_r_s(4) settings. By - default, ssuuddoo will set HOME if _e_n_v___r_e_s_e_t or _a_l_w_a_y_s___s_e_t___h_o_m_e - are set, or if _s_e_t___h_o_m_e is set and the --ss option is - specified on the command line. - - -h The --hh (_h_e_l_p) option causes ssuuddoo to print a short help - message to the standard output and exit. - - -i [command] - The --ii (_s_i_m_u_l_a_t_e _i_n_i_t_i_a_l _l_o_g_i_n) option runs the shell - - - -1.7.6 April 9, 2011 3 - - - - - -SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) - - - specified in the _p_a_s_s_w_d(4) entry of the target user as a - login shell. This means that login-specific resource files - such as .profile or .login will be read by the shell. If a - command is specified, it is passed to the shell for - execution. Otherwise, an interactive shell is executed. - ssuuddoo attempts to change to that user's home directory - before running the shell. It also initializes the - environment, leaving _D_I_S_P_L_A_Y and _T_E_R_M unchanged, setting - _H_O_M_E, _M_A_I_L, _S_H_E_L_L, _U_S_E_R, _L_O_G_N_A_M_E, and _P_A_T_H, as well as the - contents of _/_e_t_c_/_e_n_v_i_r_o_n_m_e_n_t on Linux and AIX systems. All - other environment variables are removed. - - -K The --KK (sure _k_i_l_l) option is like --kk except that it removes - the user's time stamp entirely and may not be used in - conjunction with a command or other option. This option - does not require a password. - - -k When used by itself, the --kk (_k_i_l_l) option to ssuuddoo - invalidates the user's time stamp by setting the time on it - to the Epoch. The next time ssuuddoo is run a password will be - required. This option does not require a password and was - added to allow a user to revoke ssuuddoo permissions from a - .logout file. - - When used in conjunction with a command or an option that - may require a password, the --kk option will cause ssuuddoo to - ignore the user's time stamp file. As a result, ssuuddoo will - prompt for a password (if one is required by _s_u_d_o_e_r_s) and - will not update the user's time stamp file. - - -L The --LL (_l_i_s_t defaults) option will list the parameters that - may be set in a _D_e_f_a_u_l_t_s line along with a short - description for each. This option will be removed from a - future version of ssuuddoo. - - -l[l] [_c_o_m_m_a_n_d] - If no _c_o_m_m_a_n_d is specified, the --ll (_l_i_s_t) option will list - the allowed (and forbidden) commands for the invoking user - (or the user specified by the --UU option) on the current - host. If a _c_o_m_m_a_n_d is specified and is permitted by - _s_u_d_o_e_r_s, the fully-qualified path to the command is - displayed along with any command line arguments. If - _c_o_m_m_a_n_d is specified but not allowed, ssuuddoo will exit with a - status value of 1. If the --ll option is specified with an ll - argument (i.e. --llll), or if --ll is specified multiple times, - a longer list format is used. - - -n The --nn (_n_o_n_-_i_n_t_e_r_a_c_t_i_v_e) option prevents ssuuddoo from - prompting the user for a password. If a password is - required for the command to run, ssuuddoo will display an error - messages and exit. - - -P The --PP (_p_r_e_s_e_r_v_e _g_r_o_u_p _v_e_c_t_o_r) option causes ssuuddoo to - preserve the invoking user's group vector unaltered. By - - - -1.7.6 April 9, 2011 4 - - - - - -SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) - - - default, ssuuddoo 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. - - -p _p_r_o_m_p_t The --pp (_p_r_o_m_p_t) 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 host name including the domain - name (on if the machine's host name is fully qualified - or the _f_q_d_n _s_u_d_o_e_r_s option is set) - - %h expanded to the local host name without the domain name - - %p expanded to the user whose password is being asked for - (respects the _r_o_o_t_p_w, _t_a_r_g_e_t_p_w and _r_u_n_a_s_p_w flags in - _s_u_d_o_e_r_s) - - %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 - - %% two consecutive % characters are collapsed into a - single % character - - The prompt specified by the --pp option will override the - system password prompt on systems that support PAM unless - the _p_a_s_s_p_r_o_m_p_t___o_v_e_r_r_i_d_e flag is disabled in _s_u_d_o_e_r_s. - - -r _r_o_l_e The --rr (_r_o_l_e) option causes the new (SELinux) security - context to have the role specified by _r_o_l_e. - - -S The --SS (_s_t_d_i_n) option causes ssuuddoo to read the password from - the standard input instead of the terminal device. The - password must be followed by a newline character. - - -s [command] - The --ss (_s_h_e_l_l) option runs the shell specified by the _S_H_E_L_L - environment variable if it is set or the shell as specified - in _p_a_s_s_w_d(4). If a command is specified, it is passed to - the shell for execution. Otherwise, an interactive shell - is executed. - - -t _t_y_p_e The --tt (_t_y_p_e) option causes the new (SELinux) security - context to have the type specified by _t_y_p_e. If no type is - specified, the default type is derived from the specified - role. - - -U _u_s_e_r The --UU (_o_t_h_e_r _u_s_e_r) option is used in conjunction with the - --ll option to specify the user whose privileges should be - listed. Only root or a user with ssuuddoo ALL on the current - host may use this option. - - - - -1.7.6 April 9, 2011 5 - - - - - -SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) - - - -u _u_s_e_r The --uu (_u_s_e_r) option causes ssuuddoo to run the specified - command as a user other than _r_o_o_t. To specify a _u_i_d - instead of a _u_s_e_r _n_a_m_e, use _#_u_i_d. When running commands as - a _u_i_d, many shells require that the '#' be escaped with a - backslash ('\'). Note that if the _t_a_r_g_e_t_p_w Defaults option - is set (see _s_u_d_o_e_r_s(4)) it is not possible to run commands - with a uid not listed in the password database. - - -V The --VV (_v_e_r_s_i_o_n) option causes ssuuddoo to print the version - number and exit. If the invoking user is already root the - --VV option will print out a list of the defaults ssuuddoo was - compiled with as well as the machine's local network - addresses. - - -v If given the --vv (_v_a_l_i_d_a_t_e) option, ssuuddoo will update the - user's time stamp, prompting for the user's password if - necessary. This extends the ssuuddoo timeout for another 5 - minutes (or whatever the timeout is set to in _s_u_d_o_e_r_s) but - does not run a command. - - -- The ---- option indicates that ssuuddoo should stop processing - command line arguments. - - Environment variables to be set for the command may also be passed on - the command line in the form of VVAARR=_v_a_l_u_e, e.g. - LLDD__LLIIBBRRAARRYY__PPAATTHH=_/_u_s_r_/_l_o_c_a_l_/_p_k_g_/_l_i_b. Variables passed on the command - line are subject to the same restrictions as normal environment - variables with one important exception. If the _s_e_t_e_n_v option is set in - _s_u_d_o_e_r_s, 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 _s_u_d_o_e_r_s(4) for more information. - -RREETTUURRNN VVAALLUUEESS - Upon successful execution of a program, the exit status from ssuuddoo will - simply be the exit status of the program that was executed. - - Otherwise, ssuuddoo quits with an exit value of 1 if there is a - configuration/permission problem or if ssuuddoo cannot execute the given - command. In the latter case the error string is printed to stderr. If - ssuuddoo cannot _s_t_a_t(2) one or more entries in the user's PATH an error is - printed on stderr. (If the directory does not exist or if it is not - really a directory, the entry is ignored and no error is printed.) - This should not happen under normal circumstances. The most common - reason for _s_t_a_t(2) to return "permission denied" is if you are running - an automounter and one of the directories in your PATH is on a machine - that is currently unreachable. - -SSEECCUURRIITTYY NNOOTTEESS - ssuuddoo tries to be safe when executing external commands. - - There are two distinct ways to deal with environment variables. By - default, the _e_n_v___r_e_s_e_t _s_u_d_o_e_r_s option is enabled. This causes commands - to be executed with a minimal environment containing TERM, PATH, HOME, - SHELL, LOGNAME, USER and USERNAME in addition to variables from the - - - -1.7.6 April 9, 2011 6 - - - - - -SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) - - - invoking process permitted by the _e_n_v___c_h_e_c_k and _e_n_v___k_e_e_p _s_u_d_o_e_r_s - options. There is effectively a whitelist for environment variables. - - If, however, the _e_n_v___r_e_s_e_t option is disabled in _s_u_d_o_e_r_s, any variables - not explicitly denied by the _e_n_v___c_h_e_c_k and _e_n_v___d_e_l_e_t_e options are - inherited from the invoking process. In this case, _e_n_v___c_h_e_c_k and - _e_n_v___d_e_l_e_t_e behave like a blacklist. Since it is not possible to - blacklist all potentially dangerous environment variables, use of the - default _e_n_v___r_e_s_e_t behavior is encouraged. - - In all cases, environment variables with a value beginning with () are - removed as they could be interpreted as bbaasshh functions. The list of - environment variables that ssuuddoo allows or denies is contained in the - output of sudo -V when run as root. - - Note that the dynamic linker on most operating systems will remove - variables that can control dynamic linking from the environment of - setuid executables, including ssuuddoo. Depending on the operating system - this may include _RLD*, DYLD_*, LD_*, LDR_*, LIBPATH, SHLIB_PATH, and - others. These type of variables are removed from the environment - before ssuuddoo even begins execution and, as such, it is not possible for - ssuuddoo to preserve them. - - To prevent command spoofing, ssuuddoo checks "." and "" (both denoting - current directory) last when searching for a command in the user's PATH - (if one or both are in the PATH). Note, however, that the actual PATH - environment variable is _n_o_t modified and is passed unchanged to the - program that ssuuddoo executes. - - ssuuddoo will check the ownership of its time stamp directory - (_/_v_a_r_/_a_d_m_/_s_u_d_o by default) and ignore the directory's contents if it is - not owned by root or if it is writable by a user other than root. On - systems that allow non-root users to give away files via _c_h_o_w_n(2), if - the time stamp directory is located in a directory writable by anyone - (e.g., _/_t_m_p), it is possible for a user to create the time stamp - directory before ssuuddoo is run. However, because ssuuddoo checks the - ownership and mode of the directory and its contents, the only damage - that can be done is to "hide" files by putting them in the time stamp - dir. This is unlikely to happen since once the time stamp dir is owned - by root and inaccessible by any other user, the user placing files - there would be unable to get them back out. To get around this issue - you can use a directory that is not world-writable for the time stamps - (_/_v_a_r_/_a_d_m_/_s_u_d_o for instance) or create _/_v_a_r_/_a_d_m_/_s_u_d_o with the - appropriate owner (root) and permissions (0700) in the system startup - files. - - ssuuddoo will not honor time stamps set far in the future. Timestamps with - a date greater than current_time + 2 * TIMEOUT will be ignored and sudo - will log and complain. This is done to keep a user from creating - his/her own time stamp with a bogus date on systems that allow users to - give away files. - - On systems where the boot time is available, ssuuddoo will also not honor - time stamps from before the machine booted. - - - -1.7.6 April 9, 2011 7 - - - - - -SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) - - - Since time stamp files live in the file system, they can outlive a - user's login session. As a result, a user may be able to login, run a - command with ssuuddoo after authenticating, logout, login again, and run - ssuuddoo without authenticating so long as the time stamp file's - modification time is within 5 minutes (or whatever the timeout is set - to in _s_u_d_o_e_r_s). When the _t_t_y___t_i_c_k_e_t_s option is enabled in _s_u_d_o_e_r_s, the - time stamp has per-tty granularity but still may outlive the user's - session. On Linux systems where the devpts filesystem is used, Solaris - systems with the devices filesystem, as well as other systems that - utilize a devfs filesystem that monotonically increase the inode number - of devices as they are created (such as Mac OS X), ssuuddoo is able to - determine when a tty-based time stamp file is stale and will ignore it. - Administrators should not rely on this feature as it is not universally - available. - - Please note that ssuuddoo 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 will _n_o_t be logged, nor will ssuuddoo's access - control affect them. The same is true for commands that offer shell - escapes (including most editors). Because of this, care must be taken - when giving users access to commands via ssuuddoo to verify that the - command does not inadvertently give the user an effective root shell. - For more information, please see the PREVENTING SHELL ESCAPES section - in _s_u_d_o_e_r_s(4). - -EENNVVIIRROONNMMEENNTT - ssuuddoo utilizes the following environment variables: - - EDITOR Default editor to use in --ee (sudoedit) mode if neither - SUDO_EDITOR nor VISUAL is set - - MAIL In --ii mode or when _e_n_v___r_e_s_e_t is enabled in _s_u_d_o_e_r_s, set - to the mail spool of the target user - - HOME Set to the home directory of the target user if --ii or - --HH are specified, _e_n_v___r_e_s_e_t or _a_l_w_a_y_s___s_e_t___h_o_m_e are set - in _s_u_d_o_e_r_s, or when the --ss option is specified and - _s_e_t___h_o_m_e is set in _s_u_d_o_e_r_s - - PATH Set to a sane value if the _s_e_c_u_r_e___p_a_t_h sudoers option - is set. - - SHELL Used to determine shell to run with -s option - - SUDO_ASKPASS Specifies the path to a helper program used to read the - password if no terminal is available or if the -A - option is specified. - - SUDO_COMMAND Set to the command run by sudo - - SUDO_EDITOR Default editor to use in --ee (sudoedit) mode - - SUDO_GID Set to the group ID of the user who invoked sudo - - - - -1.7.6 April 9, 2011 8 - - - - - -SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) - - - SUDO_PROMPT Used as the default password prompt - - SUDO_PS1 If set, PS1 will be set to its value for the program - being run - - SUDO_UID Set to the user ID of the user who invoked sudo - - SUDO_USER Set to the login of the user who invoked sudo - - USER Set to the target user (root unless the --uu option is - specified) - - VISUAL Default editor to use in --ee (sudoedit) mode if - SUDO_EDITOR is not set - -FFIILLEESS - _/_e_t_c_/_s_u_d_o_e_r_s List of who can run what - - _/_v_a_r_/_a_d_m_/_s_u_d_o Directory containing time stamps - - _/_e_t_c_/_e_n_v_i_r_o_n_m_e_n_t Initial environment for --ii mode on Linux and - AIX - -EEXXAAMMPPLLEESS - Note: the following examples assume suitable _s_u_d_o_e_r_s(4) entries. - - To get a file listing of an unreadable directory: - - $ sudo ls /usr/local/protected - - To list the home directory of user yaz on a machine where the file - system holding ~yaz is not exported as root: - - $ sudo -u yaz ls ~yaz - - To edit the _i_n_d_e_x_._h_t_m_l file as user www: - - $ sudo -u www vi ~www/htdocs/index.html - - To view system logs only accessible to root and users in the adm group: - - $ sudo -g adm view /var/log/syslog - - To run an editor as jim with a different primary group: - - $ sudo -u jim -g audio vi ~jim/sound.txt - - To shutdown a machine: - - $ sudo shutdown -r +15 "quick reboot" - - To make a usage listing of the directories in the /home partition. - Note that this runs the commands in a sub-shell to make the cd and file - redirection work. - - - -1.7.6 April 9, 2011 9 - - - - - -SUDO(1m) MAINTENANCE COMMANDS SUDO(1m) - - - $ sudo sh -c "cd /home ; du -s * | sort -rn > USAGE" - -SSEEEE AALLSSOO - _g_r_e_p(1), _s_u(1), _s_t_a_t(2), _l_o_g_i_n___c_a_p(3), _p_a_s_s_w_d(4), _s_u_d_o_e_r_s(5), - _v_i_s_u_d_o(1m) - -AAUUTTHHOORRSS - Many people have worked on ssuuddoo over the years; this version consists - of code written primarily by: - - Todd C. Miller - - See the HISTORY file in the ssuuddoo distribution or visit - http://www.sudo.ws/sudo/history.html for a short history of ssuuddoo. - -CCAAVVEEAATTSS - There is no easy way to prevent a user from gaining a root shell if - that user is allowed to run arbitrary commands via ssuuddoo. Also, many - programs (such as editors) allow the user to run commands via shell - escapes, thus avoiding ssuuddoo's checks. However, on most systems it is - possible to prevent shell escapes with ssuuddoo's _n_o_e_x_e_c functionality. - See the _s_u_d_o_e_r_s(4) manual for details. - - It is not meaningful to run the cd command directly via sudo, e.g., - - $ sudo cd /usr/local/protected - - since when the command exits the parent process (your shell) will still - be the same. Please see the EXAMPLES section for more information. - - If users have sudo ALL there is nothing to prevent them from creating - their own program that gives them a root shell regardless of any '!' - elements in the user specification. - - Running shell scripts via ssuuddoo can expose the same kernel bugs that - make setuid shell scripts unsafe on some operating systems (if your OS - has a /dev/fd/ directory, setuid shell scripts are generally safe). - -BBUUGGSS - If you feel you have found a bug in ssuuddoo, please submit a bug report at - http://www.sudo.ws/sudo/bugs/ - -SSUUPPPPOORRTT - Limited free support is available via the sudo-users mailing list, see - http://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or search - the archives. - -DDIISSCCLLAAIIMMEERR - ssuuddoo is provided ``AS IS'' and any express or implied warranties, - including, but not limited to, the implied warranties of - merchantability and fitness for a particular purpose are disclaimed. - See the LICENSE file distributed with ssuuddoo or - http://www.sudo.ws/sudo/license.html for complete details. - - - - -1.7.6 April 9, 2011 10 - - diff --git a/sudo.h b/sudo.h deleted file mode 100644 index a59677b..0000000 --- a/sudo.h +++ /dev/null @@ -1,372 +0,0 @@ -/* - * Copyright (c) 1993-1996, 1998-2005, 2007-2010 - * Todd C. Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * Sponsored in part by the Defense Advanced Research Projects - * Agency (DARPA) and Air Force Research Laboratory, Air Force - * Materiel Command, USAF, under agreement number F39502-99-1-0512. - */ - -#ifndef _SUDO_SUDO_H -#define _SUDO_SUDO_H - -#include -#include -#include "missing.h" -#include "alloc.h" -#include "defaults.h" -#include "error.h" -#include "list.h" -#include "logging.h" -#include "missing.h" -#include "sudo_nss.h" - -#ifdef HAVE_MBR_CHECK_MEMBERSHIP -# include -#endif - -/* - * Info pertaining to the invoking user. - */ -struct sudo_user { - struct passwd *pw; - struct passwd *_runas_pw; - struct group *_runas_gr; - struct stat *cmnd_stat; - char *path; - char *shell; - char *tty; - char *ttypath; - char *host; - char *shost; - char *prompt; - char *cmnd; - char *cmnd_args; - char *cmnd_base; - char *cmnd_safe; - char *class_name; - char *krb5_ccname; - char *display; - char *askpass; - int ngroups; - GETGROUPS_T *groups; - struct list_member *env_vars; -#ifdef HAVE_SELINUX - char *role; - char *type; -#endif - char cwd[PATH_MAX]; - char sessid[7]; -#ifdef HAVE_MBR_CHECK_MEMBERSHIP - uuid_t uuid; -#endif -}; - -/* Status passed between parent and child via socketpair */ -struct command_status { -#define CMD_INVALID 0 -#define CMD_ERRNO 1 -#define CMD_WSTATUS 2 -#define CMD_SIGNO 3 - int type; - int val; -}; - -/* - * Return values for sudoers_lookup(), also used as arguments for log_auth() - * Note: cannot use '0' as a value here. - */ -/* XXX - VALIDATE_SUCCESS and VALIDATE_FAILURE instead? */ -#define VALIDATE_ERROR 0x001 -#define VALIDATE_OK 0x002 -#define VALIDATE_NOT_OK 0x004 -#define FLAG_CHECK_USER 0x010 -#define FLAG_NO_USER 0x020 -#define FLAG_NO_HOST 0x040 -#define FLAG_NO_CHECK 0x080 - -/* - * Pseudo-boolean values - */ -#undef TRUE -#define TRUE 1 -#undef FALSE -#define FALSE 0 - -/* - * find_path()/load_cmnd() return values - */ -#define FOUND 1 -#define NOT_FOUND 0 -#define NOT_FOUND_DOT -1 - -/* - * Various modes sudo can be in (based on arguments) in hex - */ -#define MODE_RUN 0x00000001 -#define MODE_EDIT 0x00000002 -#define MODE_VALIDATE 0x00000004 -#define MODE_INVALIDATE 0x00000008 -#define MODE_KILL 0x00000010 -#define MODE_VERSION 0x00000020 -#define MODE_HELP 0x00000040 -#define MODE_LIST 0x00000080 -#define MODE_CHECK 0x00000100 -#define MODE_LISTDEFS 0x00000200 -#define MODE_MASK 0x0000ffff - -/* Mode flags */ -#define MODE_BACKGROUND 0x00010000 -#define MODE_SHELL 0x00020000 -#define MODE_LOGIN_SHELL 0x00040000 -#define MODE_IMPLIED_SHELL 0x00080000 -#define MODE_RESET_HOME 0x00100000 -#define MODE_PRESERVE_GROUPS 0x00200000 -#define MODE_PRESERVE_ENV 0x00400000 -#define MODE_NONINTERACTIVE 0x00800000 - -/* - * Used with set_perms() - */ -#define PERM_ROOT 0x00 -#define PERM_USER 0x01 -#define PERM_FULL_USER 0x02 -#define PERM_SUDOERS 0x03 -#define PERM_RUNAS 0x04 -#define PERM_FULL_RUNAS 0x05 -#define PERM_TIMESTAMP 0x06 -#define PERM_NOEXIT 0x10 /* flag */ -#define PERM_MASK 0xf0 - -/* - * Shortcuts for sudo_user contents. - */ -#define user_name (sudo_user.pw->pw_name) -#define user_passwd (sudo_user.pw->pw_passwd) -#define user_uid (sudo_user.pw->pw_uid) -#define user_uuid (sudo_user.uuid) -#define user_gid (sudo_user.pw->pw_gid) -#define user_dir (sudo_user.pw->pw_dir) -#define user_shell (sudo_user.shell) -#define user_ngroups (sudo_user.ngroups) -#define user_groups (sudo_user.groups) -#define user_tty (sudo_user.tty) -#define user_ttypath (sudo_user.ttypath) -#define user_cwd (sudo_user.cwd) -#define user_cmnd (sudo_user.cmnd) -#define user_args (sudo_user.cmnd_args) -#define user_base (sudo_user.cmnd_base) -#define user_stat (sudo_user.cmnd_stat) -#define user_path (sudo_user.path) -#define user_prompt (sudo_user.prompt) -#define user_host (sudo_user.host) -#define user_shost (sudo_user.shost) -#define user_ccname (sudo_user.krb5_ccname) -#define user_display (sudo_user.display) -#define user_askpass (sudo_user.askpass) -#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) -#define user_role (sudo_user.role) -#define user_type (sudo_user.type) - -/* - * We used to use the system definition of PASS_MAX or _PASSWD_LEN, - * but that caused problems with various alternate authentication - * methods. So, we just define our own and assume that it is >= the - * system max. - */ -#define SUDO_PASS_MAX 256 - -/* - * Flags for lock_file() - */ -#define SUDO_LOCK 1 /* lock a file */ -#define SUDO_TLOCK 2 /* test & lock a file (non-blocking) */ -#define SUDO_UNLOCK 4 /* unlock a file */ - -/* - * Flags for tgetpass() - */ -#define TGP_ECHO 0x01 /* leave echo on when reading passwd */ -#define TGP_STDIN 0x02 /* read from stdin, not /dev/tty */ -#define TGP_ASKPASS 0x04 /* read from askpass helper program */ - -struct lbuf; -struct passwd; -struct stat; -struct timeval; - -/* aix.c */ -void aix_prep_user __P((char *, char *)); -void aix_setauthdb __P((char *user)); -void aix_restoreauthdb __P((void)); - -/* boottime.c */ -int get_boottime __P((struct timeval *)); - -/* check.c */ -int user_is_exempt __P((void)); -void check_user __P((int, int)); -void remove_timestamp __P((int)); - -/* env.c */ -char **env_get __P((void)); -void env_init __P((int lazy)); -void init_envtables __P((void)); -void insert_env_vars __P((struct list_member *)); -void read_env_file __P((const char *, int)); -void rebuild_env __P((int)); -void validate_env_vars __P((struct list_member *)); - -/* exec.c */ -int sudo_execve __P((const char *path, char *argv[], char *envp[], uid_t uid, - struct command_status *cstat, int dowait, int bgmode)); -void save_signals __P((void)); -void restore_signals __P((void)); - -/* fileops.c */ -char *sudo_parseln __P((FILE *)); -int lock_file __P((int, int)); -int touch __P((int, char *, struct timeval *)); - -/* find_path.c */ -int find_path __P((char *, char **, struct stat *, char *, int)); - -/* getspwuid.c */ -char *sudo_getepw __P((const struct passwd *)); - -/* gettime.c */ -int gettime __P((struct timeval *)); - -/* goodpath.c */ -char *sudo_goodpath __P((const char *, struct stat *)); - -/* gram.y */ -int yyparse __P((void)); - -/* iolog.c */ -int io_log_open __P((void)); -int log_stderr __P((const char *buf, unsigned int len)); -int log_stdin __P((const char *buf, unsigned int len)); -int log_stdout __P((const char *buf, unsigned int len)); -int log_ttyin __P((const char *buf, unsigned int len)); -int log_ttyout __P((const char *buf, unsigned int len)); -void io_log_close __P((void)); -void io_nextid __P((void)); - -/* pam.c */ -int pam_begin_session __P((struct passwd *)); -int pam_end_session __P((void)); - -/* parse.c */ -int sudo_file_open __P((struct sudo_nss *)); -int sudo_file_close __P((struct sudo_nss *)); -int sudo_file_setdefs __P((struct sudo_nss *)); -int sudo_file_lookup __P((struct sudo_nss *, int, int)); -int sudo_file_parse __P((struct sudo_nss *)); -int sudo_file_display_cmnd __P((struct sudo_nss *, struct passwd *)); -int sudo_file_display_defaults __P((struct sudo_nss *, struct passwd *, struct lbuf *)); -int sudo_file_display_bound_defaults __P((struct sudo_nss *, struct passwd *, struct lbuf *)); -int sudo_file_display_privs __P((struct sudo_nss *, struct passwd *, struct lbuf *)); - -/* parse_args.c */ -int parse_args __P((int, char **)); - -/* get_pty.c */ -int get_pty __P((int *master, int *slave, char *name, size_t namesz, uid_t uid)); - -/* pwutil.c */ -int user_in_group __P((struct passwd *, const char *)); -struct group *sudo_fakegrnam __P((const char *)); -struct group *sudo_getgrgid __P((gid_t)); -struct group *sudo_getgrnam __P((const char *)); -struct passwd *sudo_fakepwnam __P((const char *, gid_t)); -struct passwd *sudo_getpwnam __P((const char *)); -struct passwd *sudo_getpwuid __P((uid_t)); -void sudo_endgrent __P((void)); -void sudo_endpwent __P((void)); -void sudo_endspent __P((void)); -void sudo_setgrent __P((void)); -void sudo_setpwent __P((void)); -void sudo_setspent __P((void)); -void gr_addref __P((struct group *)); -void gr_delref __P((struct group *)); -void pw_addref __P((struct passwd *)); -void pw_delref __P((struct passwd *)); - -/* selinux.c */ -int selinux_restore_tty __P((void)); -int selinux_setup __P((const char *role, const char *type, const char *ttyn, - int ttyfd)); -void selinux_execve __P((const char *path, char *argv[], char *envp[])); - -/* set_perms.c */ -int set_perms __P((int)); - -/* sudo.c */ -FILE *open_sudoers __P((const char *, int, int *)); -int exec_setup __P((int, const char *, int)); -RETSIGTYPE cleanup __P((int)); -void set_fqdn __P((void)); - -/* sudo_auth.c */ -void verify_user __P((struct passwd *, char *)); -void pass_warn __P((FILE *)); -void dump_auth_methods __P((void)); - -/* sudo_nss.c */ -void display_privs __P((struct sudo_nss_list *, struct passwd *)); -int display_cmnd __P((struct sudo_nss_list *, struct passwd *)); - -/* term.c */ -int term_cbreak __P((int)); -int term_copy __P((int, int)); -int term_noecho __P((int)); -int term_raw __P((int, int)); -int term_restore __P((int, int)); - -/* tgetpass.c */ -char *tgetpass __P((const char *, int, int)); -int tty_present __P((void)); - -/* timestr.c */ -char *get_timestr __P((time_t, int)); - -/* toke.l */ -#define YY_DECL int yylex __P((void)) -YY_DECL; - -/* zero_bytes.c */ -void zero_bytes __P((volatile void *, size_t)); - -/* Only provide extern declarations outside of sudo.c. */ -#ifndef _SUDO_MAIN -extern struct sudo_user sudo_user; -extern struct passwd *list_pw; - -extern int tgetpass_flags; -extern int long_list; -extern int sudo_mode; -extern uid_t timestamp_uid; -/* XXX - conflicts with the one in visudo */ -int run_command __P((const char *path, char *argv[], char *envp[], uid_t uid, int dowait)); -#endif -#ifndef errno -extern int errno; -#endif - -#endif /* _SUDO_SUDO_H */ diff --git a/sudo.pod b/sudo.pod deleted file mode 100644 index 555274c..0000000 --- a/sudo.pod +++ /dev/null @@ -1,702 +0,0 @@ -Copyright (c) 1994-1996, 1998-2005, 2007-2010 - Todd C. Miller - -Permission to use, copy, modify, and distribute this software for any -purpose with or without fee is hereby granted, provided that the above -copyright notice and this permission notice appear in all copies. - -THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES -WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR -ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES -WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN -ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF -OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. -ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -Sponsored in part by the Defense Advanced Research Projects -Agency (DARPA) and Air Force Research Laboratory, Air Force -Materiel Command, USAF, under agreement number F39502-99-1-0512. - -=pod - -=head1 NAME - -sudo, sudoedit - execute a command as another user - -=head1 SYNOPSIS - -B B<-h> | B<-K> | B<-k> | B<-L> | B<-V> - -B B<-v> [B<-AknS>] -S<[B<-a> I]> -S<[B<-g> I|I<#gid>]> S<[B<-p> I]> -S<[B<-u> I|I<#uid>]> - -B B<-l[l]> [B<-AknS>] -S<[B<-a> I]> -S<[B<-g> I|I<#gid>]> S<[B<-p> I]> -S<[B<-U> I]> S<[B<-u> I|I<#uid>]> [I] - -B [B<-AbEHnPS>] -S<[B<-a> I]> -S<[B<-C> I]> -S<[B<-c> I|I<->]> -S<[B<-g> I|I<#gid>]> S<[B<-p> I]> -S<[B<-r> I]> S<[B<-t> I]> -S<[B<-u> I|I<#uid>]> -S<[B=I]> S<[B<-i> | B<-s>]> [I] - -B [B<-AnS>] -S<[B<-a> I]> -S<[B<-C> I]> -S<[B<-c> I|I<->]> -S<[B<-g> I|I<#gid>]> S<[B<-p> I]> -S<[B<-u> I|I<#uid>]> file ... - -=head1 DESCRIPTION - -B allows a permitted user to execute a I as the -superuser or another user, as specified in the I file. -The real and effective uid and gid are set to match those of the -target user as specified in the passwd file and the group vector -is initialized based on the group file (unless the B<-P> option was -specified). If the invoking user is root or if the target user is -the same as the invoking user, no password is required. Otherwise, -B requires that users authenticate themselves with a password -by default (NOTE: in the default configuration this is the user's -password, not the root password). Once a user has been authenticated, -a time stamp is updated and the user may then use sudo without a -password for a short period of time (C<@timeout@> minutes unless -overridden in I). - -When invoked as B, the B<-e> option (described below), -is implied. - -B determines who is an authorized user by consulting the file -F<@sysconfdir@/sudoers>. By running B with the B<-v> option, -a user can update the time stamp without running a I. If -a password is required, B will exit if the user's password -is not entered within a configurable time limit. The default -password prompt timeout is C<@password_timeout@> minutes. - -If a user who is not listed in the I file tries to run a -command via B, mail is sent to the proper authorities, as -defined at configure time or in the I file (defaults to -C<@mailto@>). Note that the mail will not be sent if an unauthorized -user tries to run sudo with the B<-l> or B<-v> option. This allows -users to determine for themselves whether or not they are allowed -to use B. - -If B is run by root and the C environment variable -is set, B will use this value to determine who the actual -user is. This can be used by a user to log commands through sudo -even when a root shell has been invoked. It also allows the B<-e> -option 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 C. - -B can log both successful and unsuccessful attempts (as well -as errors) to syslog(3), a log file, or both. By default B -will log via syslog(3) but this is changeable at configure time -or via the I file. - -=head1 OPTIONS - -B accepts the following command line options: - -=over 12 - -=item -A - -Normally, if B requires a password, it will read it from the -current terminal. If the B<-A> (I) option is specified, -a (possibly graphical) helper program is executed to read the -user's password and output the password to the standard output. If -the C environment variable is set, it specifies the -path to the helper program. Otherwise, the value specified by the -I option in L is used. - -=item -a I - -The B<-a> (I) option causes B to use the -specified authentication type when validating the user, as allowed -by F. The system administrator may specify a list -of sudo-specific authentication methods by adding an "auth-sudo" -entry in F. This option is only available on systems -that support BSD authentication. - -=item -b - -The B<-b> (I) option tells B to run the given -command in the background. Note that if you use the B<-b> -option you cannot use shell job control to manipulate the process. - -=item -C I - -Normally, B will close all open file descriptors other than -standard input, standard output and standard error. The B<-C> -(I) 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 I option in -L. - -=item -c I - -The B<-c> (I) option causes B to run the specified command -with resources limited by the specified login class. The I -argument can be either a class name as defined in F, -or a single '-' character. Specifying a I of C<-> indicates -that the command should be run restricted by the default login -capabilities for the user the command is run as. If the I -argument specifies an existing user class, the command must be run -as root, or the B command must be run from a shell that is already -root. This option is only available on systems with BSD login classes. - -=item -E - -The B<-E> (I I) option will override the -I option in L). It is only -available when either the matching command has the C tag -or the I option is set in L. - -=item -e - -The B<-e> (I) 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 I file. If the user is authorized by I -the following steps are taken: - -=over 4 - -=item 1. - -Temporary copies are made of the files to be edited with the owner -set to the invoking user. - -=item 2. - -The editor specified by the C, C or C -environment variables is run to edit the temporary files. If none -of C, C or C are set, the first program -listed in the I I variable is used. - -=item 3. - -If they have been modified, the temporary files are copied back to -their original location and the temporary versions are removed. - -=back - -If the specified file does not exist, it will be created. Note -that unlike most commands run by B, the editor is run with -the invoking user's environment unmodified. If, for some reason, -B 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. - -=item -g I - -Normally, B 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) option causes B to run -the specified command with the primary group set to I. To -specify a I instead of a I, use I<#gid>. When -running commands as a I, 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. - -=item -H - -The B<-H> (I) option sets the C environment variable -to the homedir of the target user (root by default) as specified -in passwd(5). The default handling of the C environment -variable depends on L settings. By default, B -will set C if I or I are set, or -if I is set and the B<-s> option is specified on the -command line. - -=item -h - -The B<-h> (I) option causes B to print a short help message -to the standard output and exit. - -=item -i [command] - -The B<-i> (I) option runs the shell specified -in the L entry of the target user as a login shell. This -means that login-specific resource files such as C<.profile> or -C<.login> will be read by the shell. If a command is specified, -it is passed to the shell for execution. Otherwise, an interactive -shell is executed. B attempts to change to that user's home -directory before running the shell. It also initializes the -environment, leaving I and I unchanged, setting -I, I, I, I, I, and I, as well as -the contents of F on Linux and AIX systems. -All other environment variables are removed. - -=item -K - -The B<-K> (sure I) option is like B<-k> except that it removes -the user's time stamp entirely and may not be used in conjunction -with a command or other option. This option does not require a -password. - -=item -k - -When used by itself, the B<-k> (I) option to B invalidates -the user's time stamp by setting the time on it to the Epoch. The -next time B is run a password will be required. This option -does not require a password and was added to allow a user to revoke -B permissions from a .logout file. - -When used in conjunction with a command or an option that may require -a password, the B<-k> option will cause B to ignore the user's -time stamp file. As a result, B will prompt for a password -(if one is required by I) and will not update the user's -time stamp file. - -=item -L - -The B<-L> (I defaults) option will list the parameters that -may be set in a I line along with a short description for -each. This option will be removed from a future version of B. - -=item -l[l] [I] - -If no I is specified, the B<-l> (I) option will list -the allowed (and forbidden) commands for the invoking user (or the -user specified by the B<-U> option) on the current host. If a -I is specified and is permitted by I, the -fully-qualified path to the command is displayed along with any -command line arguments. If I is specified but not allowed, -B will exit with a status value of 1. If the B<-l> option is -specified with an B argument (i.e. B<-ll>), or if B<-l> -is specified multiple times, a longer list format is used. - -=item -n - -The B<-n> (I) option prevents B from prompting -the user for a password. If a password is required for the command -to run, B will display an error messages and exit. - -=item -P - -The B<-P> (I I) option causes B to -preserve the invoking user's group vector unaltered. By default, -B 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. - -=item -p I - -The B<-p> (I) option allows you to override the default -password prompt and use a custom one. The following percent (`C<%>') -escapes are supported: - -=over 4 - -=item C<%H> - -expanded to the local host name including the domain name -(on if the machine's host name is fully qualified or the I -I option is set) - -=item C<%h> - -expanded to the local host name without the domain name - -=item C<%p> - -expanded to the user whose password is being asked for (respects the -I, I and I flags in I) - -=item C<%U> - -expanded to the login name of the user the command will -be run as (defaults to root) - -=item C<%u> - -expanded to the invoking user's login name - -=item C<%%> - -two consecutive C<%> characters are collapsed into a single C<%> character - -=back - -The prompt specified by the B<-p> option will override the system -password prompt on systems that support PAM unless the -I flag is disabled in I. - -=item -r I - -The B<-r> (I) option causes the new (SELinux) security context to -have the role specified by I. - -=item -S - -The B<-S> (I) option causes B to read the password from -the standard input instead of the terminal device. The password must -be followed by a newline character. - -=item -s [command] - -The B<-s> (I) option runs the shell specified by the I -environment variable if it is set or the shell as specified in -L. If a command is specified, it is passed to the shell -for execution. Otherwise, an interactive shell is executed. - -=item -t I - -The B<-t> (I) option causes the new (SELinux) security context to -have the type specified by I. If no type is specified, the default -type is derived from the specified role. - -=item -U I - -The B<-U> (I) option is used in conjunction with the B<-l> -option to specify the user whose privileges should be listed. Only -root or a user with B C on the current host may use this -option. - -=item -u I - -The B<-u> (I) option causes B to run the specified -command as a user other than I. To specify a I instead -of a I, use I<#uid>. When running commands as a I, -many shells require that the '#' be escaped with a backslash ('\'). -Note that if the I Defaults option is set (see L) -it is not possible to run commands with a uid not listed in the -password database. - -=item -V - -The B<-V> (I) option causes B to print the version -number and exit. If the invoking user is already root the B<-V> -option will print out a list of the defaults B was compiled -with as well as the machine's local network addresses. - -=item -v - -If given the B<-v> (I) option, B will update the -user's time stamp, prompting for the user's password if necessary. -This extends the B timeout for another C<@timeout@> minutes -(or whatever the timeout is set to in I) but does not run -a command. - -=item -- - -The B<--> option indicates that B should stop processing command -line arguments. - -=back - -Environment variables to be set for the command may also be passed -on the command line in the form of B=I, e.g. -B=I. Variables passed on the -command line are subject to the same restrictions as normal environment -variables with one important exception. If the I option -is set in I, the command to be run has the C tag -set or the command matched is C, the user may set variables -that would overwise be forbidden. See L for more information. - -=head1 RETURN VALUES - -Upon successful execution of a program, the exit status from B -will simply be the exit status of the program that was executed. - -Otherwise, B quits with an exit value of 1 if there is a -configuration/permission problem or if B cannot execute the -given command. In the latter case the error string is printed to -stderr. If B cannot L one or more entries in the user's -C an error is printed on stderr. (If the directory does not -exist or if it is not really a directory, the entry is ignored and -no error is printed.) This should not happen under normal -circumstances. The most common reason for L to return -"permission denied" is if you are running an automounter and one -of the directories in your C is on a machine that is currently -unreachable. - -=head1 SECURITY NOTES - -B tries to be safe when executing external commands. - -There are two distinct ways to deal with environment variables. -By default, the I I option is enabled. -This causes commands to be executed with a minimal environment -containing C, C, C, C, C, C -and C in addition to variables from the invoking process -permitted by the I and I I options. -There is effectively a whitelist for environment variables. - -If, however, the I option is disabled in I, any -variables not explicitly denied by the I and I -options are inherited from the invoking process. In this case, -I and I behave like a blacklist. Since it -is not possible to blacklist all potentially dangerous environment -variables, use of the default I behavior is encouraged. - -In all cases, environment variables with a value beginning with -C<()> are removed as they could be interpreted as B functions. -The list of environment variables that B allows or denies is -contained in the output of C when run as root. - -Note that the dynamic linker on most operating systems will remove -variables that can control dynamic linking from the environment of -setuid executables, including B. Depending on the operating -system this may include C<_RLD*>, C, C, C, -C, C, and others. These type of variables are -removed from the environment before B even begins execution -and, as such, it is not possible for B to preserve them. - -To prevent command spoofing, B checks "." and "" (both denoting -current directory) last when searching for a command in the user's -PATH (if one or both are in the PATH). Note, however, that the -actual C environment variable is I modified and is passed -unchanged to the program that B executes. - -B will check the ownership of its time stamp directory -(F<@timedir@> by default) and ignore the directory's contents if -it is not owned by root or if it is writable by a user other than -root. On systems that allow non-root users to give away files via -L, if the time stamp directory is located in a directory -writable by anyone (e.g., F), it is possible for a user to -create the time stamp directory before B is run. However, -because B checks the ownership and mode of the directory and -its contents, the only damage that can be done is to "hide" files -by putting them in the time stamp dir. This is unlikely to happen -since once the time stamp dir is owned by root and inaccessible by -any other user, the user placing files there would be unable to get -them back out. To get around this issue you can use a directory -that is not world-writable for the time stamps (F for -instance) or create F<@timedir@> with the appropriate owner (root) -and permissions (0700) in the system startup files. - -B will not honor time stamps set far in the future. -Timestamps with a date greater than current_time + 2 * C -will be ignored and sudo will log and complain. This is done to -keep a user from creating his/her own time stamp with a bogus -date on systems that allow users to give away files. - -On systems where the boot time is available, B will also not -honor time stamps from before the machine booted. - -Since time stamp files live in the file system, they can outlive a -user's login session. As a result, a user may be able to login, -run a command with B after authenticating, logout, login -again, and run B without authenticating so long as the time -stamp file's modification time is within C<@timeout@> minutes (or -whatever the timeout is set to in I). When the I -option is enabled in I, the time stamp has per-tty granularity -but still may outlive the user's session. On Linux systems where -the devpts filesystem is used, Solaris systems with the devices -filesystem, as well as other systems that utilize a devfs filesystem -that monotonically increase the inode number of devices as they are -created (such as Mac OS X), B is able to determine when a -tty-based time stamp file is stale and will ignore it. Administrators -should not rely on this feature as it is not universally available. - -Please note that B will normally only log the command it -explicitly runs. If a user runs a command such as C or -C, subsequent commands run from that shell will I be -logged, nor will B's access control affect them. The same -is true for commands that offer shell escapes (including most -editors). Because of this, care must be taken when giving users -access to commands via B to verify that the command does not -inadvertently give the user an effective root shell. For more -information, please see the C section in -L. - -=head1 ENVIRONMENT - -B utilizes the following environment variables: - -=over 16 - -=item C - -Default editor to use in B<-e> (sudoedit) mode if neither C -nor C is set - -=item C - -In B<-i> mode or when I is enabled in I, set -to the mail spool of the target user - -=item C - -Set to the home directory of the target user if B<-i> or B<-H> are -specified, I or I are set in I, -or when the B<-s> option is specified and I is set in -I - -=item C - -Set to a sane value if the I sudoers option is set. - -=item C - -Used to determine shell to run with C<-s> option - -=item C - -Specifies the path to a helper program used to read the password -if no terminal is available or if the C<-A> option is specified. - -=item C - -Set to the command run by sudo - -=item C - -Default editor to use in B<-e> (sudoedit) mode - -=item C - -Set to the group ID of the user who invoked sudo - -=item C - -Used as the default password prompt - -=item C - -If set, C will be set to its value for the program being run - -=item C - -Set to the user ID of the user who invoked sudo - -=item C - -Set to the login of the user who invoked sudo - -=item C - -Set to the target user (root unless the B<-u> option is specified) - -=item C - -Default editor to use in B<-e> (sudoedit) mode if C -is not set - -=back - -=head1 FILES - -=over 24 - -=item F<@sysconfdir@/sudoers> - -List of who can run what - -=item F<@timedir@> - -Directory containing time stamps - -=item F - -Initial environment for B<-i> mode on Linux and AIX - -=back - -=head1 EXAMPLES - -Note: the following examples assume suitable L entries. - -To get a file listing of an unreadable directory: - - $ sudo ls /usr/local/protected - -To list the home directory of user yaz on a machine where the -file system holding ~yaz is not exported as root: - - $ sudo -u yaz ls ~yaz - -To edit the F file as user www: - - $ sudo -u www vi ~www/htdocs/index.html - -To view system logs only accessible to root and users in the adm group: - - $ sudo -g adm view /var/log/syslog - -To run an editor as jim with a different primary group: - - $ sudo -u jim -g audio vi ~jim/sound.txt - -To shutdown a machine: - - $ sudo shutdown -r +15 "quick reboot" - -To make a usage listing of the directories in the /home -partition. Note that this runs the commands in a sub-shell -to make the C and file redirection work. - - $ sudo sh -c "cd /home ; du -s * | sort -rn > USAGE" - -=head1 SEE ALSO - -L, L, L, -L, -L, L, L - -=head1 AUTHORS - -Many people have worked on B over the years; this -version consists of code written primarily by: - - Todd C. Miller - -See the HISTORY file in the B distribution or visit -http://www.sudo.ws/sudo/history.html for a short history -of B. - -=head1 CAVEATS - -There is no easy way to prevent a user from gaining a root shell -if that user is allowed to run arbitrary commands via B. -Also, many programs (such as editors) allow the user to run commands -via shell escapes, thus avoiding B's checks. However, on -most systems it is possible to prevent shell escapes with B's -I functionality. See the L manual -for details. - -It is not meaningful to run the C command directly via sudo, e.g., - - $ sudo cd /usr/local/protected - -since when the command exits the parent process (your shell) will -still be the same. Please see the EXAMPLES section for more information. - -If users have sudo C there is nothing to prevent them from -creating their own program that gives them a root shell regardless -of any '!' elements in the user specification. - -Running shell scripts via B can expose the same kernel bugs that -make setuid shell scripts unsafe on some operating systems (if your OS -has a /dev/fd/ directory, setuid shell scripts are generally safe). - -=head1 BUGS - -If you feel you have found a bug in B, please submit a bug report -at http://www.sudo.ws/sudo/bugs/ - -=head1 SUPPORT - -Limited free support is available via the sudo-users mailing list, -see http://www.sudo.ws/mailman/listinfo/sudo-users to subscribe or -search the archives. - -=head1 DISCLAIMER - -B is provided ``AS IS'' and any express or implied warranties, -including, but not limited to, the implied warranties of merchantability -and fitness for a particular purpose are disclaimed. See the LICENSE -file distributed with B or http://www.sudo.ws/sudo/license.html -for complete details. diff --git a/sudo.pp b/sudo.pp index 35c18b7..6b9cd92 100644 --- a/sudo.pp +++ b/sudo.pp @@ -181,6 +181,7 @@ still allow people to get their work done." $bindir/sudoedit 4111 root: $sbindir/visudo 0111 $bindir/sudoreplay 0111 + $includedir/sudo_plugin.h $libexecdir/* $sudoersdir/sudoers.d/ 0750 $sudoers_uid:$sudoers_gid $timedir/ 0700 root: diff --git a/toke.c b/toke.c deleted file mode 100644 index 77b6ecb..0000000 --- a/toke.c +++ /dev/null @@ -1,3623 +0,0 @@ -#include -/* $OpenBSD: flex.skl,v 1.11 2010/08/04 18:24:50 millert Exp $ */ - -/* A lexical scanner generated by flex */ - -/* Scanner skeleton version: - * $Header: /home/cvs/openbsd/src/usr.bin/lex/flex.skl,v 1.11 2010/08/04 18:24:50 millert Exp $ - */ - -#define FLEX_SCANNER -#define YY_FLEX_MAJOR_VERSION 2 -#define YY_FLEX_MINOR_VERSION 5 - -#include -#include - - -/* cfront 1.2 defines "c_plusplus" instead of "__cplusplus" */ -#ifdef c_plusplus -#ifndef __cplusplus -#define __cplusplus -#endif -#endif - - -#ifdef __cplusplus - -#include -#include - -/* Use prototypes in function declarations. */ -#define YY_USE_PROTOS - -/* The "const" storage-class-modifier is valid. */ -#define YY_USE_CONST - -#else /* ! __cplusplus */ - -#ifdef __STDC__ - -#define YY_USE_PROTOS -#define YY_USE_CONST - -#endif /* __STDC__ */ -#endif /* ! __cplusplus */ - -#ifdef __TURBOC__ - #pragma warn -rch - #pragma warn -use -#include -#include -#define YY_USE_CONST -#define YY_USE_PROTOS -#endif - -#ifdef YY_USE_CONST -#define yyconst const -#else -#define yyconst -#endif - - -#ifdef YY_USE_PROTOS -#define YY_PROTO(proto) proto -#else -#define YY_PROTO(proto) () -#endif - -/* Returned upon end-of-file. */ -#define YY_NULL 0 - -/* Promotes a possibly negative, possibly signed char to an unsigned - * integer for use as an array index. If the signed char is negative, - * we want to instead treat it as an 8-bit unsigned char, hence the - * double cast. - */ -#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c) - -/* Enter a start condition. This macro really ought to take a parameter, - * but we do it the disgusting crufty way forced on us by the ()-less - * definition of BEGIN. - */ -#define BEGIN yy_start = 1 + 2 * - -/* Translate the current start state into a value that can be later handed - * to BEGIN to return to the state. The YYSTATE alias is for lex - * compatibility. - */ -#define YY_START ((yy_start - 1) / 2) -#define YYSTATE YY_START - -/* Action number for EOF rule of a given start state. */ -#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1) - -/* Special action meaning "start processing a new file". */ -#define YY_NEW_FILE yyrestart( yyin ) - -#define YY_END_OF_BUFFER_CHAR 0 - -/* Size of default input buffer. */ -#define YY_BUF_SIZE 16384 - -typedef struct yy_buffer_state *YY_BUFFER_STATE; - -extern int yyleng; -extern FILE *yyin, *yyout; - -#define EOB_ACT_CONTINUE_SCAN 0 -#define EOB_ACT_END_OF_FILE 1 -#define EOB_ACT_LAST_MATCH 2 - -/* The funky do-while in the following #define is used to turn the definition - * int a single C statement (which needs a semi-colon terminator). This - * avoids problems with code like: - * - * if ( condition_holds ) - * yyless( 5 ); - * else - * do_something_else(); - * - * Prior to using the do-while the compiler would get upset at the - * "else" because it interpreted the "if" statement as being all - * done when it reached the ';' after the yyless() call. - */ - -/* Return all but the first 'n' matched characters back to the input stream. */ - -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - *yy_cp = yy_hold_char; \ - YY_RESTORE_YY_MORE_OFFSET \ - yy_c_buf_p = yy_cp = yy_bp + n - YY_MORE_ADJ; \ - YY_DO_BEFORE_ACTION; /* set up yytext again */ \ - } \ - while ( 0 ) - -#define unput(c) yyunput( c, yytext_ptr ) - -/* The following is because we cannot portably get our hands on size_t - * (without autoconf's help, which isn't available because we want - * flex-generated scanners to compile on their own). - */ -typedef unsigned int yy_size_t; - - -struct yy_buffer_state - { - FILE *yy_input_file; - - char *yy_ch_buf; /* input buffer */ - char *yy_buf_pos; /* current position in input buffer */ - - /* Size of input buffer in bytes, not including room for EOB - * characters. - */ - yy_size_t yy_buf_size; - - /* Number of characters read into yy_ch_buf, not including EOB - * characters. - */ - int yy_n_chars; - - /* Whether we "own" the buffer - i.e., we know we created it, - * and can realloc() it to grow it, and should free() it to - * delete it. - */ - int yy_is_our_buffer; - - /* Whether this is an "interactive" input source; if so, and - * if we're using stdio for input, then we want to use getc() - * instead of fread(), to make sure we stop fetching input after - * each newline. - */ - int yy_is_interactive; - - /* Whether we're considered to be at the beginning of a line. - * If so, '^' rules will be active on the next match, otherwise - * not. - */ - int yy_at_bol; - - /* Whether to try to fill the input buffer when we reach the - * end of it. - */ - int yy_fill_buffer; - - int yy_buffer_status; -#define YY_BUFFER_NEW 0 -#define YY_BUFFER_NORMAL 1 - /* When an EOF's been seen but there's still some text to process - * then we mark the buffer as YY_EOF_PENDING, to indicate that we - * shouldn't try reading from the input source any more. We might - * still have a bunch of tokens to match, though, because of - * possible backing-up. - * - * When we actually see the EOF, we change the status to "new" - * (via yyrestart()), so that the user can continue scanning by - * just pointing yyin at a new input file. - */ -#define YY_BUFFER_EOF_PENDING 2 - }; - -static YY_BUFFER_STATE yy_current_buffer = 0; - -/* We provide macros for accessing buffer states in case in the - * future we want to put the buffer states in a more general - * "scanner state". - */ -#define YY_CURRENT_BUFFER yy_current_buffer - - -/* yy_hold_char holds the character lost when yytext is formed. */ -static char yy_hold_char; - -static int yy_n_chars; /* number of characters read into yy_ch_buf */ - - -int yyleng; - -/* Points to current character in buffer. */ -static char *yy_c_buf_p = (char *) 0; -static int yy_init = 1; /* whether we need to initialize */ -static int yy_start = 0; /* start state number */ - -/* Flag which is used to allow yywrap()'s to do buffer switches - * instead of setting up a fresh yyin. A bit of a hack ... - */ -static int yy_did_buffer_switch_on_eof; - -void yyrestart YY_PROTO(( FILE *input_file )); - -void yy_switch_to_buffer YY_PROTO(( YY_BUFFER_STATE new_buffer )); -void yy_load_buffer_state YY_PROTO(( void )); -YY_BUFFER_STATE yy_create_buffer YY_PROTO(( FILE *file, int size )); -void yy_delete_buffer YY_PROTO(( YY_BUFFER_STATE b )); -void yy_init_buffer YY_PROTO(( YY_BUFFER_STATE b, FILE *file )); -void yy_flush_buffer YY_PROTO(( YY_BUFFER_STATE b )); -#define YY_FLUSH_BUFFER yy_flush_buffer( yy_current_buffer ) - -YY_BUFFER_STATE yy_scan_buffer YY_PROTO(( char *base, yy_size_t size )); -YY_BUFFER_STATE yy_scan_string YY_PROTO(( yyconst char *yy_str )); -YY_BUFFER_STATE yy_scan_bytes YY_PROTO(( yyconst char *bytes, int len )); - -static void *yy_flex_alloc YY_PROTO(( yy_size_t )); -static void *yy_flex_realloc YY_PROTO(( void *, yy_size_t )); -static void yy_flex_free YY_PROTO(( void * )); - -#define yy_new_buffer yy_create_buffer - -#define yy_set_interactive(is_interactive) \ - { \ - if ( ! yy_current_buffer ) \ - yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ - yy_current_buffer->yy_is_interactive = is_interactive; \ - } - -#define yy_set_bol(at_bol) \ - { \ - if ( ! yy_current_buffer ) \ - yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); \ - yy_current_buffer->yy_at_bol = at_bol; \ - } - -#define YY_AT_BOL() (yy_current_buffer->yy_at_bol) - - -#define yywrap() 1 -#define YY_SKIP_YYWRAP -typedef unsigned char YY_CHAR; -FILE *yyin = (FILE *) 0, *yyout = (FILE *) 0; -typedef int yy_state_type; -extern char *yytext; -#define yytext_ptr yytext - -static yy_state_type yy_get_previous_state YY_PROTO(( void )); -static yy_state_type yy_try_NUL_trans YY_PROTO(( yy_state_type current_state )); -static int yy_get_next_buffer YY_PROTO(( void )); -static void yy_fatal_error YY_PROTO(( yyconst char msg[] )); - -/* Done after the current pattern has been matched and before the - * corresponding action - sets up yytext. - */ -#define YY_DO_BEFORE_ACTION \ - yytext_ptr = yy_bp; \ - yyleng = (int) (yy_cp - yy_bp); \ - yy_hold_char = *yy_cp; \ - *yy_cp = '\0'; \ - yy_c_buf_p = yy_cp; - -#define YY_NUM_RULES 56 -#define YY_END_OF_BUFFER 57 -static yyconst short int yy_accept[599] = - { 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 57, 44, 52, 51, 50, 43, 55, 32, - 45, 46, 32, 47, 44, 44, 44, 44, 49, 48, - 55, 39, 39, 39, 39, 39, 39, 39, 55, 44, - 44, 52, 55, 39, 39, 39, 39, 39, 2, 55, - 1, 44, 44, 17, 16, 17, 16, 16, 55, 55, - 55, 3, 9, 8, 9, 4, 9, 5, 55, 13, - 13, 13, 11, 12, 44, 0, 52, 50, 0, 54, - 0, 44, 34, 0, 32, 0, 33, 0, 42, 42, - 0, 44, 44, 0, 44, 44, 44, 44, 0, 37, - - 39, 39, 39, 39, 39, 39, 39, 44, 53, 44, - 52, 0, 0, 0, 0, 0, 0, 44, 44, 44, - 44, 44, 2, 1, 0, 1, 40, 40, 0, 44, - 17, 17, 15, 14, 15, 0, 0, 3, 9, 0, - 6, 7, 9, 9, 13, 0, 13, 13, 0, 10, - 0, 0, 0, 34, 34, 0, 0, 44, 44, 44, - 44, 44, 0, 0, 37, 37, 39, 39, 39, 39, - 39, 39, 39, 39, 39, 44, 0, 0, 0, 0, - 0, 0, 44, 44, 44, 44, 44, 0, 44, 10, - 0, 44, 44, 44, 44, 44, 44, 0, 38, 38, - - 38, 0, 0, 37, 37, 37, 37, 37, 37, 37, - 39, 39, 39, 39, 39, 39, 39, 39, 39, 44, - 0, 0, 0, 0, 0, 0, 44, 44, 44, 44, - 44, 44, 44, 0, 0, 38, 38, 38, 0, 37, - 37, 0, 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 0, 25, 39, 39, 39, 39, 39, - 39, 39, 39, 44, 0, 0, 0, 0, 44, 44, - 44, 44, 44, 44, 44, 44, 0, 38, 0, 37, - 37, 37, 0, 0, 0, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 37, 39, 39, - - 39, 39, 39, 39, 39, 39, 44, 0, 0, 0, - 44, 44, 44, 35, 35, 35, 0, 0, 37, 37, - 37, 37, 37, 37, 37, 0, 0, 0, 0, 0, - 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 39, 39, 0, 24, 39, 39, - 39, 39, 0, 23, 0, 26, 44, 0, 0, 0, - 44, 44, 44, 44, 35, 35, 35, 35, 0, 37, - 0, 37, 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 0, 0, 0, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 37, 39, 39, - - 39, 39, 39, 39, 41, 0, 0, 0, 44, 20, - 40, 44, 36, 36, 36, 37, 0, 0, 0, 37, - 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 0, 0, 0, 0, 0, 37, 37, 37, - 37, 37, 37, 37, 37, 39, 39, 39, 39, 0, - 22, 0, 27, 0, 20, 0, 0, 44, 0, 44, - 44, 44, 36, 36, 36, 36, 36, 0, 0, 0, - 0, 0, 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 0, 30, 39, 39, 39, 0, 0, 0, - - 21, 20, 0, 0, 0, 0, 0, 20, 0, 44, - 44, 44, 36, 36, 0, 0, 0, 37, 37, 37, - 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, - 37, 37, 37, 37, 37, 0, 28, 39, 39, 21, - 0, 18, 0, 0, 20, 44, 44, 44, 44, 44, - 0, 0, 0, 0, 0, 37, 37, 37, 37, 37, - 37, 37, 37, 0, 31, 39, 0, 44, 44, 44, - 37, 37, 37, 37, 37, 37, 0, 29, 0, 44, - 44, 44, 44, 44, 37, 37, 37, 37, 37, 0, - 19, 35, 35, 35, 35, 35, 35, 0 - - } ; - -static yyconst int yy_ec[256] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 4, 5, 6, 1, 7, 1, 1, 8, - 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, - 19, 20, 21, 22, 22, 22, 23, 24, 1, 1, - 25, 26, 10, 27, 28, 29, 30, 31, 32, 29, - 33, 34, 35, 36, 36, 37, 36, 38, 39, 40, - 36, 41, 42, 43, 44, 45, 46, 47, 36, 36, - 10, 48, 10, 1, 49, 1, 50, 51, 52, 53, - - 54, 55, 56, 56, 57, 56, 56, 58, 59, 60, - 61, 56, 56, 62, 63, 64, 65, 56, 56, 56, - 56, 56, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1 - } ; - -static yyconst int yy_meta[66] = - { 0, - 1, 2, 3, 4, 5, 6, 1, 7, 7, 1, - 1, 8, 1, 9, 10, 11, 11, 11, 11, 11, - 11, 11, 11, 12, 13, 7, 1, 11, 11, 11, - 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 14, 15, 16, - 16, 16, 16, 16, 16, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15 - } ; - -static yyconst short int yy_base[663] = - { 0, - 0, 64, 65, 66, 85, 100, 147, 211, 275, 322, - 71, 111, 2613, 2557, 2602, 3671, 2599, 3671, 368, 87, - 3671, 3671, 2554, 3671, 113, 378, 124, 146, 2577, 3671, - 3671, 433, 2553, 483, 2560, 2551, 2555, 2550, 537, 154, - 21, 150, 561, 2522, 2526, 2482, 2477, 2478, 80, 203, - 2529, 288, 31, 0, 3671, 2516, 3671, 0, 305, 616, - 81, 0, 2469, 3671, 75, 3671, 82, 3671, 124, 2468, - 83, 86, 3671, 152, 2467, 638, 2512, 2509, 2509, 3671, - 211, 219, 289, 230, 130, 336, 2447, 663, 294, 2437, - 688, 356, 699, 2458, 2467, 395, 500, 169, 2456, 145, - - 739, 0, 2439, 2428, 314, 2408, 2396, 135, 3671, 236, - 524, 2379, 2383, 2375, 2370, 2352, 96, 72, 230, 242, - 197, 256, 180, 2409, 569, 2408, 567, 2356, 793, 253, - 0, 2399, 252, 3671, 3671, 578, 280, 0, 2354, 433, - 3671, 3671, 2353, 316, 2352, 2394, 310, 312, 319, 2393, - 2388, 2377, 586, 604, 357, 699, 545, 806, 841, 876, - 911, 2339, 2328, 951, 328, 992, 1032, 2317, 2291, 2292, - 2299, 2294, 2289, 2275, 2268, 307, 2239, 2243, 2225, 2217, - 2220, 328, 371, 2220, 301, 208, 131, 649, 321, 2240, - 2222, 661, 318, 1074, 1109, 511, 335, 2183, 2158, 716, - - 404, 2148, 2145, 412, 725, 1144, 756, 764, 1185, 790, - 2138, 401, 402, 2118, 2116, 2106, 2103, 2069, 2075, 496, - 2008, 2004, 1989, 2002, 1974, 553, 460, 593, 504, 512, - 1227, 1262, 1297, 2011, 1990, 814, 1990, 1967, 1964, 1963, - 630, 823, 642, 849, 671, 1332, 0, 859, 1343, 884, - 831, 1384, 894, 628, 3671, 1948, 1941, 1924, 1900, 1871, - 1859, 1843, 1823, 500, 1803, 1786, 1757, 611, 600, 309, - 657, 928, 752, 1426, 1461, 938, 1795, 1794, 1793, 1791, - 1494, 772, 971, 1011, 1051, 867, 1042, 1065, 1082, 1092, - 1536, 0, 1094, 1547, 1117, 902, 1588, 1127, 1759, 1755, - - 629, 577, 1751, 1738, 762, 885, 878, 1719, 1686, 607, - 601, 889, 969, 1629, 1663, 1697, 1719, 1718, 1717, 1161, - 1732, 1169, 979, 1772, 1204, 1235, 1725, 1245, 1272, 1282, - 1127, 1195, 1218, 1307, 1307, 1318, 1814, 0, 1320, 1825, - 1360, 1019, 1866, 1403, 1666, 1669, 936, 3671, 1670, 1662, - 1643, 1627, 1017, 3671, 1057, 3671, 1105, 1613, 1606, 456, - 1212, 643, 1106, 1437, 773, 1907, 1941, 1370, 1645, 1630, - 1445, 1263, 1470, 1283, 1976, 0, 676, 1987, 1478, 1411, - 2027, 1513, 1566, 1607, 1639, 1426, 1504, 1649, 1651, 1671, - 1681, 2069, 0, 1683, 2080, 1705, 1486, 1715, 1594, 1589, - - 1591, 1547, 1169, 1210, 1525, 1463, 1445, 883, 715, 1866, - 1424, 2122, 2157, 2192, 2227, 1446, 1751, 1791, 1844, 1445, - 1567, 1608, 1883, 1716, 2262, 0, 792, 2273, 1915, 1521, - 2313, 1925, 1949, 1438, 1959, 2006, 2046, 1652, 1742, 2090, - 963, 1061, 2355, 0, 1055, 1368, 1325, 1299, 1272, 1409, - 3671, 1449, 3671, 1256, 1568, 2104, 336, 1321, 1773, 1867, - 2104, 970, 2365, 2400, 2435, 2470, 1256, 2052, 1197, 2137, - 2167, 2147, 1128, 1100, 1792, 1926, 2175, 1960, 2505, 0, - 1097, 2516, 2200, 1891, 2556, 2210, 2236, 2245, 2291, 1835, - 1106, 1141, 1519, 3671, 1572, 1074, 1014, 825, 881, 288, - - 833, 2028, 2267, 2314, 2344, 2338, 2381, 2392, 2400, 2598, - 2633, 2668, 2411, 1935, 2446, 2456, 2480, 832, 829, 1988, - 2007, 2488, 2104, 2703, 0, 1206, 2714, 2533, 2183, 2575, - 801, 2542, 2607, 2426, 788, 1591, 3671, 1611, 683, 3671, - 699, 3671, 1228, 2615, 2641, 2649, 1257, 2756, 2791, 2659, - 2682, 656, 2692, 2733, 2766, 589, 549, 2123, 510, 428, - 2774, 0, 1286, 1612, 3671, 1756, 2114, 2826, 2861, 2896, - 2799, 2807, 2815, 399, 0, 280, 1757, 3671, 215, 2837, - 1620, 2931, 2966, 2847, 3671, 2870, 2880, 2218, 3671, 155, - 3671, 2907, 2915, 2948, 53, 2981, 2741, 3671, 3029, 3045, - - 3061, 3077, 3093, 3109, 3125, 3141, 3157, 3163, 3179, 3195, - 1394, 3211, 3227, 3243, 3259, 3275, 3291, 3307, 3313, 3320, - 3336, 3352, 3358, 3365, 3371, 3377, 3383, 3390, 3396, 3402, - 3408, 3415, 3423, 3429, 3435, 3441, 3448, 3456, 3462, 3468, - 3475, 3483, 3489, 3497, 3504, 3512, 3518, 3526, 3533, 3541, - 3557, 3573, 3579, 3587, 3594, 3610, 3616, 3624, 3630, 3638, - 1460, 3654 - } ; - -static yyconst short int yy_def[663] = - { 0, - 598, 1, 1, 1, 599, 599, 600, 600, 601, 601, - 602, 602, 598, 603, 598, 598, 598, 598, 604, 605, - 598, 598, 606, 598, 607, 603, 26, 26, 608, 598, - 598, 598, 32, 32, 34, 34, 34, 34, 603, 26, - 603, 598, 604, 32, 32, 34, 34, 34, 598, 598, - 598, 609, 603, 610, 598, 610, 598, 610, 598, 604, - 598, 611, 612, 598, 612, 598, 612, 598, 613, 614, - 614, 614, 598, 598, 603, 603, 598, 598, 615, 598, - 616, 598, 605, 598, 617, 605, 606, 606, 607, 618, - 603, 603, 26, 608, 93, 93, 93, 93, 619, 620, - - 32, 34, 34, 34, 34, 34, 34, 603, 598, 603, - 598, 598, 598, 598, 598, 598, 615, 603, 93, 603, - 603, 603, 598, 598, 598, 598, 609, 621, 603, 603, - 610, 610, 598, 598, 598, 616, 598, 611, 612, 612, - 598, 598, 612, 612, 614, 598, 614, 614, 598, 598, - 615, 622, 598, 598, 617, 617, 598, 603, 603, 603, - 93, 161, 623, 598, 624, 598, 32, 34, 34, 34, - 34, 34, 34, 34, 34, 603, 598, 598, 598, 598, - 598, 615, 603, 161, 603, 603, 603, 598, 603, 598, - 622, 603, 603, 603, 603, 603, 603, 625, 626, 626, - - 200, 627, 626, 628, 166, 598, 206, 206, 598, 206, - 34, 34, 34, 34, 34, 34, 34, 34, 34, 603, - 598, 598, 598, 598, 598, 615, 603, 603, 603, 603, - 603, 603, 603, 598, 629, 629, 236, 629, 630, 631, - 632, 598, 633, 209, 633, 633, 246, 633, 598, 249, - 249, 598, 249, 598, 598, 34, 34, 34, 34, 34, - 34, 34, 34, 603, 598, 598, 598, 615, 603, 603, - 603, 603, 603, 603, 603, 603, 634, 634, 635, 636, - 598, 598, 598, 598, 598, 637, 637, 638, 252, 638, - 638, 291, 638, 598, 294, 294, 598, 294, 34, 34, - - 34, 34, 34, 34, 34, 34, 603, 598, 598, 615, - 603, 603, 603, 603, 603, 603, 598, 639, 640, 281, - 598, 321, 321, 598, 321, 598, 598, 598, 598, 598, - 598, 641, 641, 642, 297, 642, 642, 337, 642, 598, - 340, 340, 598, 340, 34, 34, 598, 598, 34, 34, - 34, 34, 598, 598, 598, 598, 603, 598, 598, 615, - 603, 603, 603, 603, 603, 603, 603, 603, 598, 643, - 598, 644, 324, 644, 644, 375, 375, 598, 378, 378, - 598, 378, 598, 598, 598, 598, 645, 645, 646, 343, - 646, 646, 392, 646, 598, 395, 395, 395, 34, 34, - - 34, 34, 34, 34, 603, 598, 598, 615, 603, 603, - 603, 603, 603, 603, 603, 598, 598, 598, 598, 647, - 647, 648, 381, 648, 648, 425, 425, 598, 428, 428, - 598, 428, 598, 598, 598, 598, 598, 598, 649, 649, - 650, 650, 650, 443, 443, 34, 34, 34, 34, 598, - 598, 598, 598, 598, 598, 615, 615, 603, 651, 652, - 603, 603, 603, 603, 603, 603, 603, 598, 598, 598, - 598, 598, 598, 653, 653, 654, 431, 654, 654, 479, - 479, 598, 482, 482, 598, 482, 598, 598, 598, 598, - 655, 655, 598, 598, 34, 34, 34, 598, 656, 615, - - 603, 651, 651, 651, 651, 598, 651, 652, 652, 603, - 603, 603, 603, 603, 598, 598, 598, 598, 657, 657, - 658, 485, 658, 658, 524, 524, 598, 527, 527, 527, - 598, 598, 598, 598, 598, 598, 598, 34, 34, 598, - 656, 598, 615, 598, 598, 603, 603, 603, 603, 603, - 598, 598, 598, 598, 598, 598, 659, 659, 660, 660, - 660, 561, 561, 598, 598, 34, 615, 603, 603, 603, - 598, 598, 598, 598, 661, 661, 598, 598, 662, 603, - 603, 603, 603, 603, 598, 598, 598, 598, 598, 662, - 598, 603, 603, 603, 603, 603, 603, 0, 598, 598, - - 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, - 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, - 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, - 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, - 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, - 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, - 598, 598 - } ; - -static yyconst short int yy_nxt[3737] = - { 0, - 14, 15, 16, 17, 18, 19, 20, 21, 22, 14, - 23, 24, 14, 14, 25, 26, 27, 28, 26, 26, - 26, 26, 26, 29, 30, 31, 14, 32, 32, 32, - 32, 33, 34, 34, 34, 34, 35, 36, 34, 37, - 34, 38, 34, 34, 34, 34, 34, 39, 14, 40, - 40, 40, 40, 40, 40, 14, 14, 14, 14, 14, - 14, 14, 41, 14, 14, 42, 49, 49, 76, 43, - 50, 50, 71, 16, 72, 73, 51, 51, 76, 52, - 52, 123, 137, 109, 147, 110, 15, 55, 56, 148, - 57, 124, 84, 44, 45, 130, 57, 46, 80, 141, - - 76, 15, 55, 56, 47, 57, 142, 48, 57, 58, - 85, 57, 71, 16, 72, 73, 90, 90, 74, 76, - 90, 90, 140, 57, 58, 144, 109, 53, 53, 140, - 146, 183, 59, 146, 86, 84, 137, 109, 90, 96, - 96, 96, 96, 96, 96, 96, 96, 59, 15, 16, - 17, 111, 60, 149, 150, 182, 145, 591, 74, 164, - 91, 97, 97, 97, 97, 97, 98, 75, 166, 95, - 95, 95, 95, 95, 95, 95, 95, 156, 76, 112, - 113, 123, 76, 114, 162, 162, 162, 162, 162, 162, - 115, 124, 227, 116, 61, 62, 62, 62, 62, 62, - - 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, - 62, 62, 15, 16, 17, 125, 60, 591, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 153, 75, 76, 154, 154, 154, 154, 154, - 154, 154, 154, 137, 109, 76, 186, 229, 61, 62, - 62, 62, 62, 62, 62, 62, 62, 62, 62, 62, - 62, 62, 62, 62, 62, 62, 15, 16, 17, 64, - 60, 137, 109, 76, 184, 65, 66, 67, 176, 76, - 80, 128, 128, 371, 598, 128, 128, 90, 90, 68, - - 76, 90, 90, 76, 185, 189, 133, 109, 134, 187, - 135, 147, 598, 128, 134, 148, 135, 137, 109, 90, - 149, 150, 69, 15, 16, 17, 64, 60, 135, 135, - 80, 192, 65, 66, 67, 129, 86, 83, 80, 83, - 83, 91, 164, 83, 83, 170, 68, 83, 76, 543, - 171, 205, 135, 172, 76, 173, 76, 146, 94, 146, - 83, 83, 598, 140, 227, 76, 312, 220, 76, 69, - 80, 158, 159, 160, 158, 158, 158, 158, 158, 226, - 81, 230, 76, 82, 82, 82, 82, 82, 82, 82, - 82, 92, 500, 93, 93, 93, 93, 93, 93, 93, - - 93, 94, 254, 76, 156, 95, 95, 95, 95, 95, - 162, 162, 162, 162, 162, 162, 162, 162, 76, 238, - 238, 238, 522, 227, 255, 76, 164, 95, 95, 95, - 95, 95, 95, 75, 139, 205, 256, 139, 139, 75, - 257, 598, 75, 75, 139, 75, 75, 75, 101, 101, - 101, 101, 101, 101, 101, 101, 94, 139, 80, 75, - 101, 101, 101, 101, 101, 102, 102, 102, 102, 102, - 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, - 76, 102, 95, 95, 95, 95, 95, 95, 75, 75, - 75, 75, 75, 75, 75, 75, 75, 75, 102, 102, - - 102, 102, 102, 102, 102, 102, 598, 76, 269, 408, - 102, 102, 102, 102, 102, 162, 162, 162, 162, 162, - 162, 162, 162, 371, 192, 111, 193, 193, 193, 193, - 193, 193, 75, 75, 75, 75, 75, 75, 108, 109, - 75, 75, 75, 76, 75, 75, 90, 76, 75, 264, - 90, 76, 307, 112, 113, 80, 90, 114, 76, 76, - 75, 75, 75, 80, 115, 271, 227, 116, 90, 90, - 128, 128, 522, 81, 128, 128, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 128, 598, 598, 598, 598, 598, 598, 598, - - 598, 154, 154, 154, 154, 154, 154, 154, 154, 80, - 268, 349, 477, 80, 129, 350, 94, 117, 80, 154, - 154, 154, 154, 154, 154, 154, 154, 311, 136, 254, - 347, 598, 598, 598, 598, 598, 598, 598, 598, 75, - 76, 75, 75, 75, 164, 75, 75, 76, 76, 75, - 128, 255, 348, 205, 128, 242, 164, 270, 361, 360, - 128, 75, 75, 75, 87, 244, 87, 87, 87, 551, - 87, 87, 128, 128, 87, 310, 231, 232, 233, 231, - 231, 231, 231, 231, 598, 164, 87, 87, 87, 89, - 76, 75, 75, 89, 244, 75, 75, 420, 420, 89, - - 155, 542, 155, 155, 76, 410, 155, 155, 76, 313, - 155, 89, 89, 75, 161, 161, 161, 161, 161, 161, - 161, 161, 155, 155, 155, 566, 161, 161, 161, 161, - 161, 236, 236, 237, 238, 238, 238, 238, 238, 202, - 210, 210, 210, 210, 210, 210, 210, 210, 161, 161, - 161, 161, 161, 161, 167, 167, 167, 167, 167, 167, - 167, 167, 76, 353, 458, 272, 167, 167, 167, 167, - 167, 246, 246, 246, 246, 246, 246, 246, 246, 247, - 247, 247, 247, 247, 248, 354, 164, 364, 161, 161, - 161, 161, 161, 161, 127, 205, 75, 75, 127, 76, - - 75, 75, 164, 598, 127, 245, 245, 245, 245, 245, - 245, 245, 245, 474, 474, 164, 127, 127, 75, 192, - 76, 193, 193, 193, 193, 193, 193, 193, 193, 278, - 278, 278, 278, 278, 278, 278, 278, 202, 283, 284, - 285, 283, 283, 283, 283, 283, 292, 292, 292, 292, - 292, 293, 477, 76, 192, 423, 194, 194, 194, 194, - 194, 194, 194, 194, 253, 253, 253, 253, 253, 253, - 253, 253, 242, 164, 287, 287, 287, 287, 287, 287, - 76, 164, 244, 542, 456, 80, 355, 540, 76, 192, - 244, 195, 195, 195, 195, 195, 196, 193, 193, 291, - - 291, 291, 291, 291, 291, 291, 291, 598, 356, 290, - 290, 290, 290, 290, 290, 290, 290, 338, 338, 338, - 338, 338, 339, 76, 75, 76, 197, 197, 197, 197, - 197, 197, 197, 197, 357, 457, 76, 347, 197, 197, - 197, 197, 197, 314, 315, 316, 314, 314, 314, 314, - 314, 272, 362, 273, 273, 273, 273, 273, 273, 348, - 197, 197, 197, 197, 197, 197, 199, 200, 201, 201, - 201, 201, 201, 201, 202, 76, 242, 164, 203, 203, - 203, 203, 203, 461, 326, 76, 327, 327, 327, 327, - 327, 327, 327, 327, 376, 376, 376, 376, 376, 377, - - 203, 203, 203, 203, 203, 203, 164, 206, 207, 208, - 206, 206, 206, 206, 206, 209, 76, 76, 353, 210, - 210, 210, 210, 210, 326, 363, 328, 328, 328, 328, - 328, 328, 328, 328, 393, 393, 393, 393, 393, 394, - 354, 210, 210, 210, 210, 210, 210, 211, 211, 211, - 211, 211, 211, 211, 211, 242, 164, 539, 355, 211, - 211, 211, 211, 211, 326, 244, 329, 329, 329, 329, - 329, 330, 327, 327, 598, 164, 491, 491, 242, 164, - 356, 197, 197, 197, 197, 197, 197, 192, 289, 193, - 193, 193, 193, 193, 193, 193, 193, 298, 298, 298, - - 298, 298, 298, 298, 298, 598, 164, 242, 164, 333, - 333, 333, 333, 333, 333, 289, 538, 289, 519, 519, - 164, 76, 192, 423, 193, 193, 193, 193, 193, 193, - 193, 193, 337, 337, 337, 337, 337, 337, 337, 337, - 598, 164, 336, 336, 336, 336, 336, 336, 336, 336, - 244, 373, 76, 76, 242, 164, 76, 242, 164, 243, - 243, 243, 243, 243, 243, 243, 243, 244, 405, 411, - 450, 245, 245, 245, 245, 245, 325, 325, 325, 325, - 325, 325, 325, 325, 375, 375, 375, 375, 375, 375, - 375, 375, 451, 245, 245, 245, 245, 245, 245, 164, - - 249, 250, 251, 249, 249, 249, 249, 249, 252, 164, - 468, 452, 253, 253, 253, 253, 253, 598, 289, 374, - 374, 374, 374, 374, 374, 374, 374, 557, 557, 567, - 80, 242, 164, 453, 253, 253, 253, 253, 253, 253, - 272, 289, 273, 273, 273, 273, 273, 273, 273, 273, - 383, 384, 385, 383, 383, 383, 383, 383, 326, 76, - 327, 327, 327, 327, 327, 327, 327, 327, 409, 461, - 546, 514, 514, 514, 76, 272, 371, 274, 274, 274, - 274, 274, 274, 274, 274, 326, 373, 327, 327, 327, - 327, 327, 327, 327, 327, 326, 598, 327, 327, 327, - - 327, 327, 327, 76, 76, 498, 373, 575, 575, 76, - 272, 497, 275, 275, 275, 275, 275, 276, 273, 273, - 242, 164, 344, 344, 344, 344, 344, 344, 344, 344, - 335, 598, 164, 242, 164, 388, 388, 388, 388, 388, - 388, 335, 496, 335, 76, 242, 164, 287, 287, 287, - 287, 287, 287, 287, 287, 244, 242, 164, 288, 288, - 288, 288, 288, 288, 288, 288, 289, 495, 76, 493, - 290, 290, 290, 290, 290, 392, 392, 392, 392, 392, - 392, 392, 392, 501, 364, 365, 365, 365, 365, 365, - 365, 494, 290, 290, 290, 290, 290, 290, 164, 294, - - 295, 296, 294, 294, 294, 294, 294, 297, 138, 138, - 450, 298, 298, 298, 298, 298, 598, 76, 391, 391, - 391, 391, 391, 391, 391, 391, 426, 426, 426, 426, - 426, 427, 451, 298, 298, 298, 298, 298, 298, 272, - 164, 273, 273, 273, 273, 273, 273, 273, 273, 289, - 452, 433, 412, 413, 414, 415, 412, 412, 412, 412, - 417, 418, 419, 417, 417, 417, 417, 417, 373, 320, - 589, 76, 453, 76, 272, 589, 273, 273, 273, 273, - 273, 273, 273, 273, 76, 382, 382, 382, 382, 382, - 382, 382, 382, 425, 425, 425, 425, 425, 425, 425, - - 425, 444, 444, 444, 444, 444, 445, 455, 76, 321, - 322, 323, 321, 321, 321, 321, 321, 324, 164, 454, - 493, 325, 325, 325, 325, 325, 598, 335, 424, 424, - 424, 424, 424, 424, 424, 424, 480, 480, 480, 480, - 480, 481, 494, 325, 325, 325, 325, 325, 325, 242, - 164, 333, 333, 333, 333, 333, 333, 333, 333, 289, - 242, 164, 334, 334, 334, 334, 334, 334, 334, 334, - 335, 459, 76, 536, 336, 336, 336, 336, 336, 433, - 371, 434, 434, 434, 434, 434, 434, 434, 434, 449, - 373, 459, 536, 459, 459, 537, 336, 336, 336, 336, - - 336, 336, 164, 340, 341, 342, 340, 340, 340, 340, - 340, 343, 564, 564, 537, 344, 344, 344, 344, 344, - 433, 371, 435, 435, 435, 435, 435, 435, 435, 435, - 448, 423, 447, 580, 565, 565, 446, 344, 344, 344, - 344, 344, 344, 364, 365, 365, 365, 365, 365, 365, - 365, 365, 433, 320, 436, 436, 436, 436, 436, 437, - 434, 434, 242, 164, 242, 164, 164, 76, 240, 407, - 406, 404, 335, 403, 390, 335, 76, 364, 366, 366, - 366, 366, 366, 366, 366, 366, 398, 398, 398, 398, - 398, 398, 398, 398, 598, 164, 242, 164, 440, 440, - - 440, 440, 440, 440, 390, 402, 390, 401, 400, 399, - 76, 364, 367, 367, 367, 367, 367, 368, 365, 365, - 443, 443, 443, 443, 443, 443, 443, 443, 598, 598, - 442, 442, 442, 442, 442, 442, 442, 442, 326, 423, - 320, 240, 202, 359, 76, 371, 358, 372, 372, 372, - 372, 372, 372, 372, 372, 373, 164, 577, 577, 374, - 374, 374, 374, 374, 468, 390, 469, 469, 469, 469, - 469, 469, 469, 469, 503, 352, 504, 505, 506, 578, - 578, 374, 374, 374, 374, 374, 374, 378, 379, 380, - 378, 378, 378, 378, 378, 381, 351, 346, 345, 382, - - 382, 382, 382, 382, 468, 371, 470, 470, 470, 470, - 470, 470, 470, 470, 320, 423, 240, 202, 202, 265, - 507, 382, 382, 382, 382, 382, 382, 242, 164, 388, - 388, 388, 388, 388, 388, 388, 388, 335, 242, 164, - 389, 389, 389, 389, 389, 389, 389, 389, 390, 164, - 309, 308, 391, 391, 391, 391, 391, 468, 390, 471, - 471, 471, 471, 471, 472, 469, 469, 306, 503, 459, - 504, 505, 506, 305, 391, 391, 391, 391, 391, 391, - 164, 395, 396, 397, 395, 395, 395, 395, 395, 459, - 304, 459, 460, 398, 398, 398, 398, 398, 432, 432, - - 432, 432, 432, 432, 432, 432, 525, 525, 525, 525, - 525, 526, 303, 76, 509, 398, 398, 398, 398, 398, - 398, 364, 365, 365, 365, 365, 365, 365, 365, 365, - 479, 479, 479, 479, 479, 479, 479, 479, 598, 371, - 478, 478, 478, 478, 478, 478, 478, 478, 302, 477, - 514, 514, 514, 301, 76, 364, 365, 365, 365, 365, - 365, 365, 365, 365, 487, 488, 489, 487, 487, 487, - 487, 487, 433, 598, 434, 434, 434, 434, 434, 434, - 434, 434, 76, 477, 300, 299, 281, 240, 76, 371, - 202, 421, 421, 421, 421, 421, 421, 421, 421, 373, - - 371, 371, 422, 422, 422, 422, 422, 422, 422, 422, - 423, 477, 277, 202, 424, 424, 424, 424, 424, 433, - 371, 434, 434, 434, 434, 434, 434, 434, 434, 598, - 522, 598, 598, 598, 100, 265, 424, 424, 424, 424, - 424, 424, 428, 429, 430, 428, 428, 428, 428, 428, - 431, 267, 265, 266, 432, 432, 432, 432, 432, 433, - 265, 434, 434, 434, 434, 434, 434, 515, 516, 517, - 515, 515, 515, 515, 515, 507, 432, 432, 432, 432, - 432, 432, 242, 164, 440, 440, 440, 440, 440, 440, - 440, 440, 390, 242, 164, 441, 441, 441, 441, 441, - - 441, 441, 441, 242, 164, 456, 80, 442, 442, 442, - 442, 442, 263, 390, 262, 567, 80, 598, 499, 510, - 511, 512, 510, 510, 510, 510, 510, 522, 579, 442, - 442, 442, 442, 442, 442, 461, 371, 462, 462, 462, - 462, 462, 462, 462, 462, 261, 522, 260, 259, 258, - 468, 76, 469, 469, 469, 469, 469, 469, 469, 469, - 468, 94, 469, 469, 469, 469, 469, 469, 202, 76, - 461, 240, 463, 463, 463, 463, 463, 463, 463, 463, - 468, 202, 469, 469, 469, 469, 469, 469, 469, 469, - 486, 486, 486, 486, 486, 486, 486, 486, 562, 562, - - 562, 562, 562, 563, 76, 461, 100, 464, 464, 464, - 464, 464, 465, 466, 466, 524, 524, 524, 524, 524, - 524, 524, 524, 598, 80, 523, 523, 523, 523, 523, - 523, 523, 523, 585, 585, 585, 585, 585, 585, 76, - 461, 190, 467, 467, 467, 462, 462, 462, 462, 462, - 164, 531, 531, 531, 531, 531, 531, 531, 531, 164, - 532, 532, 532, 532, 532, 532, 532, 532, 503, 228, - 504, 505, 506, 225, 76, 371, 224, 475, 475, 475, - 475, 475, 475, 475, 475, 423, 371, 223, 476, 476, - 476, 476, 476, 476, 476, 476, 477, 222, 221, 219, - - 478, 478, 478, 478, 478, 164, 533, 533, 533, 533, - 533, 534, 531, 531, 507, 598, 218, 504, 505, 506, - 217, 216, 478, 478, 478, 478, 478, 478, 482, 483, - 484, 482, 482, 482, 482, 482, 485, 215, 214, 213, - 486, 486, 486, 486, 486, 598, 212, 598, 598, 506, - 544, 100, 92, 545, 545, 545, 545, 545, 545, 545, - 545, 507, 486, 486, 486, 486, 486, 486, 242, 164, - 492, 492, 492, 492, 492, 492, 492, 492, 461, 80, - 466, 466, 466, 466, 466, 466, 466, 466, 502, 502, - 80, 507, 502, 598, 190, 598, 598, 598, 145, 146, - - 140, 140, 132, 188, 502, 502, 502, 508, 508, 126, - 126, 508, 76, 461, 181, 466, 466, 466, 466, 466, - 466, 466, 466, 508, 508, 508, 513, 513, 513, 513, - 513, 513, 513, 513, 180, 179, 178, 177, 175, 509, - 164, 531, 531, 531, 531, 531, 531, 76, 461, 174, - 466, 466, 466, 466, 466, 466, 513, 513, 76, 551, - 169, 552, 552, 552, 552, 552, 552, 552, 552, 551, - 168, 553, 553, 553, 553, 553, 553, 553, 553, 100, - 75, 100, 76, 461, 157, 513, 513, 513, 513, 513, - 513, 513, 513, 551, 88, 554, 554, 554, 554, 554, - - 555, 552, 552, 530, 530, 530, 530, 530, 530, 530, - 530, 80, 78, 77, 76, 146, 140, 76, 371, 132, - 520, 520, 520, 520, 520, 520, 520, 520, 477, 371, - 126, 521, 521, 521, 521, 521, 521, 521, 521, 522, - 122, 121, 120, 523, 523, 523, 523, 523, 561, 561, - 561, 561, 561, 561, 561, 561, 164, 531, 531, 531, - 531, 531, 531, 531, 531, 523, 523, 523, 523, 523, - 523, 527, 528, 529, 527, 527, 527, 527, 527, 119, - 118, 107, 106, 530, 530, 530, 530, 530, 598, 105, - 560, 560, 560, 560, 560, 560, 560, 560, 104, 103, - - 100, 88, 78, 77, 76, 530, 530, 530, 530, 530, - 530, 546, 598, 547, 547, 547, 547, 547, 547, 547, - 547, 164, 531, 531, 531, 531, 531, 531, 531, 531, - 545, 545, 545, 545, 545, 545, 545, 545, 598, 598, - 598, 598, 598, 598, 598, 76, 546, 598, 548, 548, - 548, 548, 548, 548, 548, 548, 545, 545, 545, 545, - 545, 545, 545, 545, 568, 569, 570, 568, 568, 568, - 568, 568, 546, 598, 547, 547, 547, 547, 547, 547, - 76, 546, 598, 549, 549, 549, 549, 549, 550, 547, - 547, 598, 598, 598, 598, 598, 76, 571, 572, 573, - - 571, 571, 571, 571, 571, 551, 76, 552, 552, 552, - 552, 552, 552, 552, 552, 76, 371, 598, 558, 558, - 558, 558, 558, 558, 558, 558, 522, 371, 598, 559, - 559, 559, 559, 559, 559, 559, 559, 598, 598, 598, - 598, 560, 560, 560, 560, 560, 551, 598, 552, 552, - 552, 552, 552, 552, 552, 552, 595, 595, 595, 595, - 595, 595, 598, 560, 560, 560, 560, 560, 560, 546, - 598, 547, 547, 547, 547, 547, 547, 547, 547, 551, - 598, 552, 552, 552, 552, 552, 552, 371, 76, 576, - 576, 576, 576, 576, 576, 576, 576, 598, 598, 598, - - 598, 598, 598, 76, 546, 598, 547, 547, 547, 547, - 547, 547, 547, 547, 585, 585, 585, 585, 585, 585, - 585, 585, 586, 586, 586, 586, 586, 586, 586, 586, - 587, 587, 587, 587, 587, 588, 585, 585, 76, 580, - 598, 581, 581, 581, 581, 581, 581, 581, 581, 598, - 598, 598, 592, 593, 594, 592, 592, 592, 592, 592, - 580, 598, 581, 581, 581, 581, 581, 581, 598, 598, - 598, 598, 598, 76, 580, 598, 582, 582, 582, 582, - 582, 582, 582, 582, 76, 585, 585, 585, 585, 585, - 585, 585, 585, 598, 76, 585, 585, 585, 585, 585, - - 585, 585, 585, 598, 598, 598, 598, 598, 76, 580, - 598, 583, 583, 583, 583, 583, 584, 581, 581, 598, - 598, 598, 595, 595, 595, 595, 595, 595, 595, 595, - 592, 592, 592, 592, 592, 592, 592, 592, 598, 598, - 598, 598, 598, 76, 580, 598, 581, 581, 581, 581, - 581, 581, 581, 581, 76, 598, 598, 598, 598, 598, - 598, 598, 76, 596, 596, 596, 596, 596, 597, 595, - 595, 598, 598, 598, 598, 598, 598, 598, 76, 580, - 598, 581, 581, 581, 581, 581, 581, 581, 581, 598, - 598, 598, 598, 598, 598, 76, 595, 595, 595, 595, - - 595, 595, 595, 595, 598, 598, 598, 598, 598, 598, - 598, 598, 598, 76, 598, 598, 598, 598, 598, 598, - 598, 598, 598, 598, 598, 598, 598, 598, 76, 54, - 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, - 54, 54, 54, 54, 54, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 31, 63, 63, 63, 63, 63, 63, 63, 63, 63, - 63, 63, 63, 63, 63, 63, 63, 70, 70, 70, - 70, 70, 70, 70, 70, 70, 70, 70, 70, 70, - 70, 70, 70, 75, 598, 598, 598, 598, 598, 598, - - 598, 75, 75, 75, 598, 598, 75, 75, 75, 79, - 79, 79, 79, 79, 79, 79, 79, 79, 79, 79, - 79, 79, 79, 79, 79, 83, 598, 598, 598, 598, - 83, 598, 598, 83, 83, 83, 83, 598, 83, 83, - 83, 87, 598, 598, 598, 598, 598, 598, 598, 87, - 87, 87, 598, 598, 87, 87, 87, 89, 598, 598, - 89, 89, 598, 89, 598, 89, 89, 89, 598, 598, - 89, 89, 89, 99, 99, 598, 598, 598, 99, 127, - 598, 598, 127, 127, 598, 127, 598, 127, 127, 127, - 598, 598, 127, 127, 127, 131, 598, 598, 131, 131, - - 598, 131, 598, 131, 131, 131, 598, 131, 598, 131, - 131, 139, 598, 598, 139, 598, 598, 139, 598, 139, - 139, 139, 139, 598, 139, 139, 139, 143, 143, 143, - 143, 143, 143, 143, 143, 143, 143, 143, 143, 143, - 143, 143, 143, 145, 145, 598, 145, 598, 145, 145, - 145, 145, 145, 145, 145, 145, 145, 145, 145, 151, - 151, 151, 151, 151, 151, 151, 151, 151, 151, 151, - 151, 151, 151, 151, 151, 152, 152, 598, 152, 152, - 152, 152, 152, 152, 152, 152, 152, 152, 152, 152, - 152, 155, 598, 598, 598, 598, 155, 598, 598, 155, - - 155, 155, 598, 598, 155, 155, 155, 90, 598, 598, - 90, 90, 598, 90, 598, 90, 90, 90, 598, 598, - 90, 90, 90, 163, 163, 598, 598, 598, 163, 165, - 165, 165, 598, 598, 598, 165, 128, 598, 598, 128, - 128, 598, 128, 598, 128, 128, 128, 598, 598, 128, - 128, 128, 191, 191, 191, 191, 191, 191, 191, 191, - 191, 191, 191, 191, 191, 191, 191, 191, 198, 198, - 598, 598, 598, 198, 204, 204, 204, 598, 598, 598, - 204, 234, 234, 598, 598, 598, 234, 235, 235, 598, - 598, 598, 235, 239, 239, 598, 598, 598, 239, 241, - - 241, 241, 598, 598, 598, 241, 277, 277, 598, 598, - 598, 277, 279, 279, 598, 598, 598, 279, 280, 280, - 598, 598, 598, 280, 282, 282, 282, 598, 598, 598, - 282, 286, 286, 286, 286, 598, 598, 598, 286, 317, - 317, 598, 598, 598, 317, 318, 318, 598, 598, 598, - 318, 319, 319, 598, 598, 598, 319, 331, 331, 331, - 598, 598, 598, 331, 332, 332, 332, 332, 598, 598, - 598, 332, 369, 369, 598, 598, 598, 369, 370, 370, - 598, 598, 598, 370, 386, 386, 386, 598, 598, 598, - 386, 387, 387, 387, 387, 598, 598, 598, 387, 416, - - 416, 598, 598, 598, 416, 420, 598, 420, 420, 598, - 598, 598, 420, 438, 438, 438, 598, 598, 598, 438, - 439, 439, 439, 439, 598, 598, 598, 439, 473, 473, - 598, 598, 598, 473, 474, 598, 474, 474, 598, 598, - 598, 474, 490, 490, 490, 598, 598, 598, 490, 491, - 491, 491, 598, 598, 598, 598, 491, 502, 502, 598, - 502, 502, 502, 598, 598, 502, 502, 502, 598, 598, - 502, 502, 502, 508, 508, 598, 508, 508, 508, 598, - 598, 508, 508, 508, 598, 598, 508, 508, 508, 518, - 518, 598, 598, 598, 518, 519, 598, 519, 519, 598, - - 598, 598, 519, 535, 535, 598, 598, 598, 598, 535, - 541, 541, 541, 541, 541, 541, 541, 541, 541, 541, - 541, 541, 541, 541, 541, 541, 556, 556, 598, 598, - 598, 556, 557, 598, 557, 557, 598, 598, 598, 557, - 574, 574, 598, 598, 598, 574, 575, 598, 575, 598, - 598, 598, 598, 575, 590, 590, 590, 590, 590, 590, - 590, 590, 590, 590, 590, 590, 590, 590, 590, 590, - 13, 598, 598, 598, 598, 598, 598, 598, 598, 598, - 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, - 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, - - 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, - 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, - 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, - 598, 598, 598, 598, 598, 598 - } ; - -static yyconst short int yy_chk[3737] = - { 0, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 2, 3, 4, 41, 2, - 3, 4, 11, 11, 11, 11, 3, 4, 53, 3, - 4, 49, 61, 61, 71, 41, 5, 5, 5, 72, - 5, 49, 20, 2, 2, 53, 5, 2, 117, 65, - - 595, 6, 6, 6, 2, 6, 67, 2, 5, 5, - 20, 6, 12, 12, 12, 12, 25, 25, 11, 118, - 25, 25, 65, 6, 6, 69, 69, 3, 4, 67, - 71, 118, 5, 72, 20, 85, 108, 108, 25, 27, - 27, 27, 27, 27, 27, 27, 27, 6, 7, 7, - 7, 42, 7, 74, 74, 117, 74, 590, 12, 100, - 25, 28, 28, 28, 28, 28, 28, 40, 100, 40, - 40, 40, 40, 40, 40, 40, 40, 85, 187, 42, - 42, 123, 108, 42, 98, 98, 98, 98, 98, 98, - 42, 123, 187, 42, 7, 7, 7, 7, 7, 7, - - 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, - 7, 7, 8, 8, 8, 50, 8, 579, 50, 50, - 50, 50, 50, 50, 50, 50, 81, 81, 81, 81, - 81, 81, 81, 81, 82, 82, 82, 82, 82, 82, - 82, 82, 84, 119, 121, 84, 84, 84, 84, 84, - 84, 84, 84, 133, 133, 186, 121, 186, 8, 8, - 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, - 8, 8, 8, 8, 8, 8, 9, 9, 9, 9, - 9, 137, 137, 110, 119, 9, 9, 9, 110, 120, - 500, 52, 52, 576, 83, 52, 52, 89, 89, 9, - - 130, 89, 89, 122, 120, 130, 59, 59, 59, 122, - 59, 147, 83, 52, 59, 148, 59, 144, 144, 89, - 149, 149, 9, 10, 10, 10, 10, 10, 59, 59, - 182, 193, 10, 10, 10, 52, 83, 86, 457, 86, - 86, 89, 165, 86, 86, 105, 10, 86, 185, 500, - 105, 165, 59, 105, 176, 105, 270, 147, 197, 148, - 86, 86, 155, 144, 185, 193, 270, 176, 189, 10, - 19, 92, 92, 92, 92, 92, 92, 92, 92, 182, - 19, 189, 197, 19, 19, 19, 19, 19, 19, 19, - 19, 26, 457, 26, 26, 26, 26, 26, 26, 26, - - 26, 26, 212, 92, 155, 26, 26, 26, 26, 26, - 96, 96, 96, 96, 96, 96, 96, 96, 183, 201, - 201, 201, 574, 183, 212, 26, 204, 26, 26, 26, - 26, 26, 26, 32, 140, 204, 213, 140, 140, 32, - 213, 560, 32, 32, 140, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 140, 360, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, - 32, 32, 32, 32, 32, 32, 32, 32, 34, 34, - - 34, 34, 34, 34, 34, 34, 34, 227, 227, 360, - 34, 34, 34, 34, 34, 97, 97, 97, 97, 97, - 97, 97, 97, 559, 196, 111, 196, 196, 196, 196, - 196, 196, 34, 34, 34, 34, 34, 34, 39, 39, - 39, 39, 39, 220, 39, 39, 157, 264, 39, 220, - 157, 229, 264, 111, 111, 226, 157, 111, 196, 230, - 39, 39, 39, 43, 111, 230, 229, 111, 157, 157, - 127, 127, 557, 43, 127, 127, 43, 43, 43, 43, - 43, 43, 43, 43, 125, 125, 125, 125, 125, 125, - 125, 125, 127, 136, 136, 136, 136, 136, 136, 136, - - 136, 153, 153, 153, 153, 153, 153, 153, 153, 310, - 226, 302, 556, 268, 127, 302, 228, 43, 60, 154, - 154, 154, 154, 154, 154, 154, 154, 269, 60, 254, - 301, 60, 60, 60, 60, 60, 60, 60, 60, 76, - 228, 76, 76, 76, 241, 76, 76, 269, 311, 76, - 188, 254, 301, 241, 188, 243, 243, 228, 311, 310, - 188, 76, 76, 76, 88, 243, 88, 88, 88, 552, - 88, 88, 188, 188, 88, 268, 192, 192, 192, 192, - 192, 192, 192, 192, 245, 245, 88, 88, 88, 91, - 362, 91, 91, 91, 245, 91, 91, 377, 377, 91, - - 156, 541, 156, 156, 271, 362, 156, 156, 192, 271, - 156, 91, 91, 91, 93, 93, 93, 93, 93, 93, - 93, 93, 156, 156, 156, 539, 93, 93, 93, 93, - 93, 200, 200, 200, 200, 200, 200, 200, 200, 200, - 205, 205, 205, 205, 205, 205, 205, 205, 93, 93, - 93, 93, 93, 93, 101, 101, 101, 101, 101, 101, - 101, 101, 409, 305, 409, 273, 101, 101, 101, 101, - 101, 207, 207, 207, 207, 207, 207, 207, 207, 208, - 208, 208, 208, 208, 208, 305, 282, 365, 101, 101, - 101, 101, 101, 101, 129, 282, 129, 129, 129, 273, - - 129, 129, 535, 210, 129, 210, 210, 210, 210, 210, - 210, 210, 210, 427, 427, 531, 129, 129, 129, 158, - 365, 158, 158, 158, 158, 158, 158, 158, 158, 236, - 236, 236, 236, 236, 236, 236, 236, 236, 242, 242, - 242, 242, 242, 242, 242, 242, 251, 251, 251, 251, - 251, 251, 519, 158, 159, 518, 159, 159, 159, 159, - 159, 159, 159, 159, 244, 244, 244, 244, 244, 244, - 244, 244, 248, 248, 248, 248, 248, 248, 248, 248, - 501, 286, 248, 499, 408, 408, 306, 498, 159, 160, - 286, 160, 160, 160, 160, 160, 160, 160, 160, 250, - - 250, 250, 250, 250, 250, 250, 250, 253, 306, 253, - 253, 253, 253, 253, 253, 253, 253, 296, 296, 296, - 296, 296, 296, 160, 161, 307, 161, 161, 161, 161, - 161, 161, 161, 161, 307, 408, 312, 347, 161, 161, - 161, 161, 161, 272, 272, 272, 272, 272, 272, 272, - 272, 276, 312, 276, 276, 276, 276, 276, 276, 347, - 161, 161, 161, 161, 161, 161, 164, 164, 164, 164, - 164, 164, 164, 164, 164, 272, 441, 441, 164, 164, - 164, 164, 164, 462, 283, 276, 283, 283, 283, 283, - 283, 283, 283, 283, 323, 323, 323, 323, 323, 323, - - 164, 164, 164, 164, 164, 164, 166, 166, 166, 166, - 166, 166, 166, 166, 166, 166, 313, 462, 353, 166, - 166, 166, 166, 166, 284, 313, 284, 284, 284, 284, - 284, 284, 284, 284, 342, 342, 342, 342, 342, 342, - 353, 166, 166, 166, 166, 166, 166, 167, 167, 167, - 167, 167, 167, 167, 167, 287, 287, 497, 355, 167, - 167, 167, 167, 167, 285, 287, 285, 285, 285, 285, - 285, 285, 285, 285, 442, 442, 445, 445, 288, 288, - 355, 167, 167, 167, 167, 167, 167, 194, 288, 194, - 194, 194, 194, 194, 194, 194, 194, 289, 289, 289, - - 289, 289, 289, 289, 289, 290, 290, 293, 293, 293, - 293, 293, 293, 293, 293, 290, 496, 293, 481, 481, - 491, 194, 195, 474, 195, 195, 195, 195, 195, 195, - 195, 195, 295, 295, 295, 295, 295, 295, 295, 295, - 298, 331, 298, 298, 298, 298, 298, 298, 298, 298, - 331, 473, 357, 363, 492, 492, 195, 206, 206, 206, - 206, 206, 206, 206, 206, 206, 206, 206, 357, 363, - 403, 206, 206, 206, 206, 206, 320, 320, 320, 320, - 320, 320, 320, 320, 322, 322, 322, 322, 322, 322, - 322, 322, 403, 206, 206, 206, 206, 206, 206, 209, - - 209, 209, 209, 209, 209, 209, 209, 209, 209, 332, - 469, 404, 209, 209, 209, 209, 209, 325, 332, 325, - 325, 325, 325, 325, 325, 325, 325, 526, 526, 543, - 543, 333, 333, 404, 209, 209, 209, 209, 209, 209, - 231, 333, 231, 231, 231, 231, 231, 231, 231, 231, - 326, 326, 326, 326, 326, 326, 326, 326, 328, 361, - 328, 328, 328, 328, 328, 328, 328, 328, 361, 467, - 547, 467, 467, 467, 231, 232, 372, 232, 232, 232, - 232, 232, 232, 232, 232, 329, 372, 329, 329, 329, - 329, 329, 329, 329, 329, 330, 374, 330, 330, 330, - - 330, 330, 330, 467, 547, 454, 374, 563, 563, 232, - 233, 449, 233, 233, 233, 233, 233, 233, 233, 233, - 334, 334, 335, 335, 335, 335, 335, 335, 335, 335, - 334, 336, 336, 339, 339, 339, 339, 339, 339, 339, - 339, 336, 448, 339, 233, 246, 246, 246, 246, 246, - 246, 246, 246, 246, 246, 246, 249, 249, 249, 249, - 249, 249, 249, 249, 249, 249, 249, 447, 458, 446, - 249, 249, 249, 249, 249, 341, 341, 341, 341, 341, - 341, 341, 341, 458, 368, 368, 368, 368, 368, 368, - 368, 446, 249, 249, 249, 249, 249, 249, 252, 252, - - 252, 252, 252, 252, 252, 252, 252, 252, 611, 611, - 450, 252, 252, 252, 252, 252, 344, 368, 344, 344, - 344, 344, 344, 344, 344, 344, 380, 380, 380, 380, - 380, 380, 450, 252, 252, 252, 252, 252, 252, 274, - 386, 274, 274, 274, 274, 274, 274, 274, 274, 386, - 452, 434, 364, 364, 364, 364, 364, 364, 364, 364, - 371, 371, 371, 371, 371, 371, 371, 371, 420, 416, - 661, 411, 452, 274, 275, 661, 275, 275, 275, 275, - 275, 275, 275, 275, 364, 373, 373, 373, 373, 373, - 373, 373, 373, 379, 379, 379, 379, 379, 379, 379, - - 379, 397, 397, 397, 397, 397, 397, 407, 275, 281, - 281, 281, 281, 281, 281, 281, 281, 281, 387, 406, - 493, 281, 281, 281, 281, 281, 382, 387, 382, 382, - 382, 382, 382, 382, 382, 382, 430, 430, 430, 430, - 430, 430, 493, 281, 281, 281, 281, 281, 281, 291, - 291, 291, 291, 291, 291, 291, 291, 291, 291, 291, - 294, 294, 294, 294, 294, 294, 294, 294, 294, 294, - 294, 455, 405, 495, 294, 294, 294, 294, 294, 383, - 421, 383, 383, 383, 383, 383, 383, 383, 383, 402, - 421, 455, 536, 455, 455, 495, 294, 294, 294, 294, - - 294, 294, 297, 297, 297, 297, 297, 297, 297, 297, - 297, 297, 538, 564, 536, 297, 297, 297, 297, 297, - 384, 422, 384, 384, 384, 384, 384, 384, 384, 384, - 401, 422, 400, 581, 538, 564, 399, 297, 297, 297, - 297, 297, 297, 314, 314, 314, 314, 314, 314, 314, - 314, 314, 385, 370, 385, 385, 385, 385, 385, 385, - 385, 385, 388, 388, 389, 389, 438, 581, 369, 359, - 358, 352, 388, 351, 389, 438, 314, 315, 315, 315, - 315, 315, 315, 315, 315, 315, 390, 390, 390, 390, - 390, 390, 390, 390, 391, 391, 394, 394, 394, 394, - - 394, 394, 394, 394, 391, 350, 394, 349, 346, 345, - 315, 316, 316, 316, 316, 316, 316, 316, 316, 316, - 396, 396, 396, 396, 396, 396, 396, 396, 398, 424, - 398, 398, 398, 398, 398, 398, 398, 398, 327, 424, - 319, 318, 317, 309, 316, 321, 308, 321, 321, 321, - 321, 321, 321, 321, 321, 321, 439, 566, 577, 321, - 321, 321, 321, 321, 417, 439, 417, 417, 417, 417, - 417, 417, 417, 417, 459, 304, 459, 459, 459, 566, - 577, 321, 321, 321, 321, 321, 321, 324, 324, 324, - 324, 324, 324, 324, 324, 324, 303, 300, 299, 324, - - 324, 324, 324, 324, 418, 475, 418, 418, 418, 418, - 418, 418, 418, 418, 280, 475, 279, 278, 277, 267, - 459, 324, 324, 324, 324, 324, 324, 337, 337, 337, - 337, 337, 337, 337, 337, 337, 337, 337, 340, 340, - 340, 340, 340, 340, 340, 340, 340, 340, 340, 490, - 266, 265, 340, 340, 340, 340, 340, 419, 490, 419, - 419, 419, 419, 419, 419, 419, 419, 263, 460, 410, - 460, 460, 460, 262, 340, 340, 340, 340, 340, 340, - 343, 343, 343, 343, 343, 343, 343, 343, 343, 410, - 261, 410, 410, 343, 343, 343, 343, 343, 423, 423, - - 423, 423, 423, 423, 423, 423, 484, 484, 484, 484, - 484, 484, 260, 410, 460, 343, 343, 343, 343, 343, - 343, 366, 366, 366, 366, 366, 366, 366, 366, 366, - 429, 429, 429, 429, 429, 429, 429, 429, 432, 476, - 432, 432, 432, 432, 432, 432, 432, 432, 259, 476, - 514, 514, 514, 258, 366, 367, 367, 367, 367, 367, - 367, 367, 367, 367, 433, 433, 433, 433, 433, 433, - 433, 433, 435, 478, 435, 435, 435, 435, 435, 435, - 435, 435, 514, 478, 257, 256, 240, 239, 367, 375, - 238, 375, 375, 375, 375, 375, 375, 375, 375, 375, - - 378, 520, 378, 378, 378, 378, 378, 378, 378, 378, - 378, 520, 237, 235, 378, 378, 378, 378, 378, 436, - 521, 436, 436, 436, 436, 436, 436, 436, 436, 502, - 521, 502, 502, 502, 234, 225, 378, 378, 378, 378, - 378, 378, 381, 381, 381, 381, 381, 381, 381, 381, - 381, 224, 223, 222, 381, 381, 381, 381, 381, 437, - 221, 437, 437, 437, 437, 437, 437, 468, 468, 468, - 468, 468, 468, 468, 468, 502, 381, 381, 381, 381, - 381, 381, 392, 392, 392, 392, 392, 392, 392, 392, - 392, 392, 392, 395, 395, 395, 395, 395, 395, 395, - - 395, 395, 395, 440, 440, 456, 456, 395, 395, 395, - 395, 395, 219, 440, 218, 567, 567, 523, 456, 461, - 461, 461, 461, 461, 461, 461, 461, 523, 567, 395, - 395, 395, 395, 395, 395, 412, 558, 412, 412, 412, - 412, 412, 412, 412, 412, 217, 558, 216, 215, 214, - 470, 461, 470, 470, 470, 470, 470, 470, 470, 470, - 472, 211, 472, 472, 472, 472, 472, 472, 203, 412, - 413, 202, 413, 413, 413, 413, 413, 413, 413, 413, - 471, 199, 471, 471, 471, 471, 471, 471, 471, 471, - 477, 477, 477, 477, 477, 477, 477, 477, 529, 529, - - 529, 529, 529, 529, 413, 414, 198, 414, 414, 414, - 414, 414, 414, 414, 414, 483, 483, 483, 483, 483, - 483, 483, 483, 486, 191, 486, 486, 486, 486, 486, - 486, 486, 486, 588, 588, 588, 588, 588, 588, 414, - 415, 190, 415, 415, 415, 415, 415, 415, 415, 415, - 487, 487, 487, 487, 487, 487, 487, 487, 487, 488, - 488, 488, 488, 488, 488, 488, 488, 488, 503, 184, - 503, 503, 503, 181, 415, 425, 180, 425, 425, 425, - 425, 425, 425, 425, 425, 425, 428, 179, 428, 428, - 428, 428, 428, 428, 428, 428, 428, 178, 177, 175, - - 428, 428, 428, 428, 428, 489, 489, 489, 489, 489, - 489, 489, 489, 489, 503, 504, 174, 504, 504, 504, - 173, 172, 428, 428, 428, 428, 428, 428, 431, 431, - 431, 431, 431, 431, 431, 431, 431, 171, 170, 169, - 431, 431, 431, 431, 431, 505, 168, 505, 505, 505, - 506, 163, 162, 506, 506, 506, 506, 506, 506, 506, - 506, 504, 431, 431, 431, 431, 431, 431, 443, 443, - 443, 443, 443, 443, 443, 443, 443, 443, 463, 152, - 463, 463, 463, 463, 463, 463, 463, 463, 507, 507, - 151, 505, 507, 508, 150, 508, 508, 508, 146, 145, - - 143, 139, 132, 128, 507, 507, 507, 509, 509, 126, - 124, 509, 463, 464, 116, 464, 464, 464, 464, 464, - 464, 464, 464, 509, 509, 509, 513, 513, 513, 513, - 513, 513, 513, 513, 115, 114, 113, 112, 107, 508, - 534, 534, 534, 534, 534, 534, 534, 464, 465, 106, - 465, 465, 465, 465, 465, 465, 465, 465, 513, 515, - 104, 515, 515, 515, 515, 515, 515, 515, 515, 516, - 103, 516, 516, 516, 516, 516, 516, 516, 516, 99, - 95, 94, 465, 466, 90, 466, 466, 466, 466, 466, - 466, 466, 466, 517, 87, 517, 517, 517, 517, 517, - - 517, 517, 517, 522, 522, 522, 522, 522, 522, 522, - 522, 79, 78, 77, 75, 70, 63, 466, 479, 56, - 479, 479, 479, 479, 479, 479, 479, 479, 479, 482, - 51, 482, 482, 482, 482, 482, 482, 482, 482, 482, - 48, 47, 46, 482, 482, 482, 482, 482, 528, 528, - 528, 528, 528, 528, 528, 528, 532, 532, 532, 532, - 532, 532, 532, 532, 532, 482, 482, 482, 482, 482, - 482, 485, 485, 485, 485, 485, 485, 485, 485, 45, - 44, 38, 37, 485, 485, 485, 485, 485, 530, 36, - 530, 530, 530, 530, 530, 530, 530, 530, 35, 33, - - 29, 23, 17, 15, 14, 485, 485, 485, 485, 485, - 485, 510, 13, 510, 510, 510, 510, 510, 510, 510, - 510, 533, 533, 533, 533, 533, 533, 533, 533, 533, - 544, 544, 544, 544, 544, 544, 544, 544, 0, 0, - 0, 0, 0, 0, 0, 510, 511, 0, 511, 511, - 511, 511, 511, 511, 511, 511, 545, 545, 545, 545, - 545, 545, 545, 545, 546, 546, 546, 546, 546, 546, - 546, 546, 550, 0, 550, 550, 550, 550, 550, 550, - 511, 512, 0, 512, 512, 512, 512, 512, 512, 512, - 512, 0, 0, 0, 0, 0, 546, 551, 551, 551, - - 551, 551, 551, 551, 551, 553, 550, 553, 553, 553, - 553, 553, 553, 553, 553, 512, 524, 0, 524, 524, - 524, 524, 524, 524, 524, 524, 524, 527, 0, 527, - 527, 527, 527, 527, 527, 527, 527, 0, 0, 0, - 0, 527, 527, 527, 527, 527, 554, 0, 554, 554, - 554, 554, 554, 554, 554, 554, 597, 597, 597, 597, - 597, 597, 0, 527, 527, 527, 527, 527, 527, 548, - 0, 548, 548, 548, 548, 548, 548, 548, 548, 555, - 0, 555, 555, 555, 555, 555, 555, 561, 597, 561, - 561, 561, 561, 561, 561, 561, 561, 0, 0, 0, - - 0, 0, 0, 548, 549, 0, 549, 549, 549, 549, - 549, 549, 549, 549, 571, 571, 571, 571, 571, 571, - 571, 571, 572, 572, 572, 572, 572, 572, 572, 572, - 573, 573, 573, 573, 573, 573, 573, 573, 549, 568, - 0, 568, 568, 568, 568, 568, 568, 568, 568, 0, - 0, 0, 580, 580, 580, 580, 580, 580, 580, 580, - 584, 0, 584, 584, 584, 584, 584, 584, 0, 0, - 0, 0, 0, 568, 569, 0, 569, 569, 569, 569, - 569, 569, 569, 569, 580, 586, 586, 586, 586, 586, - 586, 586, 586, 0, 584, 587, 587, 587, 587, 587, - - 587, 587, 587, 0, 0, 0, 0, 0, 569, 570, - 0, 570, 570, 570, 570, 570, 570, 570, 570, 0, - 0, 0, 592, 592, 592, 592, 592, 592, 592, 592, - 593, 593, 593, 593, 593, 593, 593, 593, 0, 0, - 0, 0, 0, 570, 582, 0, 582, 582, 582, 582, - 582, 582, 582, 582, 592, 0, 0, 0, 0, 0, - 0, 0, 593, 594, 594, 594, 594, 594, 594, 594, - 594, 0, 0, 0, 0, 0, 0, 0, 582, 583, - 0, 583, 583, 583, 583, 583, 583, 583, 583, 0, - 0, 0, 0, 0, 0, 594, 596, 596, 596, 596, - - 596, 596, 596, 596, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 583, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 596, 599, - 599, 599, 599, 599, 599, 599, 599, 599, 599, 599, - 599, 599, 599, 599, 599, 600, 600, 600, 600, 600, - 600, 600, 600, 600, 600, 600, 600, 600, 600, 600, - 600, 601, 601, 601, 601, 601, 601, 601, 601, 601, - 601, 601, 601, 601, 601, 601, 601, 602, 602, 602, - 602, 602, 602, 602, 602, 602, 602, 602, 602, 602, - 602, 602, 602, 603, 0, 0, 0, 0, 0, 0, - - 0, 603, 603, 603, 0, 0, 603, 603, 603, 604, - 604, 604, 604, 604, 604, 604, 604, 604, 604, 604, - 604, 604, 604, 604, 604, 605, 0, 0, 0, 0, - 605, 0, 0, 605, 605, 605, 605, 0, 605, 605, - 605, 606, 0, 0, 0, 0, 0, 0, 0, 606, - 606, 606, 0, 0, 606, 606, 606, 607, 0, 0, - 607, 607, 0, 607, 0, 607, 607, 607, 0, 0, - 607, 607, 607, 608, 608, 0, 0, 0, 608, 609, - 0, 0, 609, 609, 0, 609, 0, 609, 609, 609, - 0, 0, 609, 609, 609, 610, 0, 0, 610, 610, - - 0, 610, 0, 610, 610, 610, 0, 610, 0, 610, - 610, 612, 0, 0, 612, 0, 0, 612, 0, 612, - 612, 612, 612, 0, 612, 612, 612, 613, 613, 613, - 613, 613, 613, 613, 613, 613, 613, 613, 613, 613, - 613, 613, 613, 614, 614, 0, 614, 0, 614, 614, - 614, 614, 614, 614, 614, 614, 614, 614, 614, 615, - 615, 615, 615, 615, 615, 615, 615, 615, 615, 615, - 615, 615, 615, 615, 615, 616, 616, 0, 616, 616, - 616, 616, 616, 616, 616, 616, 616, 616, 616, 616, - 616, 617, 0, 0, 0, 0, 617, 0, 0, 617, - - 617, 617, 0, 0, 617, 617, 617, 618, 0, 0, - 618, 618, 0, 618, 0, 618, 618, 618, 0, 0, - 618, 618, 618, 619, 619, 0, 0, 0, 619, 620, - 620, 620, 0, 0, 0, 620, 621, 0, 0, 621, - 621, 0, 621, 0, 621, 621, 621, 0, 0, 621, - 621, 621, 622, 622, 622, 622, 622, 622, 622, 622, - 622, 622, 622, 622, 622, 622, 622, 622, 623, 623, - 0, 0, 0, 623, 624, 624, 624, 0, 0, 0, - 624, 625, 625, 0, 0, 0, 625, 626, 626, 0, - 0, 0, 626, 627, 627, 0, 0, 0, 627, 628, - - 628, 628, 0, 0, 0, 628, 629, 629, 0, 0, - 0, 629, 630, 630, 0, 0, 0, 630, 631, 631, - 0, 0, 0, 631, 632, 632, 632, 0, 0, 0, - 632, 633, 633, 633, 633, 0, 0, 0, 633, 634, - 634, 0, 0, 0, 634, 635, 635, 0, 0, 0, - 635, 636, 636, 0, 0, 0, 636, 637, 637, 637, - 0, 0, 0, 637, 638, 638, 638, 638, 0, 0, - 0, 638, 639, 639, 0, 0, 0, 639, 640, 640, - 0, 0, 0, 640, 641, 641, 641, 0, 0, 0, - 641, 642, 642, 642, 642, 0, 0, 0, 642, 643, - - 643, 0, 0, 0, 643, 644, 0, 644, 644, 0, - 0, 0, 644, 645, 645, 645, 0, 0, 0, 645, - 646, 646, 646, 646, 0, 0, 0, 646, 647, 647, - 0, 0, 0, 647, 648, 0, 648, 648, 0, 0, - 0, 648, 649, 649, 649, 0, 0, 0, 649, 650, - 650, 650, 0, 0, 0, 0, 650, 651, 651, 0, - 651, 651, 651, 0, 0, 651, 651, 651, 0, 0, - 651, 651, 651, 652, 652, 0, 652, 652, 652, 0, - 0, 652, 652, 652, 0, 0, 652, 652, 652, 653, - 653, 0, 0, 0, 653, 654, 0, 654, 654, 0, - - 0, 0, 654, 655, 655, 0, 0, 0, 0, 655, - 656, 656, 656, 656, 656, 656, 656, 656, 656, 656, - 656, 656, 656, 656, 656, 656, 657, 657, 0, 0, - 0, 657, 658, 0, 658, 658, 0, 0, 0, 658, - 659, 659, 0, 0, 0, 659, 660, 0, 660, 0, - 0, 0, 0, 660, 662, 662, 662, 662, 662, 662, - 662, 662, 662, 662, 662, 662, 662, 662, 662, 662, - 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, - 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, - 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, - - 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, - 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, - 598, 598, 598, 598, 598, 598, 598, 598, 598, 598, - 598, 598, 598, 598, 598, 598 - } ; - -static yy_state_type yy_last_accepting_state; -static char *yy_last_accepting_cpos; - -/* The intent behind this definition is that it'll catch - * any uses of REJECT which flex missed. - */ -#define REJECT reject_used_but_not_detected -#define yymore() yymore_used_but_not_detected -#define YY_MORE_ADJ 0 -#define YY_RESTORE_YY_MORE_OFFSET -char *yytext; -#line 1 "toke.l" -#define INITIAL 0 -#line 2 "toke.l" -/* - * Copyright (c) 1996, 1998-2005, 2007-2010 - * Todd C. Miller - * - * Permission to use, copy, modify, and distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR - * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF - * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * Sponsored in part by the Defense Advanced Research Projects - * Agency (DARPA) and Air Force Research Laboratory, Air Force - * Materiel Command, USAF, under agreement number F39502-99-1-0512. - */ - -#include - -#include -#include -#include -#include -#ifdef STDC_HEADERS -# include -# include -#else -# ifdef HAVE_STDLIB_H -# include -# endif -#endif /* STDC_HEADERS */ -#ifdef HAVE_STRING_H -# include -#endif /* HAVE_STRING_H */ -#ifdef HAVE_STRINGS_H -# include -#endif /* HAVE_STRINGS_H */ -#ifdef HAVE_UNISTD_H -# include -#endif /* HAVE_UNISTD_H */ -#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS) -# include -#endif /* HAVE_MALLOC_H && !STDC_HEADERS */ -#ifdef HAVE_DIRENT_H -# include -# define NAMLEN(dirent) strlen((dirent)->d_name) -#else -# define dirent direct -# define NAMLEN(dirent) (dirent)->d_namlen -# ifdef HAVE_SYS_NDIR_H -# include -# endif -# ifdef HAVE_SYS_DIR_H -# include -# endif -# ifdef HAVE_NDIR_H -# include -# endif -#endif -#include -#include -#include "sudo.h" -#include "parse.h" -#include "toke.h" -#include - -extern YYSTYPE yylval; -extern int parse_error; -int sudolineno; -char *sudoers; - -static int continued, prev_state, sawspace; - -static int _push_include __P((char *, int)); -static int pop_include __P((void)); -static char *parse_include __P((char *)); - -#define fill(a, b) fill_txt(a, b, 0) - -#define push_include(_p) (_push_include((_p), FALSE)) -#define push_includedir(_p) (_push_include((_p), TRUE)) - -#ifdef TRACELEXER -#define LEXTRACE(msg) fputs(msg, stderr) -#else -#define LEXTRACE(msg) -#endif -#define YY_NO_INPUT 1 -#define YY_NO_UNPUT 1 -#define GOTDEFS 1 - -#define GOTCMND 2 - -#define STARTDEFS 3 - -#define INDEFS 4 - -#define INSTR 5 - -#line 1511 "lex.yy.c" - -/* Macros after this point can all be overridden by user definitions in - * section 1. - */ - -#ifndef YY_SKIP_YYWRAP -#ifdef __cplusplus -extern "C" int yywrap YY_PROTO(( void )); -#else -extern int yywrap YY_PROTO(( void )); -#endif -#endif - -#ifndef YY_NO_UNPUT -static void yyunput YY_PROTO(( int c, char *buf_ptr )); -#endif - -#ifndef yytext_ptr -static void yy_flex_strncpy YY_PROTO(( char *, yyconst char *, int )); -#endif - -#ifdef YY_NEED_STRLEN -static int yy_flex_strlen YY_PROTO(( yyconst char * )); -#endif - -#ifndef YY_NO_INPUT -#ifdef __cplusplus -static int yyinput YY_PROTO(( void )); -#else -static int input YY_PROTO(( void )); -#endif -#endif - -#if defined(YY_STACK_USED) && YY_STACK_USED -static int yy_start_stack_ptr = 0; -static int yy_start_stack_depth = 0; -static int *yy_start_stack = 0; -#ifndef YY_NO_PUSH_STATE -static void yy_push_state YY_PROTO(( int new_state )); -#endif -#ifndef YY_NO_POP_STATE -static void yy_pop_state YY_PROTO(( void )); -#endif -#ifndef YY_NO_TOP_STATE -static int yy_top_state YY_PROTO(( void )); -#endif - -#else -#define YY_NO_PUSH_STATE 1 -#define YY_NO_POP_STATE 1 -#define YY_NO_TOP_STATE 1 -#endif - -#ifdef YY_MALLOC_DECL -YY_MALLOC_DECL -#else -#ifdef __STDC__ -#ifndef __cplusplus -#include -#endif -#else -/* Just try to get by without declaring the routines. This will fail - * miserably on non-ANSI systems for which sizeof(size_t) != sizeof(int) - * or sizeof(void*) != sizeof(int). - */ -#endif -#endif - -/* Amount of stuff to slurp up with each read. */ -#ifndef YY_READ_BUF_SIZE -#define YY_READ_BUF_SIZE 8192 -#endif - -/* Copy whatever the last rule matched to the standard output. */ - -#ifndef ECHO -/* This used to be an fputs(), but since the string might contain NUL's, - * we now use fwrite(). - */ -#define ECHO (void) fwrite( yytext, yyleng, 1, yyout ) -#endif - -/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL, - * is returned in "result". - */ -#ifndef YY_INPUT -#define YY_INPUT(buf,result,max_size) \ - if ( yy_current_buffer->yy_is_interactive ) \ - { \ - int c = '*', n; \ - for ( n = 0; n < max_size && \ - (c = getc( yyin )) != EOF && c != '\n'; ++n ) \ - buf[n] = (char) c; \ - if ( c == '\n' ) \ - buf[n++] = (char) c; \ - if ( c == EOF && ferror( yyin ) ) \ - YY_FATAL_ERROR( "input in flex scanner failed" ); \ - result = n; \ - } \ - else if ( ((result = fread( buf, 1, max_size, yyin )) == 0) \ - && ferror( yyin ) ) \ - YY_FATAL_ERROR( "input in flex scanner failed" ); -#endif - -/* No semi-colon after return; correct usage is to write "yyterminate();" - - * we don't want an extra ';' after the "return" because that will cause - * some compilers to complain about unreachable statements. - */ -#ifndef yyterminate -#define yyterminate() return YY_NULL -#endif - -/* Number of entries by which start-condition stack grows. */ -#ifndef YY_START_STACK_INCR -#define YY_START_STACK_INCR 25 -#endif - -/* Report a fatal error. */ -#ifndef YY_FATAL_ERROR -#define YY_FATAL_ERROR(msg) yy_fatal_error( msg ) -#endif - -/* Default declaration of generated scanner - a define so the user can - * easily add parameters. - */ -#ifndef YY_DECL -#define YY_DECL int yylex YY_PROTO(( void )) -#endif - -/* Code executed at the beginning of each rule, after yytext and yyleng - * have been set up. - */ -#ifndef YY_USER_ACTION -#define YY_USER_ACTION -#endif - -/* Code executed at the end of each rule. */ -#ifndef YY_BREAK -#define YY_BREAK break; -#endif - -#define YY_RULE_SETUP \ - if ( yyleng > 0 ) \ - yy_current_buffer->yy_at_bol = \ - (yytext[yyleng - 1] == '\n'); \ - YY_USER_ACTION - -YY_DECL - { - register yy_state_type yy_current_state; - register char *yy_cp, *yy_bp; - register int yy_act; - -#line 120 "toke.l" - -#line 1667 "lex.yy.c" - - if ( yy_init ) - { - yy_init = 0; - -#ifdef YY_USER_INIT - YY_USER_INIT; -#endif - - if ( ! yy_start ) - yy_start = 1; /* first start state */ - - if ( ! yyin ) - yyin = stdin; - - if ( ! yyout ) - yyout = stdout; - - if ( ! yy_current_buffer ) - yy_current_buffer = - yy_create_buffer( yyin, YY_BUF_SIZE ); - - yy_load_buffer_state(); - } - - while ( 1 ) /* loops until end-of-file is reached */ - { - yy_cp = yy_c_buf_p; - - /* Support of yytext. */ - *yy_cp = yy_hold_char; - - /* yy_bp points to the position in yy_ch_buf of the start of - * the current run. - */ - yy_bp = yy_cp; - - yy_current_state = yy_start; - yy_current_state += YY_AT_BOL(); -yy_match: - do - { - register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)]; - if ( yy_accept[yy_current_state] ) - { - yy_last_accepting_state = yy_current_state; - yy_last_accepting_cpos = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 599 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - ++yy_cp; - } - while ( yy_base[yy_current_state] != 3671 ); - -yy_find_action: - yy_act = yy_accept[yy_current_state]; - if ( yy_act == 0 ) - { /* have to back up */ - yy_cp = yy_last_accepting_cpos; - yy_current_state = yy_last_accepting_state; - yy_act = yy_accept[yy_current_state]; - } - - YY_DO_BEFORE_ACTION; - - -do_action: /* This label is used only to access EOF actions. */ - - - switch ( yy_act ) - { /* beginning of action switch */ - case 0: /* must back up */ - /* undo the effects of YY_DO_BEFORE_ACTION */ - *yy_cp = yy_hold_char; - yy_cp = yy_last_accepting_cpos; - yy_current_state = yy_last_accepting_state; - goto yy_find_action; - -case 1: -YY_RULE_SETUP -#line 121 "toke.l" -{ - LEXTRACE(", "); - return ','; - } /* return ',' */ - YY_BREAK -case 2: -YY_RULE_SETUP -#line 126 "toke.l" -BEGIN STARTDEFS; - YY_BREAK -case 3: -YY_RULE_SETUP -#line 128 "toke.l" -{ - BEGIN INDEFS; - LEXTRACE("DEFVAR "); - if (!fill(yytext, yyleng)) - yyterminate(); - return DEFVAR; - } - YY_BREAK - -case 4: -YY_RULE_SETUP -#line 137 "toke.l" -{ - BEGIN STARTDEFS; - LEXTRACE(", "); - return ','; - } /* return ',' */ - YY_BREAK -case 5: -YY_RULE_SETUP -#line 143 "toke.l" -{ - LEXTRACE("= "); - return '='; - } /* return '=' */ - YY_BREAK -case 6: -YY_RULE_SETUP -#line 148 "toke.l" -{ - LEXTRACE("+= "); - return '+'; - } /* return '+' */ - YY_BREAK -case 7: -YY_RULE_SETUP -#line 153 "toke.l" -{ - LEXTRACE("-= "); - return '-'; - } /* return '-' */ - YY_BREAK -case 8: -YY_RULE_SETUP -#line 158 "toke.l" -{ - LEXTRACE("BEGINSTR "); - yylval.string = NULL; - prev_state = YY_START; - BEGIN INSTR; - } - YY_BREAK -case 9: -YY_RULE_SETUP -#line 165 "toke.l" -{ - LEXTRACE("WORD(2) "); - if (!fill(yytext, yyleng)) - yyterminate(); - return WORD; - } - YY_BREAK - - -case 10: -YY_RULE_SETUP -#line 174 "toke.l" -{ - /* Line continuation char followed by newline. */ - ++sudolineno; - continued = TRUE; - } - YY_BREAK -case 11: -YY_RULE_SETUP -#line 180 "toke.l" -{ - LEXTRACE("ENDSTR "); - BEGIN prev_state; - - if (yylval.string == NULL) { - LEXTRACE("ERROR "); /* empty string */ - return ERROR; - } - if (prev_state == INITIAL) { - switch (yylval.string[0]) { - case '%': - if (yylval.string[1] == '\0' || - (yylval.string[1] == ':' && - yylval.string[2] == '\0')) { - LEXTRACE("ERROR "); /* empty group */ - return ERROR; - } - LEXTRACE("USERGROUP "); - return USERGROUP; - case '+': - if (yylval.string[1] == '\0') { - LEXTRACE("ERROR "); /* empty netgroup */ - return ERROR; - } - LEXTRACE("NETGROUP "); - return NETGROUP; - } - } - LEXTRACE("WORD(4) "); - return WORD; - } - YY_BREAK -case 12: -YY_RULE_SETUP -#line 212 "toke.l" -{ - LEXTRACE("BACKSLASH "); - if (!append(yytext, yyleng)) - yyterminate(); - } - YY_BREAK -case 13: -YY_RULE_SETUP -#line 218 "toke.l" -{ - LEXTRACE("STRBODY "); - if (!append(yytext, yyleng)) - yyterminate(); - } - YY_BREAK - - -case 14: -YY_RULE_SETUP -#line 226 "toke.l" -{ - /* quoted fnmatch glob char, pass verbatim */ - LEXTRACE("QUOTEDCHAR "); - if (!fill_args(yytext, 2, sawspace)) - yyterminate(); - sawspace = FALSE; - } - YY_BREAK -case 15: -YY_RULE_SETUP -#line 234 "toke.l" -{ - /* quoted sudoers special char, strip backslash */ - LEXTRACE("QUOTEDCHAR "); - if (!fill_args(yytext + 1, 1, sawspace)) - yyterminate(); - sawspace = FALSE; - } - YY_BREAK -case 16: -YY_RULE_SETUP -#line 242 "toke.l" -{ - BEGIN INITIAL; - yyless(0); - return COMMAND; - } /* end of command line args */ - YY_BREAK -case 17: -YY_RULE_SETUP -#line 248 "toke.l" -{ - LEXTRACE("ARG "); - if (!fill_args(yytext, yyleng, sawspace)) - yyterminate(); - sawspace = FALSE; - } /* a command line arg */ - YY_BREAK - -case 18: -YY_RULE_SETUP -#line 256 "toke.l" -{ - char *path; - - if (continued) { - LEXTRACE("ERROR "); - return ERROR; - } - - if ((path = parse_include(yytext)) == NULL) - yyterminate(); - - LEXTRACE("INCLUDE\n"); - - /* Push current buffer and switch to include file */ - if (!push_include(path)) - yyterminate(); - } - YY_BREAK -case 19: -YY_RULE_SETUP -#line 274 "toke.l" -{ - char *path; - - if (continued) { - LEXTRACE("ERROR "); - return ERROR; - } - - if ((path = parse_include(yytext)) == NULL) - yyterminate(); - - LEXTRACE("INCLUDEDIR\n"); - - /* - * Push current buffer and switch to include file. - * We simply ignore empty directories. - */ - if (!push_includedir(path) && parse_error) - yyterminate(); - } - YY_BREAK -case 20: -YY_RULE_SETUP -#line 295 "toke.l" -{ - char deftype; - int n; - - if (continued) { - LEXTRACE("ERROR "); - return ERROR; - } - - for (n = 0; isblank((unsigned char)yytext[n]); n++) - continue; - n += sizeof("Defaults") - 1; - if ((deftype = yytext[n++]) != '\0') { - while (isblank((unsigned char)yytext[n])) - n++; - } - BEGIN GOTDEFS; - switch (deftype) { - case ':': - yyless(n); - LEXTRACE("DEFAULTS_USER "); - return DEFAULTS_USER; - case '>': - yyless(n); - LEXTRACE("DEFAULTS_RUNAS "); - return DEFAULTS_RUNAS; - case '@': - yyless(n); - LEXTRACE("DEFAULTS_HOST "); - return DEFAULTS_HOST; - case '!': - yyless(n); - LEXTRACE("DEFAULTS_CMND "); - return DEFAULTS_CMND; - default: - LEXTRACE("DEFAULTS "); - return DEFAULTS; - } - } - YY_BREAK -case 21: -YY_RULE_SETUP -#line 335 "toke.l" -{ - int n; - - if (continued) { - LEXTRACE("ERROR "); - return ERROR; - } - - for (n = 0; isblank((unsigned char)yytext[n]); n++) - continue; - switch (yytext[n]) { - case 'H': - LEXTRACE("HOSTALIAS "); - return HOSTALIAS; - case 'C': - LEXTRACE("CMNDALIAS "); - return CMNDALIAS; - case 'U': - LEXTRACE("USERALIAS "); - return USERALIAS; - case 'R': - LEXTRACE("RUNASALIAS "); - return RUNASALIAS; - } - } - YY_BREAK -case 22: -YY_RULE_SETUP -#line 361 "toke.l" -{ - /* cmnd does not require passwd for this user */ - LEXTRACE("NOPASSWD "); - return NOPASSWD; - } - YY_BREAK -case 23: -YY_RULE_SETUP -#line 367 "toke.l" -{ - /* cmnd requires passwd for this user */ - LEXTRACE("PASSWD "); - return PASSWD; - } - YY_BREAK -case 24: -YY_RULE_SETUP -#line 373 "toke.l" -{ - LEXTRACE("NOEXEC "); - return NOEXEC; - } - YY_BREAK -case 25: -YY_RULE_SETUP -#line 378 "toke.l" -{ - LEXTRACE("EXEC "); - return EXEC; - } - YY_BREAK -case 26: -YY_RULE_SETUP -#line 383 "toke.l" -{ - LEXTRACE("SETENV "); - return SETENV; - } - YY_BREAK -case 27: -YY_RULE_SETUP -#line 388 "toke.l" -{ - LEXTRACE("NOSETENV "); - return NOSETENV; - } - YY_BREAK -case 28: -YY_RULE_SETUP -#line 393 "toke.l" -{ - LEXTRACE("LOG_OUTPUT "); - return LOG_OUTPUT; - } - YY_BREAK -case 29: -YY_RULE_SETUP -#line 398 "toke.l" -{ - LEXTRACE("NOLOG_OUTPUT "); - return NOLOG_OUTPUT; - } - YY_BREAK -case 30: -YY_RULE_SETUP -#line 403 "toke.l" -{ - LEXTRACE("LOG_INPUT "); - return LOG_INPUT; - } - YY_BREAK -case 31: -YY_RULE_SETUP -#line 408 "toke.l" -{ - LEXTRACE("NOLOG_INPUT "); - return NOLOG_INPUT; - } - YY_BREAK -case 32: -YY_RULE_SETUP -#line 413 "toke.l" -{ - /* empty group or netgroup */ - LEXTRACE("ERROR "); - return ERROR; - } - YY_BREAK -case 33: -YY_RULE_SETUP -#line 419 "toke.l" -{ - /* netgroup */ - if (!fill(yytext, yyleng)) - yyterminate(); - LEXTRACE("NETGROUP "); - return NETGROUP; - } - YY_BREAK -case 34: -YY_RULE_SETUP -#line 427 "toke.l" -{ - /* group */ - if (!fill(yytext, yyleng)) - yyterminate(); - LEXTRACE("USERGROUP "); - return USERGROUP; - } - YY_BREAK -case 35: -YY_RULE_SETUP -#line 435 "toke.l" -{ - if (!fill(yytext, yyleng)) - yyterminate(); - LEXTRACE("NTWKADDR "); - return NTWKADDR; - } - YY_BREAK -case 36: -YY_RULE_SETUP -#line 442 "toke.l" -{ - if (!fill(yytext, yyleng)) - yyterminate(); - LEXTRACE("NTWKADDR "); - return NTWKADDR; - } - YY_BREAK -case 37: -YY_RULE_SETUP -#line 449 "toke.l" -{ - if (!ipv6_valid(yytext)) { - LEXTRACE("ERROR "); - return ERROR; - } - if (!fill(yytext, yyleng)) - yyterminate(); - LEXTRACE("NTWKADDR "); - return NTWKADDR; - } - YY_BREAK -case 38: -YY_RULE_SETUP -#line 460 "toke.l" -{ - if (!ipv6_valid(yytext)) { - LEXTRACE("ERROR "); - return ERROR; - } - if (!fill(yytext, yyleng)) - yyterminate(); - LEXTRACE("NTWKADDR "); - return NTWKADDR; - } - YY_BREAK -case 39: -YY_RULE_SETUP -#line 471 "toke.l" -{ - if (strcmp(yytext, "ALL") == 0) { - LEXTRACE("ALL "); - return ALL; - } -#ifdef HAVE_SELINUX - /* XXX - restrict type/role to initial state */ - if (strcmp(yytext, "TYPE") == 0) { - LEXTRACE("TYPE "); - return TYPE; - } - if (strcmp(yytext, "ROLE") == 0) { - LEXTRACE("ROLE "); - return ROLE; - } -#endif /* HAVE_SELINUX */ - if (!fill(yytext, yyleng)) - yyterminate(); - LEXTRACE("ALIAS "); - return ALIAS; - } - YY_BREAK -case 40: -YY_RULE_SETUP -#line 493 "toke.l" -{ - /* no command args allowed for Defaults!/path */ - if (!fill_cmnd(yytext, yyleng)) - yyterminate(); - LEXTRACE("COMMAND "); - return COMMAND; - } - YY_BREAK -case 41: -YY_RULE_SETUP -#line 501 "toke.l" -{ - BEGIN GOTCMND; - LEXTRACE("COMMAND "); - if (!fill_cmnd(yytext, yyleng)) - yyterminate(); - } /* sudo -e */ - YY_BREAK -case 42: -YY_RULE_SETUP -#line 508 "toke.l" -{ - /* directories can't have args... */ - if (yytext[yyleng - 1] == '/') { - LEXTRACE("COMMAND "); - if (!fill_cmnd(yytext, yyleng)) - yyterminate(); - return COMMAND; - } else { - BEGIN GOTCMND; - LEXTRACE("COMMAND "); - if (!fill_cmnd(yytext, yyleng)) - yyterminate(); - } - } /* a pathname */ - YY_BREAK -case 43: -YY_RULE_SETUP -#line 523 "toke.l" -{ - LEXTRACE("BEGINSTR "); - yylval.string = NULL; - prev_state = YY_START; - BEGIN INSTR; - } - YY_BREAK -case 44: -YY_RULE_SETUP -#line 530 "toke.l" -{ - /* a word */ - if (!fill(yytext, yyleng)) - yyterminate(); - LEXTRACE("WORD(5) "); - return WORD; - } - YY_BREAK -case 45: -YY_RULE_SETUP -#line 538 "toke.l" -{ - LEXTRACE("( "); - return '('; - } - YY_BREAK -case 46: -YY_RULE_SETUP -#line 543 "toke.l" -{ - LEXTRACE(") "); - return ')'; - } - YY_BREAK -case 47: -YY_RULE_SETUP -#line 548 "toke.l" -{ - LEXTRACE(", "); - return ','; - } /* return ',' */ - YY_BREAK -case 48: -YY_RULE_SETUP -#line 553 "toke.l" -{ - LEXTRACE("= "); - return '='; - } /* return '=' */ - YY_BREAK -case 49: -YY_RULE_SETUP -#line 558 "toke.l" -{ - LEXTRACE(": "); - return ':'; - } /* return ':' */ - YY_BREAK -case 50: -YY_RULE_SETUP -#line 563 "toke.l" -{ - if (yyleng & 1) { - LEXTRACE("!"); - return '!'; /* return '!' */ - } - } - YY_BREAK -case 51: -YY_RULE_SETUP -#line 570 "toke.l" -{ - if (YY_START == INSTR) { - LEXTRACE("ERROR "); - return ERROR; /* line break in string */ - } - BEGIN INITIAL; - ++sudolineno; - continued = FALSE; - LEXTRACE("\n"); - return COMMENT; - } /* return newline */ - YY_BREAK -case 52: -YY_RULE_SETUP -#line 582 "toke.l" -{ /* throw away space/tabs */ - sawspace = TRUE; /* but remember for fill_args */ - } - YY_BREAK -case 53: -YY_RULE_SETUP -#line 586 "toke.l" -{ - sawspace = TRUE; /* remember for fill_args */ - ++sudolineno; - continued = TRUE; - } /* throw away EOL after \ */ - YY_BREAK -case 54: -YY_RULE_SETUP -#line 592 "toke.l" -{ - BEGIN INITIAL; - ++sudolineno; - continued = FALSE; - LEXTRACE("#\n"); - return COMMENT; - } /* comment, not uid/gid */ - YY_BREAK -case 55: -YY_RULE_SETUP -#line 600 "toke.l" -{ - LEXTRACE("ERROR "); - return ERROR; - } /* parse error */ - YY_BREAK -case YY_STATE_EOF(INITIAL): -case YY_STATE_EOF(GOTDEFS): -case YY_STATE_EOF(GOTCMND): -case YY_STATE_EOF(STARTDEFS): -case YY_STATE_EOF(INDEFS): -case YY_STATE_EOF(INSTR): -#line 605 "toke.l" -{ - if (YY_START != INITIAL) { - BEGIN INITIAL; - LEXTRACE("ERROR "); - return ERROR; - } - if (!pop_include()) - yyterminate(); - } - YY_BREAK -case 56: -YY_RULE_SETUP -#line 615 "toke.l" -ECHO; - YY_BREAK -#line 2422 "lex.yy.c" - - case YY_END_OF_BUFFER: - { - /* Amount of text matched not including the EOB char. */ - int yy_amount_of_matched_text = (int) (yy_cp - yytext_ptr) - 1; - - /* Undo the effects of YY_DO_BEFORE_ACTION. */ - *yy_cp = yy_hold_char; - YY_RESTORE_YY_MORE_OFFSET - - if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_NEW ) - { - /* We're scanning a new file or input source. It's - * possible that this happened because the user - * just pointed yyin at a new source and called - * yylex(). If so, then we have to assure - * consistency between yy_current_buffer and our - * globals. Here is the right place to do so, because - * this is the first action (other than possibly a - * back-up) that will match for the new input source. - */ - yy_n_chars = yy_current_buffer->yy_n_chars; - yy_current_buffer->yy_input_file = yyin; - yy_current_buffer->yy_buffer_status = YY_BUFFER_NORMAL; - } - - /* Note that here we test for yy_c_buf_p "<=" to the position - * of the first EOB in the buffer, since yy_c_buf_p will - * already have been incremented past the NUL character - * (since all states make transitions on EOB to the - * end-of-buffer state). Contrast this with the test - * in input(). - */ - if ( yy_c_buf_p <= &yy_current_buffer->yy_ch_buf[yy_n_chars] ) - { /* This was really a NUL. */ - yy_state_type yy_next_state; - - yy_c_buf_p = yytext_ptr + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state(); - - /* Okay, we're now positioned to make the NUL - * transition. We couldn't have - * yy_get_previous_state() go ahead and do it - * for us because it doesn't know how to deal - * with the possibility of jamming (and we don't - * want to build jamming into it because then it - * will run more slowly). - */ - - yy_next_state = yy_try_NUL_trans( yy_current_state ); - - yy_bp = yytext_ptr + YY_MORE_ADJ; - - if ( yy_next_state ) - { - /* Consume the NUL. */ - yy_cp = ++yy_c_buf_p; - yy_current_state = yy_next_state; - goto yy_match; - } - - else - { - yy_cp = yy_c_buf_p; - goto yy_find_action; - } - } - - else switch ( yy_get_next_buffer() ) - { - case EOB_ACT_END_OF_FILE: - { - yy_did_buffer_switch_on_eof = 0; - - if ( yywrap() ) - { - /* Note: because we've taken care in - * yy_get_next_buffer() to have set up - * yytext, we can now set up - * yy_c_buf_p so that if some total - * hoser (like flex itself) wants to - * call the scanner after we return the - * YY_NULL, it'll still work - another - * YY_NULL will get returned. - */ - yy_c_buf_p = yytext_ptr + YY_MORE_ADJ; - - yy_act = YY_STATE_EOF(YY_START); - goto do_action; - } - - else - { - if ( ! yy_did_buffer_switch_on_eof ) - YY_NEW_FILE; - } - break; - } - - case EOB_ACT_CONTINUE_SCAN: - yy_c_buf_p = - yytext_ptr + yy_amount_of_matched_text; - - yy_current_state = yy_get_previous_state(); - - yy_cp = yy_c_buf_p; - yy_bp = yytext_ptr + YY_MORE_ADJ; - goto yy_match; - - case EOB_ACT_LAST_MATCH: - yy_c_buf_p = - &yy_current_buffer->yy_ch_buf[yy_n_chars]; - - yy_current_state = yy_get_previous_state(); - - yy_cp = yy_c_buf_p; - yy_bp = yytext_ptr + YY_MORE_ADJ; - goto yy_find_action; - } - break; - } - - default: - YY_FATAL_ERROR( - "fatal flex scanner internal error--no action found" ); - } /* end of action switch */ - } /* end of scanning one token */ - } /* end of yylex */ - - -/* yy_get_next_buffer - try to read in a new buffer - * - * Returns a code representing an action: - * EOB_ACT_LAST_MATCH - - * EOB_ACT_CONTINUE_SCAN - continue scanning from current position - * EOB_ACT_END_OF_FILE - end of file - */ - -static int yy_get_next_buffer() - { - register char *dest = yy_current_buffer->yy_ch_buf; - register char *source = yytext_ptr; - register int number_to_move, i; - int ret_val; - - if ( yy_c_buf_p > &yy_current_buffer->yy_ch_buf[yy_n_chars + 1] ) - YY_FATAL_ERROR( - "fatal flex scanner internal error--end of buffer missed" ); - - if ( yy_current_buffer->yy_fill_buffer == 0 ) - { /* Don't try to fill the buffer, so this is an EOF. */ - if ( yy_c_buf_p - yytext_ptr - YY_MORE_ADJ == 1 ) - { - /* We matched a single character, the EOB, so - * treat this as a final EOF. - */ - return EOB_ACT_END_OF_FILE; - } - - else - { - /* We matched some text prior to the EOB, first - * process it. - */ - return EOB_ACT_LAST_MATCH; - } - } - - /* Try to read more data. */ - - /* First move last chars to start of buffer. */ - number_to_move = (int) (yy_c_buf_p - yytext_ptr) - 1; - - for ( i = 0; i < number_to_move; ++i ) - *(dest++) = *(source++); - - if ( yy_current_buffer->yy_buffer_status == YY_BUFFER_EOF_PENDING ) - /* don't do the read, it's not guaranteed to return an EOF, - * just force an EOF - */ - yy_current_buffer->yy_n_chars = yy_n_chars = 0; - - else - { - int num_to_read = - yy_current_buffer->yy_buf_size - number_to_move - 1; - - while ( num_to_read <= 0 ) - { /* Not enough room in the buffer - grow it. */ -#ifdef YY_USES_REJECT - YY_FATAL_ERROR( -"input buffer overflow, can't enlarge buffer because scanner uses REJECT" ); -#else - - /* just a shorter name for the current buffer */ - YY_BUFFER_STATE b = yy_current_buffer; - - int yy_c_buf_p_offset = - (int) (yy_c_buf_p - b->yy_ch_buf); - - if ( b->yy_is_our_buffer ) - { - int new_size = b->yy_buf_size * 2; - - if ( new_size <= 0 ) - b->yy_buf_size += b->yy_buf_size / 8; - else - b->yy_buf_size *= 2; - - b->yy_ch_buf = (char *) - /* Include room in for 2 EOB chars. */ - yy_flex_realloc( (void *) b->yy_ch_buf, - b->yy_buf_size + 2 ); - } - else - /* Can't grow it, we don't own it. */ - b->yy_ch_buf = 0; - - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( - "fatal error - scanner input buffer overflow" ); - - yy_c_buf_p = &b->yy_ch_buf[yy_c_buf_p_offset]; - - num_to_read = yy_current_buffer->yy_buf_size - - number_to_move - 1; -#endif - } - - if ( num_to_read > YY_READ_BUF_SIZE ) - num_to_read = YY_READ_BUF_SIZE; - - /* Read in more data. */ - YY_INPUT( (&yy_current_buffer->yy_ch_buf[number_to_move]), - yy_n_chars, num_to_read ); - - yy_current_buffer->yy_n_chars = yy_n_chars; - } - - if ( yy_n_chars == 0 ) - { - if ( number_to_move == YY_MORE_ADJ ) - { - ret_val = EOB_ACT_END_OF_FILE; - yyrestart( yyin ); - } - - else - { - ret_val = EOB_ACT_LAST_MATCH; - yy_current_buffer->yy_buffer_status = - YY_BUFFER_EOF_PENDING; - } - } - - else - ret_val = EOB_ACT_CONTINUE_SCAN; - - yy_n_chars += number_to_move; - yy_current_buffer->yy_ch_buf[yy_n_chars] = YY_END_OF_BUFFER_CHAR; - yy_current_buffer->yy_ch_buf[yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR; - - yytext_ptr = &yy_current_buffer->yy_ch_buf[0]; - - return ret_val; - } - - -/* yy_get_previous_state - get the state just before the EOB char was reached */ - -static yy_state_type yy_get_previous_state() - { - register yy_state_type yy_current_state; - register char *yy_cp; - - yy_current_state = yy_start; - yy_current_state += YY_AT_BOL(); - - for ( yy_cp = yytext_ptr + YY_MORE_ADJ; yy_cp < yy_c_buf_p; ++yy_cp ) - { - register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1); - if ( yy_accept[yy_current_state] ) - { - yy_last_accepting_state = yy_current_state; - yy_last_accepting_cpos = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 599 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - } - - return yy_current_state; - } - - -/* yy_try_NUL_trans - try to make a transition on the NUL character - * - * synopsis - * next_state = yy_try_NUL_trans( current_state ); - */ - -#ifdef YY_USE_PROTOS -static yy_state_type yy_try_NUL_trans( yy_state_type yy_current_state ) -#else -static yy_state_type yy_try_NUL_trans( yy_current_state ) -yy_state_type yy_current_state; -#endif - { - register int yy_is_jam; - register char *yy_cp = yy_c_buf_p; - - register YY_CHAR yy_c = 1; - if ( yy_accept[yy_current_state] ) - { - yy_last_accepting_state = yy_current_state; - yy_last_accepting_cpos = yy_cp; - } - while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) - { - yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 599 ) - yy_c = yy_meta[(unsigned int) yy_c]; - } - yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 598); - - return yy_is_jam ? 0 : yy_current_state; - } - - -#ifndef YY_NO_UNPUT -#ifdef YY_USE_PROTOS -static void yyunput( int c, register char *yy_bp ) -#else -static void yyunput( c, yy_bp ) -int c; -register char *yy_bp; -#endif - { - register char *yy_cp = yy_c_buf_p; - - /* undo effects of setting up yytext */ - *yy_cp = yy_hold_char; - - if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) - { /* need to shift things up to make room */ - /* +2 for EOB chars. */ - register int number_to_move = yy_n_chars + 2; - register char *dest = &yy_current_buffer->yy_ch_buf[ - yy_current_buffer->yy_buf_size + 2]; - register char *source = - &yy_current_buffer->yy_ch_buf[number_to_move]; - - while ( source > yy_current_buffer->yy_ch_buf ) - *--dest = *--source; - - yy_cp += (int) (dest - source); - yy_bp += (int) (dest - source); - yy_current_buffer->yy_n_chars = - yy_n_chars = yy_current_buffer->yy_buf_size; - - if ( yy_cp < yy_current_buffer->yy_ch_buf + 2 ) - YY_FATAL_ERROR( "flex scanner push-back overflow" ); - } - - *--yy_cp = (char) c; - - - yytext_ptr = yy_bp; - yy_hold_char = *yy_cp; - yy_c_buf_p = yy_cp; - } -#endif /* ifndef YY_NO_UNPUT */ - - -#ifndef YY_NO_INPUT -#ifdef __cplusplus -static int yyinput() -#else -static int input() -#endif - { - int c; - - *yy_c_buf_p = yy_hold_char; - - if ( *yy_c_buf_p == YY_END_OF_BUFFER_CHAR ) - { - /* yy_c_buf_p now points to the character we want to return. - * If this occurs *before* the EOB characters, then it's a - * valid NUL; if not, then we've hit the end of the buffer. - */ - if ( yy_c_buf_p < &yy_current_buffer->yy_ch_buf[yy_n_chars] ) - /* This was really a NUL. */ - *yy_c_buf_p = '\0'; - - else - { /* need more input */ - int offset = yy_c_buf_p - yytext_ptr; - ++yy_c_buf_p; - - switch ( yy_get_next_buffer() ) - { - case EOB_ACT_LAST_MATCH: - /* This happens because yy_g_n_b() - * sees that we've accumulated a - * token and flags that we need to - * try matching the token before - * proceeding. But for input(), - * there's no matching to consider. - * So convert the EOB_ACT_LAST_MATCH - * to EOB_ACT_END_OF_FILE. - */ - - /* Reset buffer status. */ - yyrestart( yyin ); - - /* fall through */ - - case EOB_ACT_END_OF_FILE: - { - if ( yywrap() ) - return EOF; - - if ( ! yy_did_buffer_switch_on_eof ) - YY_NEW_FILE; -#ifdef __cplusplus - return yyinput(); -#else - return input(); -#endif - } - - case EOB_ACT_CONTINUE_SCAN: - yy_c_buf_p = yytext_ptr + offset; - break; - } - } - } - - c = *(unsigned char *) yy_c_buf_p; /* cast for 8-bit char's */ - *yy_c_buf_p = '\0'; /* preserve yytext */ - yy_hold_char = *++yy_c_buf_p; - - yy_current_buffer->yy_at_bol = (c == '\n'); - - return c; - } -#endif /* ifndef YY_NO_INPUT */ - - -#ifdef YY_USE_PROTOS -void yyrestart( FILE *input_file ) -#else -void yyrestart( input_file ) -FILE *input_file; -#endif - { - if ( ! yy_current_buffer ) - yy_current_buffer = yy_create_buffer( yyin, YY_BUF_SIZE ); - - yy_init_buffer( yy_current_buffer, input_file ); - yy_load_buffer_state(); - } - - -#ifdef YY_USE_PROTOS -void yy_switch_to_buffer( YY_BUFFER_STATE new_buffer ) -#else -void yy_switch_to_buffer( new_buffer ) -YY_BUFFER_STATE new_buffer; -#endif - { - if ( yy_current_buffer == new_buffer ) - return; - - if ( yy_current_buffer ) - { - /* Flush out information for old buffer. */ - *yy_c_buf_p = yy_hold_char; - yy_current_buffer->yy_buf_pos = yy_c_buf_p; - yy_current_buffer->yy_n_chars = yy_n_chars; - } - - yy_current_buffer = new_buffer; - yy_load_buffer_state(); - - /* We don't actually know whether we did this switch during - * EOF (yywrap()) processing, but the only time this flag - * is looked at is after yywrap() is called, so it's safe - * to go ahead and always set it. - */ - yy_did_buffer_switch_on_eof = 1; - } - - -#ifdef YY_USE_PROTOS -void yy_load_buffer_state( void ) -#else -void yy_load_buffer_state() -#endif - { - yy_n_chars = yy_current_buffer->yy_n_chars; - yytext_ptr = yy_c_buf_p = yy_current_buffer->yy_buf_pos; - yyin = yy_current_buffer->yy_input_file; - yy_hold_char = *yy_c_buf_p; - } - - -#ifdef YY_USE_PROTOS -YY_BUFFER_STATE yy_create_buffer( FILE *file, int size ) -#else -YY_BUFFER_STATE yy_create_buffer( file, size ) -FILE *file; -int size; -#endif - { - YY_BUFFER_STATE b; - - b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); - - b->yy_buf_size = size; - - /* yy_ch_buf has to be 2 characters longer than the size given because - * we need to put in 2 end-of-buffer characters. - */ - b->yy_ch_buf = (char *) yy_flex_alloc( b->yy_buf_size + 2 ); - if ( ! b->yy_ch_buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_create_buffer()" ); - - b->yy_is_our_buffer = 1; - - yy_init_buffer( b, file ); - - return b; - } - - -#ifdef YY_USE_PROTOS -void yy_delete_buffer( YY_BUFFER_STATE b ) -#else -void yy_delete_buffer( b ) -YY_BUFFER_STATE b; -#endif - { - if ( ! b ) - return; - - if ( b == yy_current_buffer ) - yy_current_buffer = (YY_BUFFER_STATE) 0; - - if ( b->yy_is_our_buffer ) - yy_flex_free( (void *) b->yy_ch_buf ); - - yy_flex_free( (void *) b ); - } - - -#ifndef YY_ALWAYS_INTERACTIVE -#ifndef YY_NEVER_INTERACTIVE -#include -#endif -#endif - -#ifdef YY_USE_PROTOS -void yy_init_buffer( YY_BUFFER_STATE b, FILE *file ) -#else -void yy_init_buffer( b, file ) -YY_BUFFER_STATE b; -FILE *file; -#endif - - - { - int oerrno = errno; - - yy_flush_buffer( b ); - - b->yy_input_file = file; - b->yy_fill_buffer = 1; - -#if defined(YY_ALWAYS_INTERACTIVE) && YY_ALWAYS_INTERACTIVE - b->yy_is_interactive = 1; -#else -#if defined(YY_NEVER_INTERACTIVE) && YY_NEVER_INTERACTIVE - b->yy_is_interactive = 0; -#else - b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0; -#endif -#endif - errno = oerrno; - } - - -#ifdef YY_USE_PROTOS -void yy_flush_buffer( YY_BUFFER_STATE b ) -#else -void yy_flush_buffer( b ) -YY_BUFFER_STATE b; -#endif - - { - if ( ! b ) - return; - - b->yy_n_chars = 0; - - /* We always need two end-of-buffer characters. The first causes - * a transition to the end-of-buffer state. The second causes - * a jam in that state. - */ - b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR; - b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR; - - b->yy_buf_pos = &b->yy_ch_buf[0]; - - b->yy_at_bol = 1; - b->yy_buffer_status = YY_BUFFER_NEW; - - if ( b == yy_current_buffer ) - yy_load_buffer_state(); - } - - -#ifndef YY_NO_SCAN_BUFFER -#ifdef YY_USE_PROTOS -YY_BUFFER_STATE yy_scan_buffer( char *base, yy_size_t size ) -#else -YY_BUFFER_STATE yy_scan_buffer( base, size ) -char *base; -yy_size_t size; -#endif - { - YY_BUFFER_STATE b; - - if ( size < 2 || - base[size-2] != YY_END_OF_BUFFER_CHAR || - base[size-1] != YY_END_OF_BUFFER_CHAR ) - /* They forgot to leave room for the EOB's. */ - return 0; - - b = (YY_BUFFER_STATE) yy_flex_alloc( sizeof( struct yy_buffer_state ) ); - if ( ! b ) - YY_FATAL_ERROR( "out of dynamic memory in yy_scan_buffer()" ); - - b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */ - b->yy_buf_pos = b->yy_ch_buf = base; - b->yy_is_our_buffer = 0; - b->yy_input_file = 0; - b->yy_n_chars = b->yy_buf_size; - b->yy_is_interactive = 0; - b->yy_at_bol = 1; - b->yy_fill_buffer = 0; - b->yy_buffer_status = YY_BUFFER_NEW; - - yy_switch_to_buffer( b ); - - return b; - } -#endif - - -#ifndef YY_NO_SCAN_STRING -#ifdef YY_USE_PROTOS -YY_BUFFER_STATE yy_scan_string( yyconst char *yy_str ) -#else -YY_BUFFER_STATE yy_scan_string( yy_str ) -yyconst char *yy_str; -#endif - { - int len; - for ( len = 0; yy_str[len]; ++len ) - ; - - return yy_scan_bytes( yy_str, len ); - } -#endif - - -#ifndef YY_NO_SCAN_BYTES -#ifdef YY_USE_PROTOS -YY_BUFFER_STATE yy_scan_bytes( yyconst char *bytes, int len ) -#else -YY_BUFFER_STATE yy_scan_bytes( bytes, len ) -yyconst char *bytes; -int len; -#endif - { - YY_BUFFER_STATE b; - char *buf; - yy_size_t n; - int i; - - /* Get memory for full buffer, including space for trailing EOB's. */ - n = len + 2; - buf = (char *) yy_flex_alloc( n ); - if ( ! buf ) - YY_FATAL_ERROR( "out of dynamic memory in yy_scan_bytes()" ); - - for ( i = 0; i < len; ++i ) - buf[i] = bytes[i]; - - buf[len] = buf[len+1] = YY_END_OF_BUFFER_CHAR; - - b = yy_scan_buffer( buf, n ); - if ( ! b ) - YY_FATAL_ERROR( "bad buffer in yy_scan_bytes()" ); - - /* It's okay to grow etc. this buffer, and we should throw it - * away when we're done. - */ - b->yy_is_our_buffer = 1; - - return b; - } -#endif - - -#ifndef YY_NO_PUSH_STATE -#ifdef YY_USE_PROTOS -static void yy_push_state( int new_state ) -#else -static void yy_push_state( new_state ) -int new_state; -#endif - { - if ( yy_start_stack_ptr >= yy_start_stack_depth ) - { - yy_size_t new_size; - - yy_start_stack_depth += YY_START_STACK_INCR; - new_size = yy_start_stack_depth * sizeof( int ); - - if ( ! yy_start_stack ) - yy_start_stack = (int *) yy_flex_alloc( new_size ); - - else - yy_start_stack = (int *) yy_flex_realloc( - (void *) yy_start_stack, new_size ); - - if ( ! yy_start_stack ) - YY_FATAL_ERROR( - "out of memory expanding start-condition stack" ); - } - - yy_start_stack[yy_start_stack_ptr++] = YY_START; - - BEGIN(new_state); - } -#endif - - -#ifndef YY_NO_POP_STATE -static void yy_pop_state() - { - if ( --yy_start_stack_ptr < 0 ) - YY_FATAL_ERROR( "start-condition stack underflow" ); - - BEGIN(yy_start_stack[yy_start_stack_ptr]); - } -#endif - - -#ifndef YY_NO_TOP_STATE -static int yy_top_state() - { - return yy_start_stack[yy_start_stack_ptr - 1]; - } -#endif - -#ifndef YY_EXIT_FAILURE -#define YY_EXIT_FAILURE 2 -#endif - -#ifdef YY_USE_PROTOS -static void yy_fatal_error( yyconst char msg[] ) -#else -static void yy_fatal_error( msg ) -char msg[]; -#endif - { - (void) fprintf( stderr, "%s\n", msg ); - exit( YY_EXIT_FAILURE ); - } - - - -/* Redefine yyless() so it works in section 3 code. */ - -#undef yyless -#define yyless(n) \ - do \ - { \ - /* Undo effects of setting up yytext. */ \ - yytext[yyleng] = yy_hold_char; \ - yy_c_buf_p = yytext + n; \ - yy_hold_char = *yy_c_buf_p; \ - *yy_c_buf_p = '\0'; \ - yyleng = n; \ - } \ - while ( 0 ) - - -/* Internal utility routines. */ - -#ifndef yytext_ptr -#ifdef YY_USE_PROTOS -static void yy_flex_strncpy( char *s1, yyconst char *s2, int n ) -#else -static void yy_flex_strncpy( s1, s2, n ) -char *s1; -yyconst char *s2; -int n; -#endif - { - register int i; - for ( i = 0; i < n; ++i ) - s1[i] = s2[i]; - } -#endif - -#ifdef YY_NEED_STRLEN -#ifdef YY_USE_PROTOS -static int yy_flex_strlen( yyconst char *s ) -#else -static int yy_flex_strlen( s ) -yyconst char *s; -#endif - { - register int n; - for ( n = 0; s[n]; ++n ) - ; - - return n; - } -#endif - - -#ifdef YY_USE_PROTOS -static void *yy_flex_alloc( yy_size_t size ) -#else -static void *yy_flex_alloc( size ) -yy_size_t size; -#endif - { - return (void *) malloc( size ); - } - -#ifdef YY_USE_PROTOS -static void *yy_flex_realloc( void *ptr, yy_size_t size ) -#else -static void *yy_flex_realloc( ptr, size ) -void *ptr; -yy_size_t size; -#endif - { - /* The cast to (char *) in the following accommodates both - * implementations that use char* generic pointers, and those - * that use void* generic pointers. It works with the latter - * because both ANSI C and C++ allow castless assignment from - * any pointer type to void*, and deal with argument conversions - * as though doing an assignment. - */ - return (void *) realloc( (char *) ptr, size ); - } - -#ifdef YY_USE_PROTOS -static void yy_flex_free( void *ptr ) -#else -static void yy_flex_free( ptr ) -void *ptr; -#endif - { - free( ptr ); - } - -#if defined(YY_MAIN) && YY_MAIN -int main() - { - yylex(); - return 0; - } -#endif -#line 615 "toke.l" - -struct path_list { - char *path; - struct path_list *next; -}; - -struct include_stack { - YY_BUFFER_STATE bs; - char *path; - struct path_list *more; /* more files in case of includedir */ - int lineno; - int keepopen; -}; - -static int -pl_compare(v1, v2) - const void *v1; - const void *v2; -{ - const struct path_list * const *p1 = v1; - const struct path_list * const *p2 = v2; - - return strcmp((*p1)->path, (*p2)->path); -} - -static char * -switch_dir(stack, dirpath) - struct include_stack *stack; - char *dirpath; -{ - DIR *dir; - int i, count = 0; - char *path = NULL; - struct dirent *dent; - struct stat sb; - struct path_list *pl, *first = NULL; - struct path_list **sorted = NULL; - - if (!(dir = opendir(dirpath))) { - if (errno != ENOENT) { - char *errbuf; - if (asprintf(&errbuf, "%s: %s", dirpath, strerror(errno)) != -1) { - yyerror(errbuf); - free(errbuf); - } else { - yyerror("unable to allocate memory"); - } - } - goto done; - } - while ((dent = readdir(dir))) { - /* Ignore files that end in '~' or have a '.' in them. */ - if (dent->d_name[0] == '\0' || dent->d_name[NAMLEN(dent) - 1] == '~' - || strchr(dent->d_name, '.') != NULL) { - continue; - } - if (asprintf(&path, "%s/%s", dirpath, dent->d_name) == -1) { - closedir(dir); - goto bad; - } - if (stat(path, &sb) != 0 || !S_ISREG(sb.st_mode)) { - efree(path); - path = NULL; - continue; - } - pl = malloc(sizeof(*pl)); - if (pl == NULL) - goto bad; - pl->path = path; - pl->next = first; - first = pl; - count++; - } - closedir(dir); - - if (count == 0) - goto done; - - /* Sort the list as an array. */ - sorted = malloc(sizeof(*sorted) * count); - if (sorted == NULL) - goto bad; - pl = first; - for (i = 0; i < count; i++) { - sorted[i] = pl; - pl = pl->next; - } - qsort(sorted, count, sizeof(*sorted), pl_compare); - - /* Apply sorting to the list. */ - first = sorted[0]; - sorted[count - 1]->next = NULL; - for (i = 1; i < count; i++) - sorted[i - 1]->next = sorted[i]; - efree(sorted); - - /* Pull out the first element for parsing, leave the rest for later. */ - if (count) { - path = first->path; - pl = first->next; - efree(first); - stack->more = pl; - } else { - path = NULL; - } -done: - efree(dirpath); - return path; -bad: - while (first != NULL) { - pl = first; - first = pl->next; - free(pl->path); - free(pl); - } - efree(sorted); - efree(dirpath); - efree(path); - return NULL; -} - -#define MAX_SUDOERS_DEPTH 128 -#define SUDOERS_STACK_INCREMENT 16 - -static size_t istacksize, idepth; -static struct include_stack *istack; -static int keepopen; - -void -init_lexer() -{ - struct path_list *pl; - - while (idepth) { - idepth--; - while ((pl = istack[idepth].more) != NULL) { - istack[idepth].more = pl->next; - efree(pl->path); - efree(pl); - } - efree(istack[idepth].path); - if (idepth && !istack[idepth].keepopen) - fclose(istack[idepth].bs->yy_input_file); - yy_delete_buffer(istack[idepth].bs); - } - efree(istack); - istack = NULL; - istacksize = idepth = 0; - sudolineno = 1; - keepopen = FALSE; - sawspace = FALSE; - continued = FALSE; - prev_state = INITIAL; -} - -static int -_push_include(path, isdir) - char *path; - int isdir; -{ - struct path_list *pl; - FILE *fp; - - /* push current state onto stack */ - if (idepth >= istacksize) { - if (idepth > MAX_SUDOERS_DEPTH) { - yyerror("too many levels of includes"); - return FALSE; - } - istacksize += SUDOERS_STACK_INCREMENT; - istack = (struct include_stack *) realloc(istack, - sizeof(*istack) * istacksize); - if (istack == NULL) { - yyerror("unable to allocate memory"); - return FALSE; - } - } - if (isdir) { - if (!(path = switch_dir(&istack[idepth], path))) { - /* switch_dir() called yyerror() for us */ - return FALSE; - } - while ((fp = open_sudoers(path, FALSE, &keepopen)) == NULL) { - /* Unable to open path in includedir, go to next one, if any. */ - efree(path); - if ((pl = istack[idepth].more) == NULL) - return FALSE; - path = pl->path; - istack[idepth].more = pl->next; - efree(pl); - } - } else { - if ((fp = open_sudoers(path, TRUE, &keepopen)) == NULL) { - char *errbuf; - if (asprintf(&errbuf, "%s: %s", path, strerror(errno)) != -1) { - yyerror(errbuf); - free(errbuf); - } else { - yyerror("unable to allocate memory"); - } - return FALSE; - } - istack[idepth].more = NULL; - } - /* Push the old (current) file and open the new one. */ - istack[idepth].path = sudoers; /* push old path */ - istack[idepth].bs = YY_CURRENT_BUFFER; - istack[idepth].lineno = sudolineno; - istack[idepth].keepopen = keepopen; - idepth++; - sudolineno = 1; - sudoers = path; - yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); - - return TRUE; -} - -static int -pop_include() -{ - struct path_list *pl; - FILE *fp; - - if (idepth == 0) - return FALSE; - - if (!keepopen) - fclose(YY_CURRENT_BUFFER->yy_input_file); - yy_delete_buffer(YY_CURRENT_BUFFER); - /* If we are in an include dir, move to the next file. */ - while ((pl = istack[idepth - 1].more) != NULL) { - fp = open_sudoers(pl->path, FALSE, &keepopen); - if (fp != NULL) { - istack[idepth - 1].more = pl->next; - efree(sudoers); - sudoers = pl->path; - sudolineno = 1; - yy_switch_to_buffer(yy_create_buffer(fp, YY_BUF_SIZE)); - efree(pl); - break; - } - /* Unable to open path in include dir, go to next one. */ - istack[idepth - 1].more = pl->next; - efree(pl->path); - efree(pl); - } - /* If no path list, just pop the last dir on the stack. */ - if (pl == NULL) { - idepth--; - yy_switch_to_buffer(istack[idepth].bs); - efree(sudoers); - sudoers = istack[idepth].path; - sudolineno = istack[idepth].lineno; - keepopen = istack[idepth].keepopen; - } - return TRUE; -} - -static char * -parse_include(base) - char *base; -{ - char *cp, *ep, *path; - int len = 0, subst = 0; - size_t shost_len = 0; - - /* Pull out path from #include line. */ - cp = base + sizeof("#include"); - if (*cp == 'i') - cp += 3; /* includedir */ - while (isblank((unsigned char) *cp)) - cp++; - ep = cp; - while (*ep != '\0' && !isspace((unsigned char) *ep)) { - if (ep[0] == '%' && ep[1] == 'h') { - shost_len = strlen(user_shost); - len += shost_len - 2; - subst = 1; - } - ep++; - } - - /* Make a copy of path and return it. */ - len += (int)(ep - cp); - if ((path = malloc(len + 1)) == NULL) - yyerror("unable to allocate memory"); - if (subst) { - /* substitute for %h */ - char *pp = path; - while (cp < ep) { - if (cp[0] == '%' && cp[1] == 'h') { - memcpy(pp, user_shost, shost_len); - pp += shost_len; - cp += 2; - continue; - } - *pp++ = *cp++; - } - *pp = '\0'; - } else { - memcpy(path, cp, len); - path[len] = '\0'; - } - - /* Push any excess characters (e.g. comment, newline) back to the lexer */ - if (*ep != '\0') - yyless((int)(ep - base)); - - return path; -} diff --git a/vasgroups.c b/vasgroups.c deleted file mode 100644 index 0ba33e1..0000000 --- a/vasgroups.c +++ /dev/null @@ -1,321 +0,0 @@ -/* - * (c) 2006 Quest Software, Inc. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * 1. Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * 3. Neither the name of Quest Software, Inc. nor the names of its - * contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#include - -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "missing.h" -#include "logging.h" -#include "nonunix.h" -#include "sudo.h" -#include "parse.h" - - -/* Pseudo-boolean types */ -#undef TRUE -#undef FALSE -#define FALSE 0 -#define TRUE 1 - - -static vas_ctx_t *sudo_vas_ctx; -static vas_id_t *sudo_vas_id; -/* Don't use VAS_NAME_FLAG_NO_CACHE or lookups just won't work. - * -tedp, 2006-08-29 */ -static const int update_flags = 0; -static int sudo_vas_available = 0; -static char *err_msg = NULL; -static void *libvas_handle = NULL; - -/* libvas functions */ -static vas_err_t (*v_ctx_alloc) (vas_ctx_t **ctx); -static void (*v_ctx_free) (vas_ctx_t *ctx); -static vas_err_t (*v_id_alloc) (vas_ctx_t *ctx, const char *name, vas_id_t **id); -static void (*v_id_free) (vas_ctx_t *ctx, vas_id_t *id); -static vas_err_t (*v_id_establish_cred_keytab) (vas_ctx_t *ctx, vas_id_t *id, int credflags, const char *keytab); -static vas_err_t (*v_user_init) (vas_ctx_t *ctx, vas_id_t *id, const char *name, int flags, vas_user_t **user); -static void (*v_user_free) (vas_ctx_t *ctx, vas_user_t *user); -static vas_err_t (*v_group_init) (vas_ctx_t *ctx, vas_id_t *id, const char *name, int flags, vas_group_t **group); -static void (*v_group_free) (vas_ctx_t *ctx, vas_group_t *group); -static vas_err_t (*v_user_is_member) (vas_ctx_t *ctx, vas_id_t *id, vas_user_t *user, vas_group_t *group); -static const char* (*v_err_get_string) (vas_ctx_t *ctx, int with_cause); - - -static int resolve_vas_funcs(void); - - -/** - * Whether nonunix group lookups are available. - * @return 1 if available, 0 if not. - */ -int -sudo_nonunix_groupcheck_available(void) -{ - return sudo_vas_available; -} - - -/** - * Check if the user is in the group - * @param group group name which can be in DOMAIN\sam format or just the group - * name - * @param user user name - * @param pwd (unused) - * @return 1 if user is a member of the group, 0 if not (or error occurred) - */ -int -sudo_nonunix_groupcheck( const char* group, const char* user, const struct passwd* pwd ) -{ - static int error_cause_shown = FALSE; - int rval = FALSE; - vas_err_t vaserr; - vas_user_t* vas_user = NULL; - vas_group_t* vas_group = NULL; - - if (!sudo_vas_available) { - if (error_cause_shown == FALSE) { - /* Produce the saved error reason */ - warningx("Non-unix group checking unavailable: %s", - err_msg ? err_msg - : "(unknown cause)"); - error_cause_shown = TRUE; - } - return 0; - } - - /* resolve the user and group. The user will be a real Unix account name, - * while the group may be a unix name, or any group name accepted by - * vas_name_to_dn, which means any of: - * - Group Name - * - Group Name@FULLY.QUALIFIED.DOMAIN - * - CN=sudoers,CN=Users,DC=rcdev,DC=vintela,DC=com - * - S-1-2-34-5678901234-5678901234-5678901234-567 - * - * XXX - we may get non-VAS user accounts here. You can add local users to an - * Active Directory group through override files. Should we handle that case? - * */ - if( (vaserr = v_user_init( sudo_vas_ctx, sudo_vas_id, user, update_flags, &vas_user )) != VAS_ERR_SUCCESS ) { - if (vaserr == VAS_ERR_NOT_FOUND) { - /* No such user in AD. Probably a local user. */ - vaserr = VAS_ERR_SUCCESS; - } - goto FINISHED; - } - - if( (vaserr = v_group_init( sudo_vas_ctx, sudo_vas_id, group, update_flags, &vas_group )) != VAS_ERR_SUCCESS ) { - goto FINISHED; - } - - /* do the membership check */ - if( (vaserr = v_user_is_member( sudo_vas_ctx, sudo_vas_id, vas_user, vas_group )) == VAS_ERR_SUCCESS ) { - rval = TRUE; - } - else if (vaserr == VAS_ERR_NOT_FOUND) { - /* fake the vaserr code so no error is triggered */ - vaserr = VAS_ERR_SUCCESS; - } - - -FINISHED: /* cleanups */ - if (vaserr != VAS_ERR_SUCCESS && vaserr != VAS_ERR_NOT_FOUND ) { - warningx("Error while checking group membership " - "for user \"%s\", group \"%s\", error: %s%s.", user, group, - v_err_get_string(sudo_vas_ctx, 1), - /* A helpful hint if there seems to be a non-FQDN as the domain */ - (strchr(group, '@') && !strchr(group, '.')) - ? "\nMake sure the fully qualified domain name is specified" - : ""); - } - if( vas_group ) v_group_free( sudo_vas_ctx, vas_group ); - if( vas_user ) v_user_free( sudo_vas_ctx, vas_user ); - - return rval; -} - - -static void -set_err_msg(const char *msg, ...) { - va_list ap; - - if (!msg) /* assert */ - return; - - if (err_msg) - free(err_msg); - - va_start(ap, msg); - - if (vasprintf(&err_msg, msg, ap) == -1) - err_msg = NULL; - - va_end(ap); -} - - -/** - * Initialise nonunix_groupcheck state. - */ -void -sudo_nonunix_groupcheck_init(void) -{ - vas_err_t vaserr; - void *libvas; - - if (err_msg) { - free(err_msg); - err_msg = NULL; - } - - libvas = dlopen(LIBVAS_SO, RTLD_LAZY); - if (!libvas) { - set_err_msg("dlopen() failed: %s", dlerror()); - return; - } - - libvas_handle = libvas; - - if (resolve_vas_funcs() != 0) - return; - - if (VAS_ERR_SUCCESS == (vaserr = v_ctx_alloc(&sudo_vas_ctx))) { - - if (VAS_ERR_SUCCESS == (vaserr = v_id_alloc(sudo_vas_ctx, "host/", &sudo_vas_id))) { - - if (update_flags & VAS_NAME_FLAG_NO_LDAP) { - sudo_vas_available = 1; - return; /* OK */ - } else { /* Get a keytab */ - if ((vaserr = v_id_establish_cred_keytab( sudo_vas_ctx, - sudo_vas_id, - VAS_ID_FLAG_USE_MEMORY_CCACHE - | VAS_ID_FLAG_KEEP_COPY_OF_CRED - | VAS_ID_FLAG_NO_INITIAL_TGT, - NULL )) == VAS_ERR_SUCCESS) { - sudo_vas_available = 1; - return; /* OK */ - } - - if (!err_msg) - set_err_msg("unable to establish creds: %s", - v_err_get_string(sudo_vas_ctx, 1)); - } - - v_id_free(sudo_vas_ctx, sudo_vas_id); - sudo_vas_id = NULL; - } - - /* This is the last opportunity to get an error message from libvas */ - if (!err_msg) - set_err_msg("Error initializing non-unix group checking: %s", - v_err_get_string(sudo_vas_ctx, 1)); - - v_ctx_free(sudo_vas_ctx); - sudo_vas_ctx = NULL; - } - - if (!err_msg) - set_err_msg("Failed to get a libvas handle for non-unix group checking (unknown cause)"); - - sudo_vas_available = 0; -} - - -/** - * Clean up nonunix_groupcheck state. - */ -void -sudo_nonunix_groupcheck_cleanup() -{ - if (err_msg) { - free(err_msg); - err_msg = NULL; - } - - if (sudo_vas_available) { - v_id_free(sudo_vas_ctx, sudo_vas_id); - sudo_vas_id = NULL; - - v_ctx_free(sudo_vas_ctx); - sudo_vas_ctx = NULL; - - sudo_vas_available = FALSE; - } - - if (libvas_handle) { - if (dlclose(libvas_handle) != 0) - warningx("dlclose() failed: %s", dlerror()); - libvas_handle = NULL; - } -} - -#define RESOLVE_OR_ERR(fptr, sym) \ - do { \ - void *_fptr = dlsym(libvas_handle, (sym)); \ - if (!_fptr) { \ - set_err_msg("dlsym() failed: %s", dlerror()); \ - return -1; \ - } \ - fptr = _fptr; \ - } while (0) - - -/** - * Resolve all the libvas functions. - * Returns -1 and sets err_msg if something went wrong, or 0 on success. - */ -int -resolve_vas_funcs(void) -{ - if (!libvas_handle) /* assert */ - return -1; - - RESOLVE_OR_ERR(v_ctx_alloc, "vas_ctx_alloc"); - RESOLVE_OR_ERR(v_ctx_free, "vas_ctx_free"); - RESOLVE_OR_ERR(v_id_alloc, "vas_id_alloc"); - RESOLVE_OR_ERR(v_id_free, "vas_id_free"); - RESOLVE_OR_ERR(v_id_establish_cred_keytab, "vas_id_establish_cred_keytab"); - RESOLVE_OR_ERR(v_user_init, "vas_user_init"); - RESOLVE_OR_ERR(v_user_free, "vas_user_free"); - RESOLVE_OR_ERR(v_group_init, "vas_group_init"); - RESOLVE_OR_ERR(v_group_free, "vas_group_free"); - RESOLVE_OR_ERR(v_user_is_member, "vas_user_is_member"); - RESOLVE_OR_ERR(v_err_get_string, "vas_err_get_string"); - - return 0; -} diff --git a/zlib/Makefile.in b/zlib/Makefile.in new file mode 100644 index 0000000..469db66 --- /dev/null +++ b/zlib/Makefile.in @@ -0,0 +1,123 @@ +# +# Copyright (c) 2011 Todd C. Miller +# +# Permission to use, copy, modify, and distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +# ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +# +# @configure_input@ +# + +#### Start of system configuration section. #### + +srcdir = @srcdir@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ + +# Compiler & tools to use +CC = @CC@ +LIBTOOL = @LIBTOOL@ + +# C preprocessor flags +CPPFLAGS = -I. -I$(srcdir) + +# Usually -O and/or -g +CFLAGS = @CFLAGS@ + +# OS dependent defines +DEFS = @OSDEFS@ + +#### End of system configuration section. #### + +SHELL = @SHELL@ + +LTOBJS = adler32.lo compress.lo crc32.lo deflate.lo gzclose.lo gzlib.lo \ + gzread.lo gzwrite.lo infback.lo inffast.lo inflate.lo inftrees.lo \ + trees.lo uncompr.lo zutil.lo + +all: libz.la + +Makefile: $(srcdir)/Makefile.in + (cd $(top_builddir) && ./config.status --file zlib/Makefile) + +.SUFFIXES: .c .h .lo + +.c.lo: + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $< + +libz.la: $(LTOBJS) + $(LIBTOOL) --mode=link $(CC) -o $@ $(LTOBJS) -no-install + +# Dependencies +adler32.lo: $(srcdir)/zutil.h $(srcdir)/zlib.h ./zconf.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/adler32.c +compress.lo: $(srcdir)/zlib.h ./zconf.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/compress.c +crc32.lo: $(srcdir)/zutil.h $(srcdir)/zlib.h ./zconf.h $(srcdir)/crc32.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/crc32.c +deflate.lo: $(srcdir)/deflate.h $(srcdir)/zutil.h $(srcdir)/zlib.h ./zconf.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/deflate.c +gzclose.lo: $(srcdir)/zlib.h ./zconf.h $(srcdir)/gzguts.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/gzclose.c +gzlib.lo: $(srcdir)/zlib.h ./zconf.h $(srcdir)/gzguts.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/gzlib.c +gzread.lo: $(srcdir)/zlib.h ./zconf.h $(srcdir)/gzguts.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/gzread.c +gzwrite.lo: $(srcdir)/zlib.h ./zconf.h $(srcdir)/gzguts.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/gzwrite.c +infback.lo: $(srcdir)/zutil.h $(srcdir)/zlib.h ./zconf.h $(srcdir)/inftrees.h $(srcdir)/inflate.h $(srcdir)/inffast.h $(srcdir)/inffixed.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/infback.c +inffast.lo: $(srcdir)/zutil.h $(srcdir)/zlib.h ./zconf.h $(srcdir)/inftrees.h $(srcdir)/inflate.h $(srcdir)/inffast.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/inffast.c +inflate.lo: $(srcdir)/zutil.h $(srcdir)/zlib.h ./zconf.h $(srcdir)/inftrees.h $(srcdir)/inflate.h $(srcdir)/inffast.h $(srcdir)/inffixed.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/inflate.c +inftrees.lo: $(srcdir)/zutil.h $(srcdir)/zlib.h ./zconf.h $(srcdir)/inftrees.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/inftrees.c +trees.lo: $(srcdir)/deflate.h $(srcdir)/zutil.h $(srcdir)/zlib.h ./zconf.h $(srcdir)/trees.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/trees.c +uncompr.lo: $(srcdir)/zlib.h ./zconf.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/uncompr.c +zutil.lo: $(srcdir)/zutil.h $(srcdir)/zlib.h ./zconf.h + $(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/zutil.c + +pre-install: + +install: + +install-dirs: + +install-binaries: + +install-includes: + +install-doc: + +install-plugin: + +uninstall: + +check: + +clean: + -$(LIBTOOL) --mode=clean rm -f *.lo *.o *.la *.a stamp-* core *.core core.* + +mostlyclean: clean + +distclean: clean + -rm -rf Makefile .libs zconf.h + +clobber: distclean + +realclean: distclean + rm -f TAGS tags + +cleandir: realclean -- 2.30.2