summaryrefslogtreecommitdiffstats
path: root/contrib/cvs/src/login.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/cvs/src/login.c')
-rw-r--r--contrib/cvs/src/login.c595
1 files changed, 331 insertions, 264 deletions
diff --git a/contrib/cvs/src/login.c b/contrib/cvs/src/login.c
index fc3a178..cc277a6 100644
--- a/contrib/cvs/src/login.c
+++ b/contrib/cvs/src/login.c
@@ -12,7 +12,16 @@
#ifdef AUTH_CLIENT_SUPPORT /* This covers the rest of the file. */
+/* There seems to be very little agreement on which system header
+ getpass is declared in. With a lot of fancy autoconfiscation,
+ we could perhaps detect this, but for now we'll just rely on
+ _CRAY, since Cray is perhaps the only system on which our own
+ declaration won't work (some Crays declare the 2#$@% thing as
+ varadic, believe it or not). On Cray, getpass will be declared
+ in either stdlib.h or unistd.h. */
+#ifndef _CRAY
extern char *getpass ();
+#endif
#ifndef CVS_PASSWORD_FILE
#define CVS_PASSWORD_FILE ".cvspass"
@@ -21,40 +30,53 @@ extern char *getpass ();
/* If non-NULL, get_cvs_password() will just return this. */
static char *cvs_password = NULL;
+static char *construct_cvspass_filename PROTO ((void));
+
/* The return value will need to be freed. */
-char *
+static char *
construct_cvspass_filename ()
{
- char *homedir;
- char *passfile;
+ char *homedir;
+ char *passfile;
- /* Environment should override file. */
- if ((passfile = getenv ("CVS_PASSFILE")) != NULL)
- return xstrdup (passfile);
+ /* Environment should override file. */
+ if ((passfile = getenv ("CVS_PASSFILE")) != NULL)
+ return xstrdup (passfile);
- /* Construct absolute pathname to user's password file. */
- /* todo: does this work under OS/2 ? */
- homedir = get_homedir ();
- if (! homedir)
+ /* Construct absolute pathname to user's password file. */
+ /* todo: does this work under OS/2 ? */
+ homedir = get_homedir ();
+ if (! homedir)
{
- error (1, errno, "could not find out home directory");
- return (char *) NULL;
+ error (1, errno, "could not find out home directory");
+ return (char *) NULL;
}
-
- passfile =
- (char *) xmalloc (strlen (homedir) + strlen (CVS_PASSWORD_FILE) + 3);
- strcpy (passfile, homedir);
- strcat (passfile, "/");
- strcat (passfile, CVS_PASSWORD_FILE);
-
- /* Safety first and last, Scouts. */
- if (isfile (passfile))
- /* xchmod() is too polite. */
- chmod (passfile, 0600);
- return passfile;
+ passfile =
+ (char *) xmalloc (strlen (homedir) + strlen (CVS_PASSWORD_FILE) + 3);
+ strcpy (passfile, homedir);
+#ifndef NO_SLASH_AFTER_HOME
+ /* NO_SLASH_AFTER_HOME is defined for VMS, where foo:[bar]/.cvspass is not
+ a legal filename but foo:[bar].cvspass is. A more clean solution would
+ be something more along the lines of a "join a directory to a filename"
+ kind of thing.... */
+ strcat (passfile, "/");
+#endif
+ strcat (passfile, CVS_PASSWORD_FILE);
+
+ /* Safety first and last, Scouts. */
+ if (isfile (passfile))
+ /* xchmod() is too polite. */
+ chmod (passfile, 0600);
+
+ return passfile;
}
+static const char *const login_usage[] =
+{
+ "Usage: %s %s\n",
+ NULL
+};
/* Prompt for a password, and store it in the file "CVS/.cvspass".
*
@@ -84,309 +106,354 @@ login (argc, argv)
int argc;
char **argv;
{
- char *passfile;
- FILE *fp;
- char *typed_password, *found_password;
- char *linebuf = (char *) NULL;
- size_t linebuf_len;
- int root_len, already_entered = 0;
-
- /* Make this a "fully-qualified" CVSroot if necessary. */
- if (! strchr (CVSroot, '@'))
- {
- /* We need to prepend "user@host:". */
- char *tmp;
+ char *passfile;
+ FILE *fp;
+ char *typed_password, *found_password;
+ char *linebuf = (char *) NULL;
+ size_t linebuf_len;
+ int root_len, already_entered = 0;
- printf ("Repository \"%s\" not fully-qualified.\n", CVSroot);
- printf ("Please enter \"user@host:/path\": ");
- fflush (stdout);
- getline (&linebuf, &linebuf_len, stdin);
+ if (argc < 0)
+ usage (login_usage);
- tmp = xmalloc (strlen (linebuf) + 1);
-
- /* Give it some permanent storage. */
- strcpy (tmp, linebuf);
- tmp[strlen (linebuf) - 1] = '\0';
- CVSroot = tmp;
-
- /* Reset. */
- free (linebuf);
- linebuf = (char *) NULL;
+ if (CVSroot_method != pserver_method)
+ {
+ error (0, 0, "can only use pserver method with `login' command");
+ error (1, 0, "CVSROOT: %s", CVSroot_original);
}
-
- if (CVSroot[0] != ':')
+
+ if (! CVSroot_username)
{
- /* Then we need to prepend ":pserver:". */
- char *tmp;
-
- tmp = xmalloc (strlen (":pserver:") + strlen (CVSroot) + 1);
- strcpy (tmp, ":pserver:");
- strcat (tmp, CVSroot);
- CVSroot = tmp;
+ error (0, 0, "CVSROOT \"%s\" is not fully-qualified.",
+ CVSroot_original);
+ error (1, 0, "Please make sure to specify \"user@host\"!");
}
- /* Check to make sure it's fully-qualified before going on.
- * Fully qualified in this context means it has both a user and a
- * host:repos portion.
- */
- {
- char *r;
-
- /* After confirming that CVSroot is non-NULL, we skip past the
- initial ":pserver:" to test the rest of it. */
-
- if (! CVSroot)
- error (1, 0, "CVSroot is NULL");
- else if (! strchr ((r = (CVSroot + strlen (":pserver:"))), '@'))
- goto not_fqrn;
- else if (! strchr (r, ':'))
- goto not_fqrn;
-
- if (0) /* Lovely. */
- {
- not_fqrn:
- error (0, 0, "CVSroot not fully-qualified: %s", CVSroot);
- error (1, 0, "should be format user@host:/path/to/repository");
- }
- }
-
- /* CVSroot is now fully qualified and has ":pserver:" prepended.
- We'll print out most of it so user knows exactly what is being
- dealt with here. */
- {
- char *s;
- s = strchr (CVSroot, ':');
- s++;
- s = strchr (s, ':');
- s++;
-
- if (s == NULL)
- error (1, 0, "NULL CVSroot");
-
- printf ("(Logging in to %s)\n", s);
+ printf ("(Logging in to %s@%s)\n", CVSroot_username, CVSroot_hostname);
fflush (stdout);
- }
- passfile = construct_cvspass_filename ();
- typed_password = getpass ("CVS password: ");
- typed_password = scramble (typed_password);
+ passfile = construct_cvspass_filename ();
+ typed_password = getpass ("CVS password: ");
+ typed_password = scramble (typed_password);
- /* Force get_cvs_password() to use this one (when the client
- * confirms the new password with the server), instead of consulting
- * the file. We make a new copy because cvs_password will get
- * zeroed by connect_to_server().
- */
- cvs_password = xstrdup (typed_password);
+ /* Force get_cvs_password() to use this one (when the client
+ * confirms the new password with the server), instead of
+ * consulting the file. We make a new copy because cvs_password
+ * will get zeroed by connect_to_server(). */
- if (connect_to_pserver (NULL, NULL, 1) == 0)
+ cvs_password = xstrdup (typed_password);
+
+ if (connect_to_pserver (NULL, NULL, 1) == 0)
{
- /* The password is wrong, according to the server. */
- error (1, 0, "incorrect password");
+ /* The password is wrong, according to the server. */
+ error (1, 0, "incorrect password");
}
- /* IF we have a password for this "[user@]host:/path" already
- * THEN
- * IF it's the same as the password we read from the prompt
- * THEN
- * do nothing
- * ELSE
- * replace the old password with the new one
- * ELSE
- * append new entry to the end of the file.
- */
-
- root_len = strlen (CVSroot);
-
- /* Yes, the method below reads the user's password file twice. It's
- inefficient, but we're not talking about a gig of data here. */
-
- fp = fopen (passfile, "r");
- /* FIXME: should be printing a message if fp == NULL and not
- existence_error (errno). */
- if (fp != NULL)
+ /* IF we have a password for this "[user@]host:/path" already
+ * THEN
+ * IF it's the same as the password we read from the prompt
+ * THEN
+ * do nothing
+ * ELSE
+ * replace the old password with the new one
+ * ELSE
+ * append new entry to the end of the file.
+ */
+
+ root_len = strlen (CVSroot_original);
+
+ /* Yes, the method below reads the user's password file twice. It's
+ inefficient, but we're not talking about a gig of data here. */
+
+ fp = CVS_FOPEN (passfile, "r");
+ /* FIXME: should be printing a message if fp == NULL and not
+ existence_error (errno). */
+ if (fp != NULL)
{
- /* Check each line to see if we have this entry already. */
- while (getline (&linebuf, &linebuf_len, fp) >= 0)
+ /* Check each line to see if we have this entry already. */
+ while (getline (&linebuf, &linebuf_len, fp) >= 0)
{
- if (strncmp (CVSroot, linebuf, root_len) == 0)
- {
- already_entered = 1;
- break;
- }
- else
+ if (strncmp (CVSroot_original, linebuf, root_len) == 0)
{
- free (linebuf);
- linebuf = (char *) NULL;
+ already_entered = 1;
+ break;
}
}
- fclose (fp);
+ fclose (fp);
}
-
- if (already_entered)
+
+ if (already_entered)
{
- /* This user/host has a password in the file already. */
+ /* This user/host has a password in the file already. */
- strtok (linebuf, " ");
- found_password = strtok (NULL, "\n");
- if (strcmp (found_password, typed_password))
+ strtok (linebuf, " ");
+ found_password = strtok (NULL, "\n");
+ if (strcmp (found_password, typed_password))
{
- /* typed_password and found_password don't match, so we'll
- * have to update passfile. We replace the old password
- * with the new one by writing a tmp file whose contents are
- * exactly the same as passfile except that this one entry
- * gets typed_password instead of found_password. Then we
- * rename the tmp file on top of passfile.
- */
- char *tmp_name;
- FILE *tmp_fp;
-
- tmp_name = tmpnam (NULL);
- if ((tmp_fp = fopen (tmp_name, "w")) == NULL)
+ /* typed_password and found_password don't match, so we'll
+ * have to update passfile. We replace the old password
+ * with the new one by writing a tmp file whose contents are
+ * exactly the same as passfile except that this one entry
+ * gets typed_password instead of found_password. Then we
+ * rename the tmp file on top of passfile.
+ */
+ char *tmp_name;
+ FILE *tmp_fp;
+
+ tmp_name = cvs_temp_name ();
+ if ((tmp_fp = CVS_FOPEN (tmp_name, "w")) == NULL)
{
- error (1, errno, "unable to open temp file %s", tmp_name);
- return 1;
+ error (1, errno, "unable to open temp file %s", tmp_name);
+ return 1;
}
- chmod (tmp_name, 0600);
+ chmod (tmp_name, 0600);
- fp = fopen (passfile, "r");
- if (fp == NULL)
+ fp = CVS_FOPEN (passfile, "r");
+ if (fp == NULL)
{
- error (1, errno, "unable to open %s", passfile);
- return 1;
+ error (1, errno, "unable to open %s", passfile);
+ if (linebuf)
+ free (linebuf);
+ return 1;
}
- /* I'm not paranoid, they really ARE out to get me: */
- chmod (passfile, 0600);
+ /* I'm not paranoid, they really ARE out to get me: */
+ chmod (passfile, 0600);
- free (linebuf);
- linebuf = (char *) NULL;
- while (getline (&linebuf, &linebuf_len, fp) >= 0)
+ while (getline (&linebuf, &linebuf_len, fp) >= 0)
{
- if (strncmp (CVSroot, linebuf, root_len))
- fprintf (tmp_fp, "%s", linebuf);
- else
- fprintf (tmp_fp, "%s %s\n", CVSroot, typed_password);
+ if (strncmp (CVSroot_original, linebuf, root_len))
+ fprintf (tmp_fp, "%s", linebuf);
+ else
+ fprintf (tmp_fp, "%s %s\n", CVSroot_original,
+ typed_password);
- free (linebuf);
- linebuf = (char *) NULL;
}
- fclose (tmp_fp);
- fclose (fp);
- rename_file (tmp_name, passfile);
- chmod (passfile, 0600);
+ if (linebuf)
+ free (linebuf);
+ fclose (tmp_fp);
+ fclose (fp);
+ copy_file (tmp_name, passfile);
+ unlink_file (tmp_name);
+ chmod (passfile, 0600);
+ free (tmp_name);
}
}
- else
+ else
{
- if ((fp = fopen (passfile, "a")) == NULL)
+ if (linebuf)
+ free (linebuf);
+ if ((fp = CVS_FOPEN (passfile, "a")) == NULL)
{
- error (1, errno, "could not open %s", passfile);
- free (passfile);
- return 1;
+ error (1, errno, "could not open %s", passfile);
+ free (passfile);
+ return 1;
}
- fprintf (fp, "%s %s\n", CVSroot, typed_password);
- fclose (fp);
+ fprintf (fp, "%s %s\n", CVSroot_original, typed_password);
+ fclose (fp);
}
- /* Utter, total, raving paranoia, I know. */
- chmod (passfile, 0600);
- memset (typed_password, 0, strlen (typed_password));
- free (typed_password);
+ /* Utter, total, raving paranoia, I know. */
+ chmod (passfile, 0600);
+ memset (typed_password, 0, strlen (typed_password));
+ free (typed_password);
- free (passfile);
- free (cvs_password);
- cvs_password = NULL;
- return 0;
+ free (passfile);
+ free (cvs_password);
+ cvs_password = NULL;
+ return 0;
}
-/* todo: "cvs logout" could erase an entry from the file.
- * But to what purpose?
- */
-
/* Returns the _scrambled_ password. The server must descramble
before hashing and comparing. */
char *
get_cvs_password ()
{
- int found_it = 0;
- int root_len;
- char *password;
- char *linebuf = (char *) NULL;
- size_t linebuf_len;
- FILE *fp;
- char *passfile;
-
- /* If someone (i.e., login()) is calling connect_to_pserver() out of
- context, then assume they have supplied the correct, scrambled
- password. */
- if (cvs_password)
- return cvs_password;
-
- /* Environment should override file. */
- if ((password = getenv ("CVS_PASSWORD")) != NULL)
+ int found_it = 0;
+ int root_len;
+ char *password;
+ char *linebuf = (char *) NULL;
+ size_t linebuf_len;
+ FILE *fp;
+ char *passfile;
+
+ /* If someone (i.e., login()) is calling connect_to_pserver() out of
+ context, then assume they have supplied the correct, scrambled
+ password. */
+ if (cvs_password)
+ return cvs_password;
+
+ if (getenv ("CVS_PASSWORD") != NULL)
+ {
+ /* In previous versions of CVS one could specify a password in
+ CVS_PASSWORD. This is a bad idea, because in BSD variants
+ of unix anyone can see the environment variable with 'ps'.
+ But for users who were using that feature we want to at
+ least let them know what is going on. After printing this
+ warning, we should fall through to the regular error where
+ we tell them to run "cvs login" (unless they already ran
+ it, of course). */
+ error (0, 0, "CVS_PASSWORD is no longer supported; ignored");
+ }
+
+ /* Else get it from the file. First make sure that the CVSROOT
+ variable has the appropriate fields filled in. */
+
+ if (CVSroot_method != pserver_method)
+ {
+ error (0, 0, "can only call GET_CVS_PASSWORD with pserver method");
+ error (1, 0, "CVSROOT: %s", CVSroot_original);
+ }
+
+ if (! CVSroot_username)
{
- char *p;
- p = xstrdup (password);
- /* If we got it from the environment, then it wasn't properly
- scrambled. Since unscrambling is done on the server side, we
- need to transmit it scrambled. */
- p = scramble (p);
- return p;
+ error (0, 0, "CVSROOT \"%s\" is not fully-qualified.",
+ CVSroot_original);
+ error (1, 0, "Please make sure to specify \"user@host\"!");
}
- /* Else get it from the file. */
- passfile = construct_cvspass_filename ();
- fp = fopen (passfile, "r");
- if (fp == NULL)
+ passfile = construct_cvspass_filename ();
+ fp = CVS_FOPEN (passfile, "r");
+ if (fp == NULL)
{
- error (0, errno, "could not open %s", passfile);
- free (passfile);
- error (1, 0, "use \"cvs login\" to log in first");
+ error (0, errno, "could not open %s", passfile);
+ free (passfile);
+ error (1, 0, "use \"cvs login\" to log in first");
}
- root_len = strlen (CVSroot);
+ root_len = strlen (CVSroot_original);
- /* Check each line to see if we have this entry already. */
- while (getline (&linebuf, &linebuf_len, fp) >= 0)
+ /* Check each line to see if we have this entry already. */
+ while (getline (&linebuf, &linebuf_len, fp) >= 0)
{
- if (strncmp (CVSroot, linebuf, root_len) == 0)
- {
- /* This is it! So break out and deal with linebuf. */
- found_it = 1;
- break;
- }
- else
+ if (strncmp (CVSroot_original, linebuf, root_len) == 0)
{
- free (linebuf);
- linebuf = (char *) NULL;
+ /* This is it! So break out and deal with linebuf. */
+ found_it = 1;
+ break;
}
}
- if (found_it)
+ if (found_it)
{
- /* linebuf now contains the line with the password. */
- char *tmp;
-
- strtok (linebuf, " ");
- password = strtok (NULL, "\n");
-
- /* Give it permanent storage. */
- tmp = xmalloc (strlen (password) + 1);
- strcpy (tmp, password);
- tmp[strlen (password)] = '\0';
- memset (password, 0, strlen (password));
- free (linebuf);
- return tmp;
+ /* linebuf now contains the line with the password. */
+ char *tmp;
+
+ strtok (linebuf, " ");
+ password = strtok (NULL, "\n");
+
+ /* Give it permanent storage. */
+ tmp = xstrdup (password);
+ memset (password, 0, strlen (password));
+ free (linebuf);
+ return tmp;
}
- else
+ else
{
- error (0, 0, "cannot find password");
- error (0, 0, "use \"cvs login\" to log in first");
- error (1, 0, "or set the CVS_PASSWORD environment variable");
+ if (linebuf)
+ free (linebuf);
+ error (0, 0, "cannot find password");
+ error (1, 0, "use \"cvs login\" to log in first");
}
- /* NOTREACHED */
- return NULL;
+ /* NOTREACHED */
+ return NULL;
}
-#endif /* AUTH_CLIENT_SUPPORT from beginning of file. */
+static const char *const logout_usage[] =
+{
+ "Usage: %s %s\n",
+ NULL
+};
+
+/* Remove any entry for the CVSRoot repository found in "CVS/.cvspass". */
+int
+logout (argc, argv)
+ int argc;
+ char **argv;
+{
+ char *passfile;
+ FILE *fp;
+ char *tmp_name;
+ FILE *tmp_fp;
+ char *linebuf = (char *) NULL;
+ size_t linebuf_len;
+ int root_len, found = 0;
+
+ if (argc < 0)
+ usage (logout_usage);
+
+ if (CVSroot_method != pserver_method)
+ {
+ error (0, 0, "can only use pserver method with `logout' command");
+ error (1, 0, "CVSROOT: %s", CVSroot_original);
+ }
+
+ if (! CVSroot_username)
+ {
+ error (0, 0, "CVSROOT \"%s\" is not fully-qualified.",
+ CVSroot_original);
+ error (1, 0, "Please make sure to specify \"user@host\"!");
+ }
+
+ /* Hmm. Do we want a variant of this command which deletes _all_
+ the entries from the current .cvspass? Might be easier to
+ remember than "rm ~/.cvspass" but then again if people are
+ mucking with HOME (common in Win95 as the system doesn't set
+ it), then this variant of "cvs logout" might give a false sense
+ of security, in that it wouldn't delete entries from any
+ .cvspass files but the current one. */
+
+ printf ("(Logging out of %s@%s)\n", CVSroot_username, CVSroot_hostname);
+ fflush (stdout);
+ /* IF we have a password for this "[user@]host:/path" already
+ * THEN
+ * drop the entry
+ * ELSE
+ * do nothing
+ */
+
+ passfile = construct_cvspass_filename ();
+ tmp_name = cvs_temp_name ();
+ if ((tmp_fp = CVS_FOPEN (tmp_name, "w")) == NULL)
+ {
+ error (1, errno, "unable to open temp file %s", tmp_name);
+ return 1;
+ }
+ chmod (tmp_name, 0600);
+
+ root_len = strlen (CVSroot_original);
+
+ fp = CVS_FOPEN (passfile, "r");
+ if (fp == NULL)
+ error (1, errno, "Error opening %s", passfile);
+
+ /* Check each line to see if we have this entry. */
+ /* Copy only those lines that do not match this entry */
+ while (getline (&linebuf, &linebuf_len, fp) >= 0)
+ {
+ if (strncmp (CVSroot_original, linebuf, root_len))
+ fprintf (tmp_fp, "%s", linebuf);
+ else
+ found = TRUE;
+ }
+ if (linebuf)
+ free (linebuf);
+ fclose (fp);
+ fclose (tmp_fp);
+
+ if (! found)
+ {
+ printf ("Entry not found for %s\n", CVSroot_original);
+ unlink_file (tmp_name);
+ }
+ else
+ {
+ copy_file (tmp_name, passfile);
+ unlink_file (tmp_name);
+ chmod (passfile, 0600);
+ }
+ return 0;
+}
+
+#endif /* AUTH_CLIENT_SUPPORT from beginning of file. */
OpenPOWER on IntegriCloud