* passwd.c (longopts): Add --reg-store-pwd option.

(opts): Add -R option.
	(usage): Add text for -R/--reg-store-pwd option.
	(main): Fix size of local user and password string arrays.
	Handle -R option.
	* utils.sgml: Add text for passwd -R/--reg-store-pwd option.
This commit is contained in:
Corinna Vinschen 2008-11-26 10:19:09 +00:00
parent d4db08d7a6
commit d865502063
3 changed files with 110 additions and 17 deletions

View File

@ -1,3 +1,12 @@
2008-11-26 Corinna Vinschen <corinna@vinschen.de>
* passwd.c (longopts): Add --reg-store-pwd option.
(opts): Add -R option.
(usage): Add text for -R/--reg-store-pwd option.
(main): Fix size of local user and password string arrays.
Handle -R option.
* utils.sgml: Add text for passwd -R/--reg-store-pwd option.
2008-10-29 Christopher Faylor <me+cygwin@cgf.cx> 2008-10-29 Christopher Faylor <me+cygwin@cgf.cx>
* Makefile.in (ALL_LDFLAGS): Link libgcc statically for everything * Makefile.in (ALL_LDFLAGS): Link libgcc statically for everything

View File

@ -1,6 +1,6 @@
/* passwd.c: Changing passwords and managing account information /* passwd.c: Changing passwords and managing account information
Copyright 1999, 2000, 2001, 2002, 2003 Red Hat, Inc. Copyright 1999, 2000, 2001, 2002, 2003, 2008 Red Hat, Inc.
Written by Corinna Vinschen <corinna.vinschen@cityweb.de> Written by Corinna Vinschen <corinna.vinschen@cityweb.de>
@ -26,6 +26,7 @@ details. */
#include <sys/cygwin.h> #include <sys/cygwin.h>
#include <sys/types.h> #include <sys/types.h>
#include <time.h> #include <time.h>
#include <errno.h>
#define USER_PRIV_ADMIN 2 #define USER_PRIV_ADMIN 2
@ -50,10 +51,11 @@ static struct option longopts[] =
{"maxage", required_argument, NULL, 'x'}, {"maxage", required_argument, NULL, 'x'},
{"length", required_argument, NULL, 'L'}, {"length", required_argument, NULL, 'L'},
{"status", no_argument, NULL, 'S'}, {"status", no_argument, NULL, 'S'},
{ "reg-store-pwd", no_argument, NULL, 'R'},
{NULL, 0, NULL, 0} {NULL, 0, NULL, 0}
}; };
static char opts[] = "cCd:eEhi:ln:pPuvx:L:S"; static char opts[] = "cCd:eEhi:ln:pPuvx:L:SR";
int int
eprint (int with_name, const char *fmt, ...) eprint (int with_name, const char *fmt, ...)
@ -263,6 +265,9 @@ usage (FILE * stream, int status)
" password aging rule.\n" " password aging rule.\n"
" -p, --pwd-not-required no password required for USER.\n" " -p, --pwd-not-required no password required for USER.\n"
" -P, --pwd-required password is required for USER.\n" " -P, --pwd-required password is required for USER.\n"
" -R, --reg-store-pwd enter password to store it in the registry for\n"
" later usage by services to be able to switch\n"
" to this user context with network credentials.\n"
"\n" "\n"
"System operations:\n" "System operations:\n"
" -i, --inactive NUM set NUM of days before inactive accounts are disabled\n" " -i, --inactive NUM set NUM of days before inactive accounts are disabled\n"
@ -283,6 +288,15 @@ usage (FILE * stream, int status)
"operate on current user. System operations must not be mixed with user\n" "operate on current user. System operations must not be mixed with user\n"
"operations. Don't specify a USER when triggering a system operation.\n" "operations. Don't specify a USER when triggering a system operation.\n"
"\n" "\n"
"Don't specify a user or any other option together with the -R option.\n"
"Non-Admin users can only store their password if cygserver is running and\n"
"the CYGWIN environment variable is set to contain the word 'server'.\n"
"Note that storing even obfuscated passwords in the registry is not overly\n"
"secure. Use this feature only if the machine is adequately locked down.\n"
"Don't use this feature if you don't need network access within a remote\n"
"session. You can delete your stored password by using `passwd -R' and\n"
"specifying an empty password.\n"
"\n"
"Report bugs to <cygwin@cygwin.com>\n", prog_name); "Report bugs to <cygwin@cygwin.com>\n", prog_name);
exit (status); exit (status);
} }
@ -314,7 +328,7 @@ int
main (int argc, char **argv) main (int argc, char **argv)
{ {
char *c; char *c;
char user[64], oldpwd[64], newpwd[64]; char user[UNLEN + 1], oldpwd[_PASSWORD_LEN + 1], newpwd[_PASSWORD_LEN + 1];
int ret = 0; int ret = 0;
int cnt = 0; int cnt = 0;
int opt, len; int opt, len;
@ -331,6 +345,7 @@ main (int argc, char **argv)
int popt = 0; int popt = 0;
int Popt = 0; int Popt = 0;
int Sopt = 0; int Sopt = 0;
int Ropt = 0;
PUSER_INFO_3 ui, li; PUSER_INFO_3 ui, li;
LPWSTR server = NULL; LPWSTR server = NULL;
@ -353,20 +368,20 @@ main (int argc, char **argv)
break; break;
case 'i': case 'i':
if (lopt || uopt || copt || Copt || eopt || Eopt || popt || Popt || Sopt) if (lopt || uopt || copt || Copt || eopt || Eopt || popt || Popt || Sopt || Ropt)
usage (stderr, 1); usage (stderr, 1);
if ((iarg = atoi (optarg)) < 0 || iarg > 999) if ((iarg = atoi (optarg)) < 0 || iarg > 999)
return eprint (1, "Force logout time must be between 0 and 999."); return eprint (1, "Force logout time must be between 0 and 999.");
break; break;
case 'l': case 'l':
if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || uopt || Sopt) if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || uopt || Sopt || Ropt)
usage (stderr, 1); usage (stderr, 1);
lopt = 1; lopt = 1;
break; break;
case 'n': case 'n':
if (lopt || uopt || copt || Copt || eopt || Eopt || popt || Popt || Sopt) if (lopt || uopt || copt || Copt || eopt || Eopt || popt || Popt || Sopt || Ropt)
usage (stderr, 1); usage (stderr, 1);
if ((narg = atoi (optarg)) < 0 || narg > 999) if ((narg = atoi (optarg)) < 0 || narg > 999)
return eprint (1, "Minimum password age must be between 0 and 999."); return eprint (1, "Minimum password age must be between 0 and 999.");
@ -376,25 +391,27 @@ main (int argc, char **argv)
break; break;
case 'u': case 'u':
if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || lopt || Sopt) if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || lopt || Sopt || Ropt)
usage (stderr, 1); usage (stderr, 1);
uopt = 1; uopt = 1;
break; break;
case 'c': case 'c':
if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || Sopt) if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || Sopt || Ropt)
usage (stderr, 1); usage (stderr, 1);
copt = 1; copt = 1;
break; break;
case 'C': case 'C':
if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || Sopt) if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || Sopt || Ropt)
usage (stderr, 1); usage (stderr, 1);
Copt = 1; Copt = 1;
break; break;
case 'd': case 'd':
{ {
if (Ropt)
usage (stderr, 1);
char *tmpbuf = alloca (strlen (optarg) + 3); char *tmpbuf = alloca (strlen (optarg) + 3);
tmpbuf[0] = '\0'; tmpbuf[0] = '\0';
if (*optarg != '\\') if (*optarg != '\\')
@ -408,25 +425,25 @@ main (int argc, char **argv)
break; break;
case 'e': case 'e':
if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || Sopt) if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || Sopt || Ropt)
usage (stderr, 1); usage (stderr, 1);
eopt = 1; eopt = 1;
break; break;
case 'E': case 'E':
if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || Sopt) if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || Sopt || Ropt)
usage (stderr, 1); usage (stderr, 1);
Eopt = 1; Eopt = 1;
break; break;
case 'p': case 'p':
if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || Sopt) if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || Sopt || Ropt)
usage (stderr, 1); usage (stderr, 1);
popt = 1; popt = 1;
break; break;
case 'P': case 'P':
if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || Sopt) if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || Sopt || Ropt)
usage (stderr, 1); usage (stderr, 1);
Popt = 1; Popt = 1;
break; break;
@ -437,7 +454,7 @@ main (int argc, char **argv)
break; break;
case 'x': case 'x':
if (lopt || uopt || copt || Copt || eopt || Eopt || popt || Popt || Sopt) if (lopt || uopt || copt || Copt || eopt || Eopt || popt || Popt || Sopt || Ropt)
usage (stderr, 1); usage (stderr, 1);
if ((xarg = atoi (optarg)) < 0 || xarg > 999) if ((xarg = atoi (optarg)) < 0 || xarg > 999)
return eprint (1, "Maximum password age must be between 0 and 999."); return eprint (1, "Maximum password age must be between 0 and 999.");
@ -447,7 +464,7 @@ main (int argc, char **argv)
break; break;
case 'L': case 'L':
if (lopt || uopt || copt || Copt || eopt || Eopt || popt || Popt || Sopt) if (lopt || uopt || copt || Copt || eopt || Eopt || popt || Popt || Sopt || Ropt)
usage (stderr, 1); usage (stderr, 1);
if ((Larg = atoi (optarg)) < 0 || Larg > LM20_PWLEN) if ((Larg = atoi (optarg)) < 0 || Larg > LM20_PWLEN)
return eprint (1, "Minimum password length must be between " return eprint (1, "Minimum password length must be between "
@ -456,15 +473,45 @@ main (int argc, char **argv)
case 'S': case 'S':
if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || lopt || uopt if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || lopt || uopt
|| copt || Copt || eopt || Eopt || popt || Popt) || copt || Copt || eopt || Eopt || popt || Popt || Ropt)
usage (stderr, 1); usage (stderr, 1);
Sopt = 1; Sopt = 1;
break; break;
case 'R':
if (xarg >= 0 || narg >= 0 || iarg >= 0 || Larg >= 0 || lopt || uopt
|| copt || Copt || eopt || Eopt || popt || Popt || Sopt
|| server)
usage (stderr, 1);
Ropt = 1;
break;
default: default:
usage (stderr, 1); usage (stderr, 1);
} }
if (Ropt)
{
if (optind < argc)
usage (stderr, 1);
printf (
"This functionality stores a password in the registry for usage by services\n"
"which need to change the user context and require network access. Typical\n"
"applications are interactive remote logons using sshd, cron task, etc.\n"
"This password will always tried first when any privileged application is\n"
"about to switch the user context.\n\n"
"Note that storing even obfuscated passwords in the registry is not overly\n"
"secure. Use this feature only if the machine is adequately locked down.\n"
"Don't use this feature if you don't need network access within a remote\n"
"session. You can delete your stored password by specifying an empty password.\n\n");
strcpy (newpwd, getpass ("Enter your current password: "));
if (strcmp (newpwd, getpass ("Re-enter your current password: ")))
eprint (0, "Password is not identical.");
else if (cygwin_internal (CW_SET_PRIV_KEY, newpwd))
return eprint (0, "Storing password failed: %s", strerror (errno));
return 0;
}
if (!server) if (!server)
{ {
len = GetEnvironmentVariableW (L"LOGONSERVER", NULL, 0); len = GetEnvironmentVariableW (L"LOGONSERVER", NULL, 0);

View File

@ -899,6 +899,9 @@ User operations:
password aging rule. password aging rule.
-p, --pwd-not-required no password required for USER. -p, --pwd-not-required no password required for USER.
-P, --pwd-required password is required for USER. -P, --pwd-required password is required for USER.
-R, --reg-store-pwd enter password to store it in the registry for
later usage by services to be able to switch
to this user context with network credentials."
System operations: System operations:
-i, --inactive NUM set NUM of days before inactive accounts are disabled -i, --inactive NUM set NUM of days before inactive accounts are disabled
@ -916,6 +919,15 @@ Other options:
If no option is given, change USER's password. If no user name is given, If no option is given, change USER's password. If no user name is given,
operate on current user. System operations must not be mixed with user operate on current user. System operations must not be mixed with user
operations. Don't specify a USER when triggering a system operation. operations. Don't specify a USER when triggering a system operation.
Don't specify a user or any other option together with the -R option.
Non-Admin users can only store their password if cygserver is running and
the CYGWIN environment variable is set to contain the word 'server'.
Note that storing even obfuscated passwords in the registry is not overly
secure. Use this feature only if the machine is adequately locked down.
Don't use this feature if you don't need network access within a remote
session. You can delete your stored password by using `passwd -R' and
specifying an empty password.
</screen> </screen>
<para> <command>passwd</command> changes passwords for user accounts. <para> <command>passwd</command> changes passwords for user accounts.
@ -976,6 +988,31 @@ to <emphasis>LEN</emphasis> characters. Allowed values for the minimum
password length are 0 to 14. In any of the above cases, a value of 0 password length are 0 to 14. In any of the above cases, a value of 0
means `no restrictions'.</para> means `no restrictions'.</para>
<para>Users can use the <command>passwd -R</command> to enter
a password which then gets stored in a special area of the registry,
which is also used by Windows to store passwords of accounts running
Windows services. When a privileged Cygwin application calls the
<command>set{e}uid(user_id)</command> system call, Cygwin checks if a
password for that user has been stored in this registry area. If so, it
uses this password to switch to this user account using that password.
This allows to logon through, for instance, <command>ssh</command> with
public key authentication and to get a full qualified user token with
all credentials for network access. However, the method has some
drawbacks security-wise. This is explained in more detail in the
<xref linkend="ntsec"></xref> section.</para>
<para>Please note that storing password in that registry area is a
privileged operation which only administrative accounts are allowed to
do. If normal, non-admin users should be allowed to enter their
passwords using <command>passwd -R</command>, it's required to run
<command>cygserver</command> as a service under the LocalSystem account
and the environment variable CYGWIN
(see <xref linkend="using-cygwinenv"></xref>)
must be set to contain the "server" setting before running
<command>passwd -R</command>. This only affects storing passwords.
Using passwords in privileged processes does not require
<command>cygserver</command> to run.</para>
<para>Limitations: Users may not be able to change their password on <para>Limitations: Users may not be able to change their password on
some systems.</para> some systems.</para>