1 # Add support for overriding lookups in CVSROOT/passwd
2 # Specify --password-file <file> on the pserver command line to use it
3 # Initial patch from the Debian DSA team, adapted by Steve McIntyre.
4 # See README.Debian for more details.
5 diff -ruN cvs-1.12.13-old/src/cvs.h cvs-1.12.13/src/cvs.h
6 --- cvs-1.12.13-old/src/cvs.h 2005-10-02 16:17:20.000000000 +0100
7 +++ cvs-1.12.13/src/cvs.h 2006-08-19 01:20:33.000000000 +0100
11 extern mode_t cvsumask;
12 +extern char *PasswordFileName;
14 /* Temp dir abstraction. */
16 diff -ruN cvs-1.12.13-old/src/main.c cvs-1.12.13/src/main.c
17 --- cvs-1.12.13-old/src/main.c 2006-08-17 00:25:16.000000000 +0100
18 +++ cvs-1.12.13/src/main.c 2006-08-19 01:20:03.000000000 +0100
25 +char *PasswordFileName = NULL;
30 {"help-commands", 0, NULL, 1},
31 {"help-synonyms", 0, NULL, 2},
32 {"help-options", 0, NULL, 4},
33 + {"password-file", required_argument, NULL, 5},
35 {"allow-root", required_argument, NULL, 3},
36 #endif /* SERVER_SUPPORT */
38 root_allow_add (optarg, gConfigPath);
40 #endif /* SERVER_SUPPORT */
42 + /* --password-file */
43 + PasswordFileName = xstrdup(optarg);
48 diff -ruN cvs-1.12.13-old/src/Makefile.in cvs-1.12.13/src/Makefile.in
49 --- cvs-1.12.13-old/src/Makefile.in 2005-10-03 14:37:18.000000000 +0100
50 +++ cvs-1.12.13/src/Makefile.in 2006-08-17 00:28:35.000000000 +0100
52 ls.$(OBJEXT) main.$(OBJEXT) mkmodules.$(OBJEXT) \
53 modules.$(OBJEXT) ms-buffer.$(OBJEXT) myndbm.$(OBJEXT) \
54 no_diff.$(OBJEXT) parseinfo.$(OBJEXT) patch.$(OBJEXT) \
55 - rcs.$(OBJEXT) rcscmds.$(OBJEXT) recurse.$(OBJEXT) \
56 + rcs.$(OBJEXT) rcscmds.$(OBJEXT) readpw.$(OBJEXT) recurse.$(OBJEXT) \
57 release.$(OBJEXT) remove.$(OBJEXT) repos.$(OBJEXT) \
58 root.$(OBJEXT) rsh-client.$(OBJEXT) run.$(OBJEXT) \
59 scramble.$(OBJEXT) server.$(OBJEXT) stack.$(OBJEXT) \
69 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/patch.Po@am__quote@
70 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rcs.Po@am__quote@
71 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rcscmds.Po@am__quote@
72 +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/readpw.Po@am__quote@
73 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/recurse.Po@am__quote@
74 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/release.Po@am__quote@
75 @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/remove.Po@am__quote@
76 diff -ruN cvs-1.12.13-old/src/parseinfo.h cvs-1.12.13/src/parseinfo.h
77 --- cvs-1.12.13-old/src/parseinfo.h 2006-08-17 00:25:16.000000000 +0100
78 +++ cvs-1.12.13/src/parseinfo.h 2006-08-17 00:58:25.000000000 +0100
81 char *HistorySearchPath;
83 + char *PasswordFileName;
85 /* Should the logmsg be re-read during the do_verify phase?
86 * RereadLogAfterVerify=no|stat|yes
87 diff -ruN cvs-1.12.13-old/src/readpw.c cvs-1.12.13/src/readpw.c
88 --- cvs-1.12.13-old/src/readpw.c 1970-01-01 01:00:00.000000000 +0100
89 +++ cvs-1.12.13/src/readpw.c 2006-08-19 01:45:26.000000000 +0100
92 + readpw.c - read the CVS password from an external file
93 + Copyright (c) 2006 Martin Schulze <joey@infodrom.org>
95 + This program is free software; you can redistribute it and/or modify
96 + it under the terms of the GNU General Public License as published by
97 + the Free Software Foundation; either version 2 of the License, or
98 + (at your option) any later version.
100 + This program is distributed in the hope that it will be useful,
101 + but WITHOUT ANY WARRANTY; without even the implied warranty of
102 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
103 + GNU General Public License for more details.
105 + You should have received a copy of the GNU General Public License
106 + along with this program; if not, write to the Free Software
107 + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
115 +#define PWFILE "/tmp/work/cvs/cvs.passwd"
118 + * Source: control_nextline() in dtaus.c from dtaus
120 +size_t readline (FILE *f, char **buf, unsigned int len)
127 + memset (line, 0, sizeof(line));
128 + memset (*buf, 0, len);
132 + while (!strlen(line) && (cp = fgets(line, 100, f))) {
133 + if (strlen(line)) {
134 + if (line[0] != '#') {
135 + if (line[strlen(line)-1] != '\n') {
137 + while (tmp[strlen(tmp)-1] != '\n' && (cp = fgets(tmp, 100, f)));
139 + line[strlen(line)-1] = '\0';
140 + if (line[strlen(line)-1] == '\r')
141 + line[strlen(line)-1] = '\0';
142 + for (i=strlen(line);(line[i-1] == ' '||line[i-1] == '\t')&&i>0; i--)
148 + for (cp=line; *cp==' '; cp++);
151 + memcpy(*buf, cp, strlen(cp) >= len ? len-1 : strlen(cp));
152 + return (strlen (cp));
160 +char *getpwline (const char *fname, const char *repository, const char *logname)
163 + char buf[MAXLINE], *bp = buf;
164 + static char line[MAXLINE];
168 + memset (line, 0, sizeof (line));
170 + if ((f = fopen (fname, "r")) == NULL) {
175 + while (readline (f, &bp, 50)) {
176 + if (buf[0] == '/') {
177 + syslog(LOG_ERR, "Looking for repo %s in %s\n", repository, buf);
178 + if (!inrepo && !strcmp (buf, repository))
180 + syslog(LOG_ERR, "matched repository %s\n", repository);
187 + if ((cp = strchr (buf, ':')) != NULL) {
188 + if ( (cp - buf) == strlen (logname)
189 + && !strncmp (buf, logname, strlen (logname))) {
190 + memcpy (line, buf, strlen(buf) >= MAXLINE ? MAXLINE-1 : strlen(buf));
199 + if (fclose (f) < 0)
206 +*****************************************************************
210 +void getpasswd (const char *fname, const char *repository, const char *logname, char **pw, char **user)
215 + memset (*pw, 0, PWLEN);
216 + memset (*user, 0, PWLEN);
218 + line = getpwline(fname, repository, logname);
220 + if (line[0] == '\0')
223 + cp = strchr (line, ':');
226 + if ((xp = strchr (cp, ':')) != NULL) {
227 + memcpy (*pw, cp, xp-cp >= PWLEN ? PWLEN-1 : xp-cp);
232 + memcpy (*user, xp, strlen(xp) >= PWLEN ? PWLEN-1 : strlen(xp));
238 + char pw[PWLEN], *ppw = pw;
239 + char cvsuser[PWLEN], *pcu = cvsuser;
241 + getpasswd (PWFILE, "/cvs/debian-doc", "jseidel", &ppw, &pcu);
243 + printf ("%s<:>%s\n", pw, cvsuser);
244 + printf ("XXXXXXXXXXXXX\n");
248 +#endif /*TEST_READPW */
249 diff -ruN cvs-1.12.13-old/src/server.c cvs-1.12.13/src/server.c
250 --- cvs-1.12.13-old/src/server.c 2006-08-17 00:25:16.000000000 +0100
251 +++ cvs-1.12.13/src/server.c 2006-08-20 00:31:22.000000000 +0100
254 int server_active = 0;
256 +char *getpwline (const char *fname, const char *repository, const char *logname);
258 #if defined (SERVER_SUPPORT) || defined (CLIENT_SUPPORT)
260 # include "log-buffer.h"
261 @@ -6689,51 +6691,71 @@
266 + char *filename = NULL;
268 char *linebuf = NULL;
273 - /* We don't use current_parsed_root->directory because it hasn't been
274 - * set yet -- our `repository' argument came from the authentication
275 - * protocol, not the regular CVS protocol.
278 - filename = xmalloc (strlen (repository)
280 - + strlen (CVSROOTADM)
282 - + strlen (CVSROOTADM_PASSWD)
284 + if (!PasswordFileName)
286 + /* We don't use current_parsed_root->directory because it hasn't been
287 + * set yet -- our `repository' argument came from the authentication
288 + * protocol, not the regular CVS protocol.
291 + filename = xmalloc (strlen (repository)
293 + + strlen (CVSROOTADM)
295 + + strlen (CVSROOTADM_PASSWD)
298 - (void) sprintf (filename, "%s/%s/%s", repository,
299 - CVSROOTADM, CVSROOTADM_PASSWD);
300 + (void) sprintf (filename, "%s/%s/%s", repository,
301 + CVSROOTADM, CVSROOTADM_PASSWD);
303 - fp = CVS_FOPEN (filename, "r");
306 - if (!existence_error (errno))
307 - error (0, errno, "cannot open %s", filename);
311 + fp = CVS_FOPEN (filename, "r");
314 + if (!existence_error (errno))
315 + error (0, errno, "cannot open %s", filename);
320 - /* Look for a relevant line -- one with this user's name. */
321 - namelen = strlen (username);
322 - while (getline (&linebuf, &linebuf_len, fp) >= 0)
324 - if ((strncmp (linebuf, username, namelen) == 0)
325 - && (linebuf[namelen] == ':'))
330 + /* Look for a relevant line -- one with this user's name. */
331 + namelen = strlen (username);
332 + while (getline (&linebuf, &linebuf_len, fp) >= 0)
334 + if ((strncmp (linebuf, username, namelen) == 0)
335 + && (linebuf[namelen] == ':'))
342 + error (0, errno, "cannot read %s", filename);
343 + if (fclose (fp) < 0)
344 + error (0, errno, "cannot close %s", filename);
346 + else /* DSA_VERSION */
348 + namelen = strlen (username);
350 + cp = getpwline (PasswordFileName, repository, username);
351 + /* syslog (LOG_NOTICE, "cp=%s", cp); */
353 + linebuf = xmalloc (strlen (cp) + 1);
354 + memcpy (linebuf, cp, strlen(cp)+1);
355 + /* syslog (LOG_NOTICE, "line=%s", linebuf); */
360 + /* syslog (LOG_NOTICE, "username=%s, password=%s, repository=%s", username, password, repository); */
363 - error (0, errno, "cannot read %s", filename);
364 - if (fclose (fp) < 0)
365 - error (0, errno, "cannot close %s", filename);
367 /* If found_it, then linebuf contains the information we need. */
369 @@ -6823,6 +6845,7 @@
377 @@ -7043,7 +7066,10 @@
378 letting you in if it won't say why, and I am not convinced
379 that the potential information disclosure to an attacker
381 - printf ("error 0 no such user %s in CVSROOT/passwd\n", username);
382 + if (PasswordFileName)
383 + printf ("error 0 no such user %s in %s\n", username, PasswordFileName);
385 + printf ("error 0 no such user %s in CVSROOT/passwd\n", username);