[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Nmh-workers] connecting to POP via an external command
From: |
Oliver Kiddle |
Subject: |
[Nmh-workers] connecting to POP via an external command |
Date: |
Tue, 25 Jan 2005 13:10:21 +0100 |
One of the patches I apply against the nmh sources is a modification of
Michael Richardson's patch which can be seen here:
http://www.mhonarc.org/archive/html/nmh-workers/2002-07/msg00000.html
My modification to it is to run a different command to get around a
firewall issue I have. Anyway, I've had a go at making the patch more
general by making the command configurable. This means both inc and
msgchk gain a -proxy option for specifying the external command. This is
very similar to fetchmail's plugin option (which is actually what I
normally use) and to ssh's ProxyCommand option.
There are a lot of different uses for this. I haven't tried but it should
make it simpler to use stunnel for SSL support: instead of stunnel
needing to listen on port 110 on the local host, you would just run
it with -proxy. If you look at the original patch, you'll see that it
can be used to run a pop daemon directly, perhaps through ssh or rsh.
My use is 'ssh othermachine netcat -w 1 %h 110' which allows me to go
via a different machine and so bypass a restrictive firewall. The patch
below substitutes the hostname for %h. I've omitted to reindent popsbr.c
so you can see the changes more clearly.
Any comments on this would be welcome.
Oliver
Index: h/popsbr.h
===================================================================
RCS file: /cvsroot/nmh/nmh/h/popsbr.h,v
retrieving revision 1.3
diff -u -r1.3 popsbr.h
--- h/popsbr.h 7 Jul 2000 03:48:03 -0000 1.3
+++ h/popsbr.h 25 Jan 2005 11:47:25 -0000
@@ -22,7 +22,7 @@
int pop_exists (int (*)());
#endif
-int pop_init (char *, char *, char *, int, int, int, int, char *);
+int pop_init (char *, char *, char *, char *, int, int, int, int, char *);
int pop_fd (char *, int, char *, int);
int pop_stat (int *, int *);
int pop_retr (int, int (*)());
Index: man/inc.man
===================================================================
RCS file: /cvsroot/nmh/nmh/man/inc.man,v
retrieving revision 1.13
diff -u -r1.13 inc.man
--- man/inc.man 25 Jan 2001 21:15:54 -0000 1.13
+++ man/inc.man 25 Jan 2005 11:47:25 -0000
@@ -32,6 +32,8 @@
.RB [ \-pack
.IR file ]
.RB [ \-nopack ]
+.RB [ \-proxy
+.IR command ]
.RB [ \-apop " | " \-noapop ]
.RB [ \-kpop ]
.RB [ \-sasl ]
@@ -231,6 +233,16 @@
.RI \*(lq .netrc \*(rq
file should be owned and readable only by you.
.PP
+If passed the
+.B \-proxy
+.I command
+switch,
+.B inc
+will use the specified command to establish the connection to the POP
+server. The string
+.IR %h
+in the command will be substituted by the hostname to connect to.
+.PP
If
.B inc
uses POP, then the
Index: uip/inc.c
===================================================================
RCS file: /cvsroot/nmh/nmh/uip/inc.c,v
retrieving revision 1.19
diff -u -r1.19 inc.c
--- uip/inc.c 12 Oct 2004 21:14:02 -0000 1.19
+++ uip/inc.c 25 Jan 2005 11:47:25 -0000
@@ -131,6 +131,8 @@
{ "sasl", SASLminc(-4) },
#define SASLMECHSW 25
{ "saslmech", SASLminc(-8) },
+#define PROXYSW 26
+ { "proxy command", POPminc(-5) },
{ NULL, 0 }
};
@@ -237,7 +239,7 @@
int kpop = 0, sasl = 0;
char *cp, *maildir, *folder = NULL;
char *format = NULL, *form = NULL;
- char *host = NULL, *user = NULL;
+ char *host = NULL, *user = NULL, *proxy = NULL;
char *audfile = NULL, *from = NULL, *saslmech = NULL;
char buf[BUFSIZ], **argp, *nfs, **arguments;
struct msgs *mp;
@@ -444,6 +446,10 @@
if (!(saslmech = *argp++) || *saslmech == '-')
adios (NULL, "missing argument to %s", argp[-2]);
continue;
+ case PROXYSW:
+ if (!(proxy = *argp++) || *proxy == '-')
+ adios (NULL, "missing argument to %s", argp[-2]);
+ continue;
}
}
if (*cp == '+' || *cp == '@') {
@@ -500,7 +506,7 @@
/*
* initialize POP connection
*/
- if (pop_init (host, user, pass, snoop, kpop ? 1 : rpop, kpop,
+ if (pop_init (host, user, pass, proxy, snoop, kpop ? 1 : rpop, kpop,
sasl, saslmech) == NOTOK)
adios (NULL, "%s", response);
Index: uip/msgchk.c
===================================================================
RCS file: /cvsroot/nmh/nmh/uip/msgchk.c,v
retrieving revision 1.10
diff -u -r1.10 msgchk.c
--- uip/msgchk.c 2 Jul 2002 22:09:14 -0000 1.10
+++ uip/msgchk.c 25 Jan 2005 11:47:26 -0000
@@ -85,6 +85,8 @@
{ "sasl", SASLminc(-4) },
#define SASLMECHSW 15
{ "saslmech", SASLminc(-5) },
+#define PROXYSW 16
+ { "proxy command", POPminc(-5) },
{ NULL, 0 }
};
@@ -115,7 +117,7 @@
static int checkmail (char *, char *, int, int, int);
#ifdef POP
-static int remotemail (char *, char *, int, int, int, int, int, int, char *);
+static int remotemail (char *, char *, char *, int, int, int, int, int, int,
char *);
#endif
@@ -127,7 +129,8 @@
int kpop = 0, sasl = 0;
int snoop = 0, vecp = 0;
uid_t uid;
- char *cp, *host = NULL, *user, buf[BUFSIZ], *saslmech = NULL;
+ char *cp, *host = NULL, *user, *proxy = NULL;
+ char buf[BUFSIZ], *saslmech = NULL;
char **argp, **arguments, *vec[MAXVEC];
struct passwd *pw;
@@ -237,6 +240,11 @@
if (!(saslmech = *argp++) || *saslmech == '-')
adios (NULL, "missing argument to %s", argp[-2]);
continue;
+
+ case PROXYSW:
+ if (!(proxy = *argp++) || *proxy == '-')
+ adios (NULL, "missing argument to %s", argp[-2]);
+ continue;
}
}
if (vecp >= MAXVEC-1)
@@ -286,12 +294,12 @@
kpop = 1;
}
if (vecp == 0) {
- status = remotemail (host, user, rpop, kpop, notifysw, 1, snoop,
- sasl, saslmech);
+ status = remotemail (host, user, proxy, rpop, kpop, notifysw, 1,
+ snoop, sasl, saslmech);
} else {
for (vecp = 0; vec[vecp]; vecp++)
- status += remotemail (host, vec[vecp], rpop, kpop, notifysw, 0,
- snoop, sasl, saslmech);
+ status += remotemail (host, vec[vecp], proxy, rpop, kpop,
+ notifysw, 0, snoop, sasl, saslmech);
}
} else {
#endif /* POP */
@@ -412,7 +420,7 @@
extern char response[];
static int
-remotemail (char *host, char *user, int rpop, int kpop, int notifysw, int
personal, int snoop, int sasl, char *saslmech)
+remotemail (char *host, char *user, char *proxy, int rpop, int kpop, int
notifysw, int personal, int snoop, int sasl, char *saslmech)
{
int nmsgs, nbytes, status;
char *pass = NULL;
@@ -425,7 +433,7 @@
ruserpass (host, &user, &pass);
/* open the POP connection */
- if (pop_init (host, user, pass, snoop, kpop ? 1 : rpop, kpop,
+ if (pop_init (host, user, pass, proxy, snoop, kpop ? 1 : rpop, kpop,
sasl, saslmech) == NOTOK
|| pop_stat (&nmsgs, &nbytes) == NOTOK /* check for messages
*/
|| pop_quit () == NOTOK) { /* quit POP connection
*/
Index: uip/popi.c
===================================================================
RCS file: /cvsroot/nmh/nmh/uip/popi.c,v
retrieving revision 1.7
diff -u -r1.7 popi.c
--- uip/popi.c 30 Sep 2003 16:58:43 -0000 1.7
+++ uip/popi.c 25 Jan 2005 11:47:26 -0000
@@ -214,7 +214,7 @@
}
snprintf (mailname, sizeof(mailname), "PO box for address@hidden", user,
host);
- if (pop_init (host, user, pass, snoop, rpop) == NOTOK)
+ if (pop_init (host, user, pass, NULL, snoop, rpop) == NOTOK)
adios (NULL, "%s", response);
if (rpop > 0)
setuid (getuid ());
Index: uip/popsbr.c
===================================================================
RCS file: /cvsroot/nmh/nmh/uip/popsbr.c,v
retrieving revision 1.9
diff -u -r1.9 popsbr.c
--- uip/popsbr.c 5 Sep 2003 21:07:49 -0000 1.9
+++ uip/popsbr.c 25 Jan 2005 11:47:26 -0000
@@ -444,13 +444,111 @@
}
#endif /* CYRUS_SASL */
+
+/*
+ * Split string containing proxy command into an array of arguments
+ * suitable for passing to exec. Returned array must be freed. Shouldn't
+ * be possible to call this with host set to NULL.
+ */
+char **
+parse_proxy(char *proxy, char *host)
+{
+ char **pargv, **p;
+ int pargc = 2;
+ int hlen = strlen(host);
+ int plen = 1;
+ char *cur, *pro;
+ char *c;
+
+ /* skip any initial space */
+ for (pro = proxy; isspace(*pro); pro++)
+ continue;
+
+ /* calculate required size for argument array */
+ for (cur = pro; *cur; cur++) {
+ if (isspace(*cur) && cur[1] && !isspace(cur[1]))
+ plen++, pargc++;
+ else if (*cur == '%' && cur[1] == 'h') {
+ plen += hlen;
+ cur++;
+ } else if (!isspace(*cur))
+ plen++;
+ }
+
+ /* put together list of arguments */
+ p = pargv = malloc(pargc * sizeof(char *));
+ c = *pargv = malloc(plen * sizeof(char));
+ for (cur = pro; *cur; cur++) {
+ if (isspace(*cur) && cur[1] && !isspace(cur[1])) {
+ *c++ = '\0';
+ *++p = c;
+ } else if (*cur == '%' && cur[1] == 'h') {
+ strcpy (c, host);
+ c += hlen;
+ cur++;
+ } else if (!isspace(*cur))
+ *c++ = *cur;
+ }
+ *++p = NULL;
+ return pargv;
+}
+
int
-pop_init (char *host, char *user, char *pass, int snoop, int rpop, int kpop,
- int sasl, char *mech)
+pop_init (char *host, char *user, char *pass, char *proxy, int snoop,
+ int rpop, int kpop, int sasl, char *mech)
{
int fd1, fd2;
char buffer[BUFSIZ];
+ if (proxy && *proxy) {
+ int pid;
+ int inpipe[2]; /* for reading from the server */
+ int outpipe[2]; /* for sending to the server */
+
+ /* first give up any root priviledges we may have for rpop */
+ setuid(getuid());
+
+ pipe(inpipe);
+ pipe(outpipe);
+
+ pid=fork();
+ if (pid==0) {
+ char **argv;
+
+ /* in child */
+ close(0);
+ close(1);
+ dup2(outpipe[0],0); /* connect read end of connection */
+ dup2(inpipe[1], 1); /* connect write end of connection */
+ if(inpipe[0]>1) close(inpipe[0]);
+ if(inpipe[1]>1) close(inpipe[1]);
+ if(outpipe[0]>1) close(outpipe[0]);
+ if(outpipe[1]>1) close(outpipe[1]);
+
+ /* run the proxy command */
+ argv=parse_proxy(proxy, host);
+ execvp(argv[0],argv);
+
+ perror(argv[0]);
+ close(0);
+ close(1);
+ free(*argv);
+ free(argv);
+ exit(10);
+ }
+
+ /* okay in the parent we do some stuff */
+ close(inpipe[1]); /* child uses this */
+ close(outpipe[0]); /* child uses this */
+
+ /* we read on fd1 */
+ fd1=inpipe[0];
+
+ /* and write on fd2 */
+ fd2=outpipe[1];
+
+ } else {
+
#ifdef APOP
int apop;
@@ -490,6 +588,7 @@
close (fd1);
return NOTOK;
}
+ }
#ifndef NNTP
if (pop_set (fd1, fd2, snoop) == NOTOK)
#else /* NNTP */
@@ -866,7 +965,7 @@
return NOTOK; /* unknown XTND command */
#endif /* NNTP */
}
-#endif BPOP
+#endif /* BPOP */
int
@@ -984,7 +1083,7 @@
#endif /* CYRUS_SASL */
fprintf (stderr, "<--- %s\n", response);
}
-#endif DEBUG
+#endif /* DEBUG */
if (strncmp (buffer, TRM, TRMLEN) == 0) {
if (buffer[TRMLEN] == 0)
return DONE;
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Nmh-workers] connecting to POP via an external command,
Oliver Kiddle <=