dc2ba353b6
Latest upstream/feature release, similar to Debian, see the ChangeLog excerpts available at http://cto.homelinux.net/usr/ports/devel/cvs-devel/ChangeLog page. This feature release/version, I think, would be quite useful for all those users who want to share and, or transfer their existing CVS repositories from Linux to FreeBSD machines. PR: ports/118033 Submitted by: Balwinder S Dheeman <bdheeman@gmail.com>
388 lines
11 KiB
Text
388 lines
11 KiB
Text
# Add support for overriding lookups in CVSROOT/passwd
|
|
# Specify --password-file <file> on the pserver command line to use it
|
|
# Initial patch from the Debian DSA team, adapted by Steve McIntyre.
|
|
# See README.Debian for more details.
|
|
diff -Nur src/cvs.h src/cvs.h
|
|
--- src/cvs.h 2005-10-02 16:17:20.000000000 +0100
|
|
+++ src/cvs.h 2006-08-19 01:20:33.000000000 +0100
|
|
@@ -371,6 +371,7 @@
|
|
extern int use_editor;
|
|
extern int cvswrite;
|
|
extern mode_t cvsumask;
|
|
+extern char *PasswordFileName;
|
|
|
|
/* Temp dir abstraction. */
|
|
/* From main.c. */
|
|
diff -Nur src/main.c src/main.c
|
|
--- src/main.c 2006-08-17 00:25:16.000000000 +0100
|
|
+++ src/main.c 2006-08-19 01:20:03.000000000 +0100
|
|
@@ -43,8 +43,7 @@
|
|
int noexec = 0;
|
|
int readonlyfs = 0;
|
|
int logoff = 0;
|
|
-
|
|
-
|
|
+char *PasswordFileName = NULL;
|
|
|
|
/***
|
|
***
|
|
@@ -519,6 +518,7 @@
|
|
{"help-commands", 0, NULL, 1},
|
|
{"help-synonyms", 0, NULL, 2},
|
|
{"help-options", 0, NULL, 4},
|
|
+ {"password-file", required_argument, NULL, 5},
|
|
#ifdef SERVER_SUPPORT
|
|
{"allow-root", required_argument, NULL, 3},
|
|
#endif /* SERVER_SUPPORT */
|
|
@@ -646,6 +646,10 @@
|
|
root_allow_add (optarg, gConfigPath);
|
|
break;
|
|
#endif /* SERVER_SUPPORT */
|
|
+ case 5:
|
|
+ /* --password-file */
|
|
+ PasswordFileName = xstrdup(optarg);
|
|
+ break;
|
|
case 'Q':
|
|
really_quiet = 1;
|
|
/* FALL THROUGH */
|
|
diff -Nur src/Makefile.in src/Makefile.in
|
|
--- src/Makefile.in 2005-10-03 14:37:18.000000000 +0100
|
|
+++ src/Makefile.in 2006-08-17 00:28:35.000000000 +0100
|
|
@@ -146,7 +146,7 @@
|
|
ls.$(OBJEXT) main.$(OBJEXT) mkmodules.$(OBJEXT) \
|
|
modules.$(OBJEXT) ms-buffer.$(OBJEXT) myndbm.$(OBJEXT) \
|
|
no_diff.$(OBJEXT) parseinfo.$(OBJEXT) patch.$(OBJEXT) \
|
|
- rcs.$(OBJEXT) rcscmds.$(OBJEXT) recurse.$(OBJEXT) \
|
|
+ rcs.$(OBJEXT) rcscmds.$(OBJEXT) readpw.$(OBJEXT) recurse.$(OBJEXT) \
|
|
release.$(OBJEXT) remove.$(OBJEXT) repos.$(OBJEXT) \
|
|
root.$(OBJEXT) rsh-client.$(OBJEXT) run.$(OBJEXT) \
|
|
scramble.$(OBJEXT) server.$(OBJEXT) stack.$(OBJEXT) \
|
|
@@ -349,6 +349,7 @@
|
|
patch.c \
|
|
rcs.c \
|
|
rcscmds.c \
|
|
+ readpw.c \
|
|
recurse.c \
|
|
release.c \
|
|
remove.c \
|
|
@@ -543,6 +544,7 @@
|
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/patch.Po@am__quote@
|
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rcs.Po@am__quote@
|
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rcscmds.Po@am__quote@
|
|
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readpw.Po@am__quote@
|
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/recurse.Po@am__quote@
|
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/release.Po@am__quote@
|
|
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/remove.Po@am__quote@
|
|
diff -Nur src/parseinfo.h src/parseinfo.h
|
|
--- src/parseinfo.h 2006-08-17 00:25:16.000000000 +0100
|
|
+++ src/parseinfo.h 2006-08-17 00:58:25.000000000 +0100
|
|
@@ -21,6 +21,7 @@
|
|
char *HistoryLogPath;
|
|
char *HistorySearchPath;
|
|
char *TmpDir;
|
|
+ char *PasswordFileName;
|
|
|
|
/* Should the logmsg be re-read during the do_verify phase?
|
|
* RereadLogAfterVerify=no|stat|yes
|
|
diff -Nur src/readpw.c src/readpw.c
|
|
--- src/readpw.c 1970-01-01 01:00:00.000000000 +0100
|
|
+++ src/readpw.c 2006-08-19 01:45:26.000000000 +0100
|
|
@@ -0,0 +1,158 @@
|
|
+/*
|
|
+ readpw.c - read the CVS password from an external file
|
|
+ Copyright (c) 2006 Martin Schulze <joey@infodrom.org>
|
|
+
|
|
+ This program is free software; you can redistribute it and/or modify
|
|
+ it under the terms of the GNU General Public License as published by
|
|
+ the Free Software Foundation; either version 2 of the License, or
|
|
+ (at your option) any later version.
|
|
+
|
|
+ This program is distributed in the hope that it will be useful,
|
|
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
+ GNU General Public License for more details.
|
|
+
|
|
+ You should have received a copy of the GNU General Public License
|
|
+ along with this program; if not, write to the Free Software
|
|
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
+*/
|
|
+
|
|
+#include <string.h>
|
|
+#include <stdio.h>
|
|
+#include <errno.h>
|
|
+#include <syslog.h>
|
|
+
|
|
+#define PWFILE "/tmp/work/cvs/cvs.passwd"
|
|
+
|
|
+/*
|
|
+ * Source: control_nextline() in dtaus.c from dtaus
|
|
+ */
|
|
+size_t readline (FILE *f, char **buf, unsigned int len)
|
|
+{
|
|
+ char line[100];
|
|
+ char tmp[100];
|
|
+ char *cp;
|
|
+ int i;
|
|
+
|
|
+ memset (line, 0, sizeof(line));
|
|
+ memset (*buf, 0, len);
|
|
+
|
|
+ cp = line;
|
|
+
|
|
+ while (!strlen(line) && (cp = fgets(line, 100, f))) {
|
|
+ if (strlen(line)) {
|
|
+ if (line[0] != '#') {
|
|
+ if (line[strlen(line)-1] != '\n') {
|
|
+ strcpy(tmp, line);
|
|
+ while (tmp[strlen(tmp)-1] != '\n' && (cp = fgets(tmp, 100, f)));
|
|
+ } else
|
|
+ line[strlen(line)-1] = '\0';
|
|
+ if (line[strlen(line)-1] == '\r')
|
|
+ line[strlen(line)-1] = '\0';
|
|
+ for (i=strlen(line);(line[i-1] == ' '||line[i-1] == '\t')&&i>0; i--)
|
|
+ line[i-1] = '\0';
|
|
+ } else
|
|
+ line[0] = '\0';
|
|
+ }
|
|
+ }
|
|
+ for (cp=line; *cp==' '; cp++);
|
|
+
|
|
+ if (strlen(cp)) {
|
|
+ memcpy(*buf, cp, strlen(cp) >= len ? len-1 : strlen(cp));
|
|
+ return (strlen (cp));
|
|
+ } else
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+#define MAXLINE 100
|
|
+#define PWLEN 20
|
|
+
|
|
+char *getpwline (const char *fname, const char *repository, const char *logname)
|
|
+{
|
|
+ FILE *f;
|
|
+ char buf[MAXLINE], *bp = buf;
|
|
+ static char line[MAXLINE];
|
|
+ int inrepo = 0;
|
|
+ char *cp;
|
|
+
|
|
+ memset (line, 0, sizeof (line));
|
|
+
|
|
+ if ((f = fopen (fname, "r")) == NULL) {
|
|
+ perror ("fopen");
|
|
+ return line;
|
|
+ }
|
|
+
|
|
+ while (readline (f, &bp, 50)) {
|
|
+ if (buf[0] == '/') {
|
|
+ syslog(LOG_ERR, "Looking for repo %s in %s\n", repository, buf);
|
|
+ if (!inrepo && !strcmp (buf, repository))
|
|
+ {
|
|
+ syslog(LOG_ERR, "matched repository %s\n", repository);
|
|
+ inrepo = 1;
|
|
+ }
|
|
+ else if (inrepo)
|
|
+ inrepo = 0;
|
|
+ } else {
|
|
+ if (inrepo) {
|
|
+ if ((cp = strchr (buf, ':')) != NULL) {
|
|
+ if ( (cp - buf) == strlen (logname)
|
|
+ && !strncmp (buf, logname, strlen (logname))) {
|
|
+ memcpy (line, buf, strlen(buf) >= MAXLINE ? MAXLINE-1 : strlen(buf));
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ if (ferror (f))
|
|
+ perror ("ferror");
|
|
+ if (fclose (f) < 0)
|
|
+ perror ("fclose");
|
|
+
|
|
+ return line;
|
|
+}
|
|
+
|
|
+/*
|
|
+*****************************************************************
|
|
+ */
|
|
+#ifdef TEST_READPW
|
|
+
|
|
+void getpasswd (const char *fname, const char *repository, const char *logname, char **pw, char **user)
|
|
+{
|
|
+ char *line;
|
|
+ char *cp, *xp;
|
|
+
|
|
+ memset (*pw, 0, PWLEN);
|
|
+ memset (*user, 0, PWLEN);
|
|
+
|
|
+ line = getpwline(fname, repository, logname);
|
|
+
|
|
+ if (line[0] == '\0')
|
|
+ return;
|
|
+
|
|
+ cp = strchr (line, ':');
|
|
+ cp++;
|
|
+
|
|
+ if ((xp = strchr (cp, ':')) != NULL) {
|
|
+ memcpy (*pw, cp, xp-cp >= PWLEN ? PWLEN-1 : xp-cp);
|
|
+
|
|
+ xp++;
|
|
+
|
|
+ if (strlen (xp))
|
|
+ memcpy (*user, xp, strlen(xp) >= PWLEN ? PWLEN-1 : strlen(xp));
|
|
+ }
|
|
+}
|
|
+
|
|
+int main ()
|
|
+{
|
|
+ char pw[PWLEN], *ppw = pw;
|
|
+ char cvsuser[PWLEN], *pcu = cvsuser;
|
|
+
|
|
+ getpasswd (PWFILE, "/cvs/debian-doc", "jseidel", &ppw, &pcu);
|
|
+
|
|
+ printf ("%s<:>%s\n", pw, cvsuser);
|
|
+ printf ("XXXXXXXXXXXXX\n");
|
|
+
|
|
+ return 0;
|
|
+}
|
|
+#endif /*TEST_READPW */
|
|
diff -Nur src/server.c src/server.c
|
|
--- src/server.c 2006-08-17 00:25:16.000000000 +0100
|
|
+++ src/server.c 2006-08-20 00:31:22.000000000 +0100
|
|
@@ -22,6 +22,8 @@
|
|
|
|
int server_active = 0;
|
|
|
|
+char *getpwline (const char *fname, const char *repository, const char *logname);
|
|
+
|
|
#if defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT)
|
|
|
|
# include "log-buffer.h"
|
|
@@ -6689,51 +6691,71 @@
|
|
{
|
|
int retval = 0;
|
|
FILE *fp;
|
|
- char *filename;
|
|
+ char *filename = NULL;
|
|
+ char *cp;
|
|
char *linebuf = NULL;
|
|
size_t linebuf_len;
|
|
int found_it = 0;
|
|
int namelen;
|
|
|
|
- /* We don't use current_parsed_root->directory because it hasn't been
|
|
- * set yet -- our `repository' argument came from the authentication
|
|
- * protocol, not the regular CVS protocol.
|
|
- */
|
|
-
|
|
- filename = xmalloc (strlen (repository)
|
|
- + 1
|
|
- + strlen (CVSROOTADM)
|
|
- + 1
|
|
- + strlen (CVSROOTADM_PASSWD)
|
|
- + 1);
|
|
+ if (!PasswordFileName)
|
|
+ {
|
|
+ /* We don't use current_parsed_root->directory because it hasn't been
|
|
+ * set yet -- our `repository' argument came from the authentication
|
|
+ * protocol, not the regular CVS protocol.
|
|
+ */
|
|
+
|
|
+ filename = xmalloc (strlen (repository)
|
|
+ + 1
|
|
+ + strlen (CVSROOTADM)
|
|
+ + 1
|
|
+ + strlen (CVSROOTADM_PASSWD)
|
|
+ + 1);
|
|
|
|
- (void) sprintf (filename, "%s/%s/%s", repository,
|
|
- CVSROOTADM, CVSROOTADM_PASSWD);
|
|
+ (void) sprintf (filename, "%s/%s/%s", repository,
|
|
+ CVSROOTADM, CVSROOTADM_PASSWD);
|
|
|
|
- fp = CVS_FOPEN (filename, "r");
|
|
- if (fp == NULL)
|
|
- {
|
|
- if (!existence_error (errno))
|
|
- error (0, errno, "cannot open %s", filename);
|
|
- free (filename);
|
|
- return 0;
|
|
- }
|
|
+ fp = CVS_FOPEN (filename, "r");
|
|
+ if (fp == NULL)
|
|
+ {
|
|
+ if (!existence_error (errno))
|
|
+ error (0, errno, "cannot open %s", filename);
|
|
+ free (filename);
|
|
+ return 0;
|
|
+ }
|
|
|
|
- /* Look for a relevant line -- one with this user's name. */
|
|
- namelen = strlen (username);
|
|
- while (getline (&linebuf, &linebuf_len, fp) >= 0)
|
|
- {
|
|
- if ((strncmp (linebuf, username, namelen) == 0)
|
|
- && (linebuf[namelen] == ':'))
|
|
- {
|
|
- found_it = 1;
|
|
- break;
|
|
- }
|
|
+ /* Look for a relevant line -- one with this user's name. */
|
|
+ namelen = strlen (username);
|
|
+ while (getline (&linebuf, &linebuf_len, fp) >= 0)
|
|
+ {
|
|
+ if ((strncmp (linebuf, username, namelen) == 0)
|
|
+ && (linebuf[namelen] == ':'))
|
|
+ {
|
|
+ found_it = 1;
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ if (ferror (fp))
|
|
+ error (0, errno, "cannot read %s", filename);
|
|
+ if (fclose (fp) < 0)
|
|
+ error (0, errno, "cannot close %s", filename);
|
|
+ }
|
|
+ else /* DSA_VERSION */
|
|
+ {
|
|
+ namelen = strlen (username);
|
|
+
|
|
+ cp = getpwline (PasswordFileName, repository, username);
|
|
+ /* syslog (LOG_NOTICE, "cp=%s", cp); */
|
|
+ if (strlen (cp)) {
|
|
+ linebuf = xmalloc (strlen (cp) + 1);
|
|
+ memcpy (linebuf, cp, strlen(cp)+1);
|
|
+ /* syslog (LOG_NOTICE, "line=%s", linebuf); */
|
|
+ found_it = 1;
|
|
+ } else
|
|
+ found_it = 0;
|
|
+
|
|
+ /* syslog (LOG_NOTICE, "username=%s, password=%s, repository=%s", username, password, repository); */
|
|
}
|
|
- if (ferror (fp))
|
|
- error (0, errno, "cannot read %s", filename);
|
|
- if (fclose (fp) < 0)
|
|
- error (0, errno, "cannot close %s", filename);
|
|
|
|
/* If found_it, then linebuf contains the information we need. */
|
|
if (found_it)
|
|
@@ -6823,6 +6845,7 @@
|
|
retval = 0;
|
|
}
|
|
|
|
+ if (filename)
|
|
free (filename);
|
|
if (linebuf)
|
|
free (linebuf);
|
|
@@ -7043,7 +7066,10 @@
|
|
letting you in if it won't say why, and I am not convinced
|
|
that the potential information disclosure to an attacker
|
|
outweighs this. */
|
|
- printf ("error 0 no such user %s in CVSROOT/passwd\n", username);
|
|
+ if (PasswordFileName)
|
|
+ printf ("error 0 no such user %s in %s\n", username, PasswordFileName);
|
|
+ else
|
|
+ printf ("error 0 no such user %s in CVSROOT/passwd\n", username);
|
|
|
|
exit (EXIT_FAILURE);
|
|
}
|