Mercurial > emacs
annotate lib-src/pop.c @ 22084:08f31e440c92
(system-tmp-directory): New variable.
(recover-session-finish): Unmark the current line
so that the file being used for recovery will not get deleted.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Sat, 16 May 1998 03:38:20 +0000 |
parents | aa5d46f74b6a |
children | bfaacbee089a |
rev | line source |
---|---|
9158 | 1 /* pop.c: client routines for talking to a POP3-protocol post-office server |
19018
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
2 Copyright (c) 1991, 1993, 1996, 1997 Free Software Foundation, Inc. |
9158 | 3 Written by Jonathan Kamens, jik@security.ov.com. |
4 | |
5 This file is part of GNU Emacs. | |
6 | |
7 GNU Emacs is free software; you can redistribute it and/or modify | |
8 it under the terms of the GNU General Public License as published by | |
9 the Free Software Foundation; either version 2, or (at your option) | |
10 any later version. | |
11 | |
12 GNU Emacs is distributed in the hope that it will be useful, | |
13 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 GNU General Public License for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with GNU Emacs; see the file COPYING. If not, write to | |
14186
ee40177f6c68
Update FSF's address in the preamble.
Erik Naggum <erik@naggum.no>
parents:
14036
diff
changeset
|
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
ee40177f6c68
Update FSF's address in the preamble.
Erik Naggum <erik@naggum.no>
parents:
14036
diff
changeset
|
20 Boston, MA 02111-1307, USA. */ |
9158 | 21 |
9613
530b4511e5b3
Only include ../src/config.h if HAVE_CONFIG_H is
Richard M. Stallman <rms@gnu.org>
parents:
9600
diff
changeset
|
22 #ifdef HAVE_CONFIG_H |
530b4511e5b3
Only include ../src/config.h if HAVE_CONFIG_H is
Richard M. Stallman <rms@gnu.org>
parents:
9600
diff
changeset
|
23 #define NO_SHORTNAMES /* Tell config not to load remap.h */ |
9592
132798b0352b
Include ../src/config.h.
Richard M. Stallman <rms@gnu.org>
parents:
9591
diff
changeset
|
24 #include <../src/config.h> |
9613
530b4511e5b3
Only include ../src/config.h if HAVE_CONFIG_H is
Richard M. Stallman <rms@gnu.org>
parents:
9600
diff
changeset
|
25 #else |
530b4511e5b3
Only include ../src/config.h if HAVE_CONFIG_H is
Richard M. Stallman <rms@gnu.org>
parents:
9600
diff
changeset
|
26 #define MAIL_USE_POP |
530b4511e5b3
Only include ../src/config.h if HAVE_CONFIG_H is
Richard M. Stallman <rms@gnu.org>
parents:
9600
diff
changeset
|
27 #endif |
9592
132798b0352b
Include ../src/config.h.
Richard M. Stallman <rms@gnu.org>
parents:
9591
diff
changeset
|
28 |
9613
530b4511e5b3
Only include ../src/config.h if HAVE_CONFIG_H is
Richard M. Stallman <rms@gnu.org>
parents:
9600
diff
changeset
|
29 #ifdef MAIL_USE_POP |
530b4511e5b3
Only include ../src/config.h if HAVE_CONFIG_H is
Richard M. Stallman <rms@gnu.org>
parents:
9600
diff
changeset
|
30 |
530b4511e5b3
Only include ../src/config.h if HAVE_CONFIG_H is
Richard M. Stallman <rms@gnu.org>
parents:
9600
diff
changeset
|
31 #ifdef HAVE_CONFIG_H |
530b4511e5b3
Only include ../src/config.h if HAVE_CONFIG_H is
Richard M. Stallman <rms@gnu.org>
parents:
9600
diff
changeset
|
32 /* Cancel these substitutions made in config.h */ |
530b4511e5b3
Only include ../src/config.h if HAVE_CONFIG_H is
Richard M. Stallman <rms@gnu.org>
parents:
9600
diff
changeset
|
33 #undef open |
9594
7461e7aa4f3c
(open, close, read, write): Add #undefs.
Richard M. Stallman <rms@gnu.org>
parents:
9592
diff
changeset
|
34 #undef read |
7461e7aa4f3c
(open, close, read, write): Add #undefs.
Richard M. Stallman <rms@gnu.org>
parents:
9592
diff
changeset
|
35 #undef write |
9613
530b4511e5b3
Only include ../src/config.h if HAVE_CONFIG_H is
Richard M. Stallman <rms@gnu.org>
parents:
9600
diff
changeset
|
36 #undef close |
530b4511e5b3
Only include ../src/config.h if HAVE_CONFIG_H is
Richard M. Stallman <rms@gnu.org>
parents:
9600
diff
changeset
|
37 #endif |
9158 | 38 |
39 #include <sys/types.h> | |
15102
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
40 #ifdef WINDOWSNT |
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
41 #include "ntlib.h" |
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
42 #include <winsock.h> |
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
43 #undef SOCKET_ERROR |
15108
442458addd50
(SEND, RECV): Renamed from send, recv.
Richard M. Stallman <rms@gnu.org>
parents:
15102
diff
changeset
|
44 #define RECV(s,buf,len,flags) recv(s,buf,len,flags) |
442458addd50
(SEND, RECV): Renamed from send, recv.
Richard M. Stallman <rms@gnu.org>
parents:
15102
diff
changeset
|
45 #define SEND(s,buf,len,flags) send(s,buf,len,flags) |
442458addd50
(SEND, RECV): Renamed from send, recv.
Richard M. Stallman <rms@gnu.org>
parents:
15102
diff
changeset
|
46 #define CLOSESOCKET(s) closesocket(s) |
15102
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
47 #else |
9158 | 48 #include <netinet/in.h> |
49 #include <sys/socket.h> | |
15108
442458addd50
(SEND, RECV): Renamed from send, recv.
Richard M. Stallman <rms@gnu.org>
parents:
15102
diff
changeset
|
50 #define RECV(s,buf,len,flags) read(s,buf,len) |
442458addd50
(SEND, RECV): Renamed from send, recv.
Richard M. Stallman <rms@gnu.org>
parents:
15102
diff
changeset
|
51 #define SEND(s,buf,len,flags) write(s,buf,len) |
442458addd50
(SEND, RECV): Renamed from send, recv.
Richard M. Stallman <rms@gnu.org>
parents:
15102
diff
changeset
|
52 #define CLOSESOCKET(s) close(s) |
15102
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
53 #endif |
9158 | 54 #include <pop.h> |
9600
f0d3266e07d7
Fix mismatch in conditionals.
Richard M. Stallman <rms@gnu.org>
parents:
9594
diff
changeset
|
55 |
9158 | 56 #ifdef sun |
57 #include <malloc.h> | |
9613
530b4511e5b3
Only include ../src/config.h if HAVE_CONFIG_H is
Richard M. Stallman <rms@gnu.org>
parents:
9600
diff
changeset
|
58 #endif /* sun */ |
9600
f0d3266e07d7
Fix mismatch in conditionals.
Richard M. Stallman <rms@gnu.org>
parents:
9594
diff
changeset
|
59 |
9158 | 60 #ifdef HESIOD |
61 #include <hesiod.h> | |
62 /* | |
63 * It really shouldn't be necessary to put this declaration here, but | |
64 * the version of hesiod.h that Athena has installed in release 7.2 | |
65 * doesn't declare this function; I don't know if the 7.3 version of | |
66 * hesiod.h does. | |
67 */ | |
68 extern struct servent *hes_getservbyname (/* char *, char * */); | |
69 #endif | |
9600
f0d3266e07d7
Fix mismatch in conditionals.
Richard M. Stallman <rms@gnu.org>
parents:
9594
diff
changeset
|
70 |
9158 | 71 #include <pwd.h> |
72 #include <netdb.h> | |
73 #include <errno.h> | |
74 #include <stdio.h> | |
19018
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
75 #ifdef STDC_HEADERS |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
76 #include <string.h> |
19978
83050d7e3f64
Use system header files instead of declaring C-library
Karl Heuer <kwzh@gnu.org>
parents:
19018
diff
changeset
|
77 #define index strchr |
83050d7e3f64
Use system header files instead of declaring C-library
Karl Heuer <kwzh@gnu.org>
parents:
19018
diff
changeset
|
78 #endif |
83050d7e3f64
Use system header files instead of declaring C-library
Karl Heuer <kwzh@gnu.org>
parents:
19018
diff
changeset
|
79 #ifdef STDC_HEADERS |
83050d7e3f64
Use system header files instead of declaring C-library
Karl Heuer <kwzh@gnu.org>
parents:
19018
diff
changeset
|
80 #include <stdlib.h> |
83050d7e3f64
Use system header files instead of declaring C-library
Karl Heuer <kwzh@gnu.org>
parents:
19018
diff
changeset
|
81 #endif |
83050d7e3f64
Use system header files instead of declaring C-library
Karl Heuer <kwzh@gnu.org>
parents:
19018
diff
changeset
|
82 #ifdef HAVE_UNISTD_H |
83050d7e3f64
Use system header files instead of declaring C-library
Karl Heuer <kwzh@gnu.org>
parents:
19018
diff
changeset
|
83 #include <unistd.h> |
19018
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
84 #endif |
9600
f0d3266e07d7
Fix mismatch in conditionals.
Richard M. Stallman <rms@gnu.org>
parents:
9594
diff
changeset
|
85 |
9158 | 86 #ifdef KERBEROS |
19018
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
87 # ifdef HAVE_KRB5_H |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
88 # include <krb5.h> |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
89 # endif |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
90 # ifdef HAVE_DES_H |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
91 # include <des.h> |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
92 # else |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
93 # ifdef HAVE_KERBEROSIV_DES_H |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
94 # include <kerberosIV/des.h> |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
95 # else |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
96 # ifdef HAVE_KERBEROS_DES_H |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
97 # include <kerberos/des.h> |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
98 # endif |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
99 # endif |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
100 # endif |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
101 # ifdef HAVE_KRB_H |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
102 # include <krb.h> |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
103 # else |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
104 # ifdef HAVE_KERBEROSIV_KRB_H |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
105 # include <kerberosIV/krb.h> |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
106 # else |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
107 # ifdef HAVE_KERBEROS_KRB_H |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
108 # include <kerberos/krb.h> |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
109 # endif |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
110 # endif |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
111 # endif |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
112 # ifdef HAVE_COM_ERR_H |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
113 # include <com_err.h> |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
114 # endif |
9613
530b4511e5b3
Only include ../src/config.h if HAVE_CONFIG_H is
Richard M. Stallman <rms@gnu.org>
parents:
9600
diff
changeset
|
115 #endif /* KERBEROS */ |
9158 | 116 |
9613
530b4511e5b3
Only include ../src/config.h if HAVE_CONFIG_H is
Richard M. Stallman <rms@gnu.org>
parents:
9600
diff
changeset
|
117 #ifdef KERBEROS |
19018
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
118 #ifndef KERBEROS5 |
9158 | 119 extern int krb_sendauth (/* long, int, KTEXT, char *, char *, char *, |
9613
530b4511e5b3
Only include ../src/config.h if HAVE_CONFIG_H is
Richard M. Stallman <rms@gnu.org>
parents:
9600
diff
changeset
|
120 u_long, MSG_DAT *, CREDENTIALS *, Key_schedule, |
530b4511e5b3
Only include ../src/config.h if HAVE_CONFIG_H is
Richard M. Stallman <rms@gnu.org>
parents:
9600
diff
changeset
|
121 struct sockaddr_in *, struct sockaddr_in *, |
530b4511e5b3
Only include ../src/config.h if HAVE_CONFIG_H is
Richard M. Stallman <rms@gnu.org>
parents:
9600
diff
changeset
|
122 char * */); |
9158 | 123 extern char *krb_realmofhost (/* char * */); |
19018
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
124 #endif /* ! KERBEROS5 */ |
9613
530b4511e5b3
Only include ../src/config.h if HAVE_CONFIG_H is
Richard M. Stallman <rms@gnu.org>
parents:
9600
diff
changeset
|
125 #endif /* KERBEROS */ |
9158 | 126 |
15102
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
127 #ifndef WINDOWSNT |
9613
530b4511e5b3
Only include ../src/config.h if HAVE_CONFIG_H is
Richard M. Stallman <rms@gnu.org>
parents:
9600
diff
changeset
|
128 #if !defined(HAVE_H_ERRNO) || !defined(HAVE_CONFIG_H) |
9158 | 129 extern int h_errno; |
130 #endif | |
15102
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
131 #endif |
9158 | 132 |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
133 #ifndef _P |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
134 # ifdef __STDC__ |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
135 # define _P(a) a |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
136 # else |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
137 # define _P(a) () |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
138 # endif /* __STDC__ */ |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
139 #endif /* ! __P */ |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
140 |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
141 static int socket_connection _P((char *, int)); |
21295
f399e51d6d11
(pop_getline): Renamed from getline.
Richard M. Stallman <rms@gnu.org>
parents:
20418
diff
changeset
|
142 static int pop_getline _P((popserver, char **)); |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
143 static int sendline _P((popserver, char *)); |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
144 static int fullwrite _P((int, char *, int)); |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
145 static int getok _P((popserver)); |
9158 | 146 #if 0 |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
147 static int gettermination _P((popserver)); |
9158 | 148 #endif |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
149 static void pop_trash _P((popserver)); |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
150 static char *find_crlf _P((char *, int)); |
9591
0774e217e8aa
Don't declare malloc, realloc, free.
Richard M. Stallman <rms@gnu.org>
parents:
9158
diff
changeset
|
151 |
9158 | 152 #define ERROR_MAX 80 /* a pretty arbitrary size */ |
153 #define POP_PORT 110 | |
154 #define KPOP_PORT 1109 | |
15102
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
155 #ifdef WINDOWSNT |
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
156 #define POP_SERVICE "pop3" /* we don't want the POP2 port! */ |
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
157 #else |
9158 | 158 #define POP_SERVICE "pop" |
15102
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
159 #endif |
9158 | 160 #ifdef KERBEROS |
161 #define KPOP_SERVICE "kpop" | |
162 #endif | |
163 | |
21397 | 164 #ifdef GSSAPI |
165 # ifdef HAVE_GSSAPI_H | |
166 # include <gssapi.h> | |
167 # else | |
168 # include <gssapi/gssapi.h> | |
169 # endif | |
170 #define GSSAPI_SERVICE "pop" | |
171 static int pop_auth (/* popserver server, char *user, | |
172 char *host, int flags */); | |
173 static void gen_gss_error (/* char *msg, OM_uint32 major, OM_uint32 minor */); | |
174 struct _pop_gssapi | |
175 { | |
176 int gss_flags; /* encryption? integrity protection? */ | |
177 OM_uint32 max_size; /* max size we can send the server */ | |
178 gss_ctx_id_t gss_context; /* the security context */ | |
179 }; | |
180 #define GSSAPI_NOPROT 0x01 | |
181 #define GSSAPI_INTEGRITY 0x02 | |
182 #define GSSAPI_PRIVACY 0x04 | |
183 #define GSSAPI_NEEDWRAP (GSSAPI_INTEGRITY|GSSAPI_PRIVACY) | |
184 #define GSSAPI_PROTECTION (GSSAPI_NOPROT|GSSAPI_INTEGRITY|GSSAPI_PRIVACY) | |
185 #define GSSAPI_RCVBUF 1024 | |
186 #define GSSAPI_SVC_TYPE {10, "\052\206\110\206\367\022\001\002\001\004"} | |
187 #define Gssapi(data) ((struct _pop_gssapi *) (data)) | |
188 | |
189 static int b64_decode (/* char *enc, gss_buffer_t dec */); | |
190 static int b64_encode (/* gss_buffer_t dec, char **enc */); | |
191 #define B64_SUCCESS 0 | |
192 #define B64_BADPARAM 1 | |
193 #define B64_BADCHAR 2 | |
194 #define B64_BADPAD 3 | |
195 #define B64_BADLEN 4 | |
196 #define B64_NOMEM 5 | |
197 static char *b64_error[] = | |
198 { | |
199 "Success", | |
200 "Bad parameters", | |
201 "Bad characters in encoding", | |
202 "Bad padding in encoding", | |
203 "Bad length", | |
204 "Out of memory" | |
205 }; | |
206 | |
207 /* | |
208 * This function is only needed if you are using the GSSAPI protection | |
209 * mechanisms; it keeps trying until it has read the requested number | |
210 * bytes from the passed-in fd. | |
211 */ | |
212 static int fullread (/* int fd, char *buf, int nbytes */); | |
213 #endif /* GSSAPI */ | |
214 | |
9158 | 215 char pop_error[ERROR_MAX]; |
216 int pop_debug = 0; | |
217 | |
218 #ifndef min | |
219 #define min(a,b) (((a) < (b)) ? (a) : (b)) | |
220 #endif | |
221 | |
222 /* | |
223 * Function: pop_open (char *host, char *username, char *password, | |
224 * int flags) | |
225 * | |
226 * Purpose: Establishes a connection with a post-office server, and | |
227 * completes the authorization portion of the session. | |
228 * | |
229 * Arguments: | |
230 * host The server host with which the connection should be | |
231 * established. Optional. If omitted, internal | |
232 * heuristics will be used to determine the server host, | |
233 * if possible. | |
234 * username | |
235 * The username of the mail-drop to access. Optional. | |
236 * If omitted, internal heuristics will be used to | |
237 * determine the username, if possible. | |
238 * password | |
239 * The password to use for authorization. If omitted, | |
240 * internal heuristics will be used to determine the | |
241 * password, if possible. | |
242 * flags A bit mask containing flags controlling certain | |
243 * functions of the routine. Valid flags are defined in | |
244 * the file pop.h | |
245 * | |
246 * Return value: Upon successful establishment of a connection, a | |
247 * non-null popserver will be returned. Otherwise, null will be | |
248 * returned, and the string variable pop_error will contain an | |
249 * explanation of the error. | |
250 */ | |
251 popserver | |
252 pop_open (host, username, password, flags) | |
253 char *host; | |
254 char *username; | |
255 char *password; | |
256 int flags; | |
257 { | |
258 int sock; | |
259 popserver server; | |
260 | |
261 /* Determine the user name */ | |
262 if (! username) | |
263 { | |
264 username = getenv ("USER"); | |
265 if (! (username && *username)) | |
266 { | |
267 username = getlogin (); | |
268 if (! (username && *username)) | |
269 { | |
270 struct passwd *passwd; | |
271 passwd = getpwuid (getuid ()); | |
272 if (passwd && passwd->pw_name && *passwd->pw_name) | |
273 { | |
274 username = passwd->pw_name; | |
275 } | |
276 else | |
277 { | |
278 strcpy (pop_error, "Could not determine username"); | |
279 return (0); | |
280 } | |
281 } | |
282 } | |
283 } | |
284 | |
285 /* | |
286 * Determine the mail host. | |
287 */ | |
288 | |
289 if (! host) | |
290 { | |
291 host = getenv ("MAILHOST"); | |
292 } | |
293 | |
294 #ifdef HESIOD | |
295 if ((! host) && (! (flags & POP_NO_HESIOD))) | |
296 { | |
297 struct hes_postoffice *office; | |
298 office = hes_getmailhost (username); | |
299 if (office && office->po_type && (! strcmp (office->po_type, "POP")) | |
300 && office->po_name && *office->po_name && office->po_host | |
301 && *office->po_host) | |
302 { | |
303 host = office->po_host; | |
304 username = office->po_name; | |
305 } | |
306 } | |
307 #endif | |
308 | |
309 #ifdef MAILHOST | |
310 if (! host) | |
311 { | |
312 host = MAILHOST; | |
313 } | |
314 #endif | |
315 | |
316 if (! host) | |
317 { | |
318 strcpy (pop_error, "Could not determine POP server"); | |
319 return (0); | |
320 } | |
321 | |
322 /* Determine the password */ | |
21397 | 323 #if defined(KERBEROS) || defined(GSSAPI) |
324 # ifdef KERBEROS | |
325 # define NO_KERBEROS POP_NO_KERBEROS | |
326 # else | |
327 # define NO_KERBEROS 0 | |
328 # endif /* KERBEROS */ | |
329 | |
330 # ifdef GSSAPI | |
331 # define NO_GSSAPI POP_NO_GSSAPI | |
332 # else | |
333 # define NO_GSSAPI 0 | |
334 # endif /* GSSAPI */ | |
335 | |
336 # define DONT_NEED_PASSWORD (! (flags & (NO_KERBEROS | NO_GSSAPI))) | |
9158 | 337 #else |
21397 | 338 # define DONT_NEED_PASSWORD 0 |
9158 | 339 #endif |
340 | |
341 if ((! password) && (! DONT_NEED_PASSWORD)) | |
342 { | |
343 if (! (flags & POP_NO_GETPASS)) | |
344 { | |
345 password = getpass ("Enter POP password:"); | |
346 } | |
347 if (! password) | |
348 { | |
349 strcpy (pop_error, "Could not determine POP password"); | |
350 return (0); | |
351 } | |
352 } | |
353 if (password) | |
21397 | 354 flags |= POP_NO_KERBEROS | (!(flags & POP_NO_NOPROT) ? POP_NO_GSSAPI : 0); |
9158 | 355 else |
356 password = username; | |
357 | |
358 sock = socket_connection (host, flags); | |
359 if (sock == -1) | |
360 return (0); | |
361 | |
362 server = (popserver) malloc (sizeof (struct _popserver)); | |
363 if (! server) | |
364 { | |
365 strcpy (pop_error, "Out of memory in pop_open"); | |
366 return (0); | |
367 } | |
368 server->buffer = (char *) malloc (GETLINE_MIN); | |
369 if (! server->buffer) | |
370 { | |
371 strcpy (pop_error, "Out of memory in pop_open"); | |
372 free ((char *) server); | |
373 return (0); | |
374 } | |
375 | |
376 server->file = sock; | |
377 server->data = 0; | |
378 server->buffer_index = 0; | |
379 server->buffer_size = GETLINE_MIN; | |
380 server->in_multi = 0; | |
15102
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
381 server->trash_started = 0; |
21397 | 382 server->extra = 0; |
9158 | 383 |
384 if (getok (server)) | |
385 return (0); | |
386 | |
21397 | 387 #ifdef GSSAPI |
388 /* | |
389 * unless forbidden to use GSSAPI, try the GSSAPI AUTH mechanism..first. | |
390 */ | |
391 pop_error[0] = '\0'; /* so we can detect errors later... */ | |
392 if (! (flags & POP_NO_GSSAPI)) | |
393 { | |
394 int ret; | |
395 | |
396 ret = pop_auth (server, username, host, flags); | |
397 if (ret == 0) | |
398 { | |
399 return (server); | |
400 } | |
401 else if (ret == -2) | |
402 { | |
403 pop_close (server); | |
404 return (0); | |
405 } | |
406 } | |
407 #endif /* GSSAPI */ | |
408 /* | |
409 * POP_NO_NOPROT is used in the case that we want protection; if | |
410 * the authentication negotiation failed, then we want to fail now. | |
411 */ | |
412 if ((flags & POP_NO_NOPROT)) | |
413 { | |
414 pop_close (server); | |
415 #ifdef GSSAPI | |
416 if (pop_error[0] == '\0') | |
417 #endif | |
418 strcpy (pop_error, "Unable to provide protection"); | |
419 return (0); | |
420 } | |
421 | |
9158 | 422 /* |
423 * I really shouldn't use the pop_error variable like this, but.... | |
424 */ | |
425 if (strlen (username) > ERROR_MAX - 6) | |
426 { | |
427 pop_close (server); | |
428 strcpy (pop_error, | |
429 "Username too long; recompile pop.c with larger ERROR_MAX"); | |
430 return (0); | |
431 } | |
432 sprintf (pop_error, "USER %s", username); | |
433 | |
434 if (sendline (server, pop_error) || getok (server)) | |
435 { | |
436 return (0); | |
437 } | |
438 | |
439 if (strlen (password) > ERROR_MAX - 6) | |
440 { | |
441 pop_close (server); | |
442 strcpy (pop_error, | |
443 "Password too long; recompile pop.c with larger ERROR_MAX"); | |
444 return (0); | |
445 } | |
446 sprintf (pop_error, "PASS %s", password); | |
447 | |
448 if (sendline (server, pop_error) || getok (server)) | |
449 { | |
450 return (0); | |
451 } | |
452 | |
453 return (server); | |
454 } | |
455 | |
456 /* | |
457 * Function: pop_stat | |
458 * | |
459 * Purpose: Issue the STAT command to the server and return (in the | |
460 * value parameters) the number of messages in the maildrop and | |
461 * the total size of the maildrop. | |
462 * | |
463 * Return value: 0 on success, or non-zero with an error in pop_error | |
464 * in failure. | |
465 * | |
466 * Side effects: On failure, may make further operations on the | |
467 * connection impossible. | |
468 */ | |
469 int | |
470 pop_stat (server, count, size) | |
471 popserver server; | |
472 int *count; | |
473 int *size; | |
474 { | |
475 char *fromserver; | |
476 | |
477 if (server->in_multi) | |
478 { | |
479 strcpy (pop_error, "In multi-line query in pop_stat"); | |
480 return (-1); | |
481 } | |
482 | |
21295
f399e51d6d11
(pop_getline): Renamed from getline.
Richard M. Stallman <rms@gnu.org>
parents:
20418
diff
changeset
|
483 if (sendline (server, "STAT") || (pop_getline (server, &fromserver) < 0)) |
9158 | 484 return (-1); |
485 | |
486 if (strncmp (fromserver, "+OK ", 4)) | |
487 { | |
488 if (0 == strncmp (fromserver, "-ERR", 4)) | |
489 { | |
490 strncpy (pop_error, fromserver, ERROR_MAX); | |
491 } | |
492 else | |
493 { | |
494 strcpy (pop_error, | |
495 "Unexpected response from POP server in pop_stat"); | |
496 pop_trash (server); | |
497 } | |
498 return (-1); | |
499 } | |
500 | |
501 *count = atoi (&fromserver[4]); | |
502 | |
503 fromserver = index (&fromserver[4], ' '); | |
504 if (! fromserver) | |
505 { | |
506 strcpy (pop_error, | |
507 "Badly formatted response from server in pop_stat"); | |
508 pop_trash (server); | |
509 return (-1); | |
510 } | |
511 | |
512 *size = atoi (fromserver + 1); | |
513 | |
514 return (0); | |
515 } | |
516 | |
517 /* | |
518 * Function: pop_list | |
519 * | |
520 * Purpose: Performs the POP "list" command and returns (in value | |
521 * parameters) two malloc'd zero-terminated arrays -- one of | |
522 * message IDs, and a parallel one of sizes. | |
523 * | |
524 * Arguments: | |
525 * server The pop connection to talk to. | |
526 * message The number of the one message about which to get | |
527 * information, or 0 to get information about all | |
528 * messages. | |
529 * | |
530 * Return value: 0 on success, non-zero with error in pop_error on | |
531 * failure. | |
532 * | |
533 * Side effects: On failure, may make further operations on the | |
534 * connection impossible. | |
535 */ | |
536 int | |
537 pop_list (server, message, IDs, sizes) | |
538 popserver server; | |
539 int message; | |
540 int **IDs; | |
541 int **sizes; | |
542 { | |
543 int how_many, i; | |
544 char *fromserver; | |
545 | |
546 if (server->in_multi) | |
547 { | |
548 strcpy (pop_error, "In multi-line query in pop_list"); | |
549 return (-1); | |
550 } | |
551 | |
552 if (message) | |
553 how_many = 1; | |
554 else | |
555 { | |
556 int count, size; | |
557 if (pop_stat (server, &count, &size)) | |
558 return (-1); | |
559 how_many = count; | |
560 } | |
561 | |
562 *IDs = (int *) malloc ((how_many + 1) * sizeof (int)); | |
563 *sizes = (int *) malloc ((how_many + 1) * sizeof (int)); | |
564 if (! (*IDs && *sizes)) | |
565 { | |
566 strcpy (pop_error, "Out of memory in pop_list"); | |
567 return (-1); | |
568 } | |
569 | |
570 if (message) | |
571 { | |
572 sprintf (pop_error, "LIST %d", message); | |
573 if (sendline (server, pop_error)) | |
574 { | |
575 free ((char *) *IDs); | |
576 free ((char *) *sizes); | |
577 return (-1); | |
578 } | |
21295
f399e51d6d11
(pop_getline): Renamed from getline.
Richard M. Stallman <rms@gnu.org>
parents:
20418
diff
changeset
|
579 if (pop_getline (server, &fromserver) < 0) |
9158 | 580 { |
581 free ((char *) *IDs); | |
582 free ((char *) *sizes); | |
583 return (-1); | |
584 } | |
585 if (strncmp (fromserver, "+OK ", 4)) | |
586 { | |
587 if (! strncmp (fromserver, "-ERR", 4)) | |
588 strncpy (pop_error, fromserver, ERROR_MAX); | |
589 else | |
590 { | |
591 strcpy (pop_error, | |
592 "Unexpected response from server in pop_list"); | |
593 pop_trash (server); | |
594 } | |
595 free ((char *) *IDs); | |
596 free ((char *) *sizes); | |
597 return (-1); | |
598 } | |
599 (*IDs)[0] = atoi (&fromserver[4]); | |
600 fromserver = index (&fromserver[4], ' '); | |
601 if (! fromserver) | |
602 { | |
603 strcpy (pop_error, | |
604 "Badly formatted response from server in pop_list"); | |
605 pop_trash (server); | |
606 free ((char *) *IDs); | |
607 free ((char *) *sizes); | |
608 return (-1); | |
609 } | |
610 (*sizes)[0] = atoi (fromserver); | |
611 (*IDs)[1] = (*sizes)[1] = 0; | |
612 return (0); | |
613 } | |
614 else | |
615 { | |
616 if (pop_multi_first (server, "LIST", &fromserver)) | |
617 { | |
618 free ((char *) *IDs); | |
619 free ((char *) *sizes); | |
620 return (-1); | |
621 } | |
622 for (i = 0; i < how_many; i++) | |
623 { | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
624 if (pop_multi_next (server, &fromserver) <= 0) |
9158 | 625 { |
626 free ((char *) *IDs); | |
627 free ((char *) *sizes); | |
628 return (-1); | |
629 } | |
630 (*IDs)[i] = atoi (fromserver); | |
631 fromserver = index (fromserver, ' '); | |
632 if (! fromserver) | |
633 { | |
634 strcpy (pop_error, | |
635 "Badly formatted response from server in pop_list"); | |
636 free ((char *) *IDs); | |
637 free ((char *) *sizes); | |
638 pop_trash (server); | |
639 return (-1); | |
640 } | |
641 (*sizes)[i] = atoi (fromserver); | |
642 } | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
643 if (pop_multi_next (server, &fromserver) < 0) |
9158 | 644 { |
645 free ((char *) *IDs); | |
646 free ((char *) *sizes); | |
647 return (-1); | |
648 } | |
649 else if (fromserver) | |
650 { | |
651 strcpy (pop_error, | |
652 "Too many response lines from server in pop_list"); | |
653 free ((char *) *IDs); | |
654 free ((char *) *sizes); | |
655 return (-1); | |
656 } | |
657 (*IDs)[i] = (*sizes)[i] = 0; | |
658 return (0); | |
659 } | |
660 } | |
661 | |
662 /* | |
663 * Function: pop_retrieve | |
664 * | |
665 * Purpose: Retrieve a specified message from the maildrop. | |
666 * | |
667 * Arguments: | |
668 * server The server to retrieve from. | |
669 * message The message number to retrieve. | |
670 * markfrom | |
671 * If true, then mark the string "From " at the beginning | |
672 * of lines with '>'. | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
673 * msg_buf Output parameter to which a buffer containing the |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
674 * message is assigned. |
9158 | 675 * |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
676 * Return value: The number of bytes in msg_buf, which may contain |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
677 * embedded nulls, not including its final null, or -1 on error |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
678 * with pop_error set. |
9158 | 679 * |
680 * Side effects: May kill connection on error. | |
681 */ | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
682 int |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
683 pop_retrieve (server, message, markfrom, msg_buf) |
9158 | 684 popserver server; |
685 int message; | |
686 int markfrom; | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
687 char **msg_buf; |
9158 | 688 { |
689 int *IDs, *sizes, bufsize, fromcount = 0, cp = 0; | |
690 char *ptr, *fromserver; | |
691 int ret; | |
692 | |
693 if (server->in_multi) | |
694 { | |
695 strcpy (pop_error, "In multi-line query in pop_retrieve"); | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
696 return (-1); |
9158 | 697 } |
698 | |
699 if (pop_list (server, message, &IDs, &sizes)) | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
700 return (-1); |
9158 | 701 |
702 if (pop_retrieve_first (server, message, &fromserver)) | |
703 { | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
704 return (-1); |
9158 | 705 } |
706 | |
707 /* | |
708 * The "5" below is an arbitrary constant -- I assume that if | |
709 * there are "From" lines in the text to be marked, there | |
710 * probably won't be more than 5 of them. If there are, I | |
711 * allocate more space for them below. | |
712 */ | |
713 bufsize = sizes[0] + (markfrom ? 5 : 0); | |
14238
b55e97028105
(pop_retrieve, getline): Avoid type clashes.
Karl Heuer <kwzh@gnu.org>
parents:
14186
diff
changeset
|
714 ptr = (char *)malloc (bufsize); |
9158 | 715 free ((char *) IDs); |
716 free ((char *) sizes); | |
717 | |
718 if (! ptr) | |
719 { | |
720 strcpy (pop_error, "Out of memory in pop_retrieve"); | |
721 pop_retrieve_flush (server); | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
722 return (-1); |
9158 | 723 } |
724 | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
725 while ((ret = pop_retrieve_next (server, &fromserver)) >= 0) |
9158 | 726 { |
727 if (! fromserver) | |
728 { | |
729 ptr[cp] = '\0'; | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
730 *msg_buf = ptr; |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
731 return (cp); |
9158 | 732 } |
733 if (markfrom && fromserver[0] == 'F' && fromserver[1] == 'r' && | |
734 fromserver[2] == 'o' && fromserver[3] == 'm' && | |
735 fromserver[4] == ' ') | |
736 { | |
737 if (++fromcount == 5) | |
738 { | |
739 bufsize += 5; | |
14238
b55e97028105
(pop_retrieve, getline): Avoid type clashes.
Karl Heuer <kwzh@gnu.org>
parents:
14186
diff
changeset
|
740 ptr = (char *)realloc (ptr, bufsize); |
9158 | 741 if (! ptr) |
742 { | |
743 strcpy (pop_error, "Out of memory in pop_retrieve"); | |
744 pop_retrieve_flush (server); | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
745 return (-1); |
9158 | 746 } |
747 fromcount = 0; | |
748 } | |
749 ptr[cp++] = '>'; | |
750 } | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
751 bcopy (fromserver, &ptr[cp], ret); |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
752 cp += ret; |
9158 | 753 ptr[cp++] = '\n'; |
754 } | |
755 | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
756 free (ptr); |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
757 return (-1); |
9158 | 758 } |
759 | |
760 int | |
761 pop_retrieve_first (server, message, response) | |
762 popserver server; | |
763 int message; | |
764 char **response; | |
765 { | |
766 sprintf (pop_error, "RETR %d", message); | |
767 return (pop_multi_first (server, pop_error, response)); | |
768 } | |
769 | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
770 /* |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
771 Returns a negative number on error, 0 to indicate that the data has |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
772 all been read (i.e., the server has returned a "." termination |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
773 line), or a positive number indicating the number of bytes in the |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
774 returned buffer (which is null-terminated and may contain embedded |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
775 nulls, but the returned bytecount doesn't include the final null). |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
776 */ |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
777 |
9158 | 778 int |
779 pop_retrieve_next (server, line) | |
780 popserver server; | |
781 char **line; | |
782 { | |
783 return (pop_multi_next (server, line)); | |
784 } | |
785 | |
786 int | |
787 pop_retrieve_flush (server) | |
788 popserver server; | |
789 { | |
790 return (pop_multi_flush (server)); | |
791 } | |
792 | |
793 int | |
794 pop_top_first (server, message, lines, response) | |
795 popserver server; | |
796 int message, lines; | |
797 char **response; | |
798 { | |
799 sprintf (pop_error, "TOP %d %d", message, lines); | |
800 return (pop_multi_first (server, pop_error, response)); | |
801 } | |
802 | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
803 /* |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
804 Returns a negative number on error, 0 to indicate that the data has |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
805 all been read (i.e., the server has returned a "." termination |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
806 line), or a positive number indicating the number of bytes in the |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
807 returned buffer (which is null-terminated and may contain embedded |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
808 nulls, but the returned bytecount doesn't include the final null). |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
809 */ |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
810 |
9158 | 811 int |
812 pop_top_next (server, line) | |
813 popserver server; | |
814 char **line; | |
815 { | |
816 return (pop_multi_next (server, line)); | |
817 } | |
818 | |
819 int | |
820 pop_top_flush (server) | |
821 popserver server; | |
822 { | |
823 return (pop_multi_flush (server)); | |
824 } | |
825 | |
826 int | |
827 pop_multi_first (server, command, response) | |
828 popserver server; | |
829 char *command; | |
830 char **response; | |
831 { | |
832 if (server->in_multi) | |
833 { | |
834 strcpy (pop_error, | |
835 "Already in multi-line query in pop_multi_first"); | |
836 return (-1); | |
837 } | |
838 | |
21295
f399e51d6d11
(pop_getline): Renamed from getline.
Richard M. Stallman <rms@gnu.org>
parents:
20418
diff
changeset
|
839 if (sendline (server, command) || (pop_getline (server, response) < 0)) |
9158 | 840 { |
841 return (-1); | |
842 } | |
843 | |
844 if (0 == strncmp (*response, "-ERR", 4)) | |
845 { | |
846 strncpy (pop_error, *response, ERROR_MAX); | |
847 return (-1); | |
848 } | |
849 else if (0 == strncmp (*response, "+OK", 3)) | |
850 { | |
851 for (*response += 3; **response == ' '; (*response)++) /* empty */; | |
852 server->in_multi = 1; | |
853 return (0); | |
854 } | |
855 else | |
856 { | |
857 strcpy (pop_error, | |
858 "Unexpected response from server in pop_multi_first"); | |
859 return (-1); | |
860 } | |
861 } | |
862 | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
863 /* |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
864 Read the next line of data from SERVER and place a pointer to it |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
865 into LINE. Return -1 on error, 0 if there are no more lines to read |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
866 (i.e., the server has returned a line containing only "."), or a |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
867 positive number indicating the number of bytes in the LINE buffer |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
868 (not including the final null). The data in that buffer may contain |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
869 embedded nulls, but does not contain the final CRLF. When returning |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
870 0, LINE is set to null. */ |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
871 |
9158 | 872 int |
873 pop_multi_next (server, line) | |
874 popserver server; | |
875 char **line; | |
876 { | |
877 char *fromserver; | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
878 int ret; |
9158 | 879 |
880 if (! server->in_multi) | |
881 { | |
882 strcpy (pop_error, "Not in multi-line query in pop_multi_next"); | |
883 return (-1); | |
884 } | |
885 | |
21295
f399e51d6d11
(pop_getline): Renamed from getline.
Richard M. Stallman <rms@gnu.org>
parents:
20418
diff
changeset
|
886 if ((ret = pop_getline (server, &fromserver)) < 0) |
9158 | 887 { |
888 return (-1); | |
889 } | |
890 | |
891 if (fromserver[0] == '.') | |
892 { | |
893 if (! fromserver[1]) | |
894 { | |
895 *line = 0; | |
896 server->in_multi = 0; | |
897 return (0); | |
898 } | |
899 else | |
900 { | |
901 *line = fromserver + 1; | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
902 return (ret - 1); |
9158 | 903 } |
904 } | |
905 else | |
906 { | |
907 *line = fromserver; | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
908 return (ret); |
9158 | 909 } |
910 } | |
911 | |
912 int | |
913 pop_multi_flush (server) | |
914 popserver server; | |
915 { | |
916 char *line; | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
917 int ret; |
9158 | 918 |
919 if (! server->in_multi) | |
920 { | |
921 return (0); | |
922 } | |
923 | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
924 while ((ret = pop_multi_next (server, &line))) |
9158 | 925 { |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
926 if (ret < 0) |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
927 return (-1); |
9158 | 928 } |
929 | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
930 return (0); |
9158 | 931 } |
932 | |
933 /* Function: pop_delete | |
934 * | |
935 * Purpose: Delete a specified message. | |
936 * | |
937 * Arguments: | |
938 * server Server from which to delete the message. | |
939 * message Message to delete. | |
940 * | |
941 * Return value: 0 on success, non-zero with error in pop_error | |
942 * otherwise. | |
943 */ | |
944 int | |
945 pop_delete (server, message) | |
946 popserver server; | |
947 int message; | |
948 { | |
949 if (server->in_multi) | |
950 { | |
951 strcpy (pop_error, "In multi-line query in pop_delete"); | |
952 return (-1); | |
953 } | |
954 | |
955 sprintf (pop_error, "DELE %d", message); | |
956 | |
957 if (sendline (server, pop_error) || getok (server)) | |
958 return (-1); | |
959 | |
960 return (0); | |
961 } | |
962 | |
963 /* | |
964 * Function: pop_noop | |
965 * | |
966 * Purpose: Send a noop command to the server. | |
967 * | |
968 * Argument: | |
969 * server The server to send to. | |
970 * | |
971 * Return value: 0 on success, non-zero with error in pop_error | |
972 * otherwise. | |
973 * | |
974 * Side effects: Closes connection on error. | |
975 */ | |
976 int | |
977 pop_noop (server) | |
978 popserver server; | |
979 { | |
980 if (server->in_multi) | |
981 { | |
982 strcpy (pop_error, "In multi-line query in pop_noop"); | |
983 return (-1); | |
984 } | |
985 | |
986 if (sendline (server, "NOOP") || getok (server)) | |
987 return (-1); | |
988 | |
989 return (0); | |
990 } | |
991 | |
992 /* | |
993 * Function: pop_last | |
994 * | |
995 * Purpose: Find out the highest seen message from the server. | |
996 * | |
997 * Arguments: | |
998 * server The server. | |
999 * | |
1000 * Return value: If successful, the highest seen message, which is | |
1001 * greater than or equal to 0. Otherwise, a negative number with | |
1002 * the error explained in pop_error. | |
1003 * | |
1004 * Side effects: Closes the connection on error. | |
1005 */ | |
1006 int | |
1007 pop_last (server) | |
1008 popserver server; | |
1009 { | |
1010 char *fromserver; | |
1011 | |
1012 if (server->in_multi) | |
1013 { | |
1014 strcpy (pop_error, "In multi-line query in pop_last"); | |
1015 return (-1); | |
1016 } | |
1017 | |
1018 if (sendline (server, "LAST")) | |
1019 return (-1); | |
1020 | |
21295
f399e51d6d11
(pop_getline): Renamed from getline.
Richard M. Stallman <rms@gnu.org>
parents:
20418
diff
changeset
|
1021 if (pop_getline (server, &fromserver) < 0) |
9158 | 1022 return (-1); |
1023 | |
1024 if (! strncmp (fromserver, "-ERR", 4)) | |
1025 { | |
1026 strncpy (pop_error, fromserver, ERROR_MAX); | |
1027 return (-1); | |
1028 } | |
1029 else if (strncmp (fromserver, "+OK ", 4)) | |
1030 { | |
1031 strcpy (pop_error, "Unexpected response from server in pop_last"); | |
1032 pop_trash (server); | |
1033 return (-1); | |
1034 } | |
1035 else | |
1036 { | |
1037 return (atoi (&fromserver[4])); | |
1038 } | |
1039 } | |
1040 | |
1041 /* | |
1042 * Function: pop_reset | |
1043 * | |
1044 * Purpose: Reset the server to its initial connect state | |
1045 * | |
1046 * Arguments: | |
1047 * server The server. | |
1048 * | |
1049 * Return value: 0 for success, non-0 with error in pop_error | |
1050 * otherwise. | |
1051 * | |
1052 * Side effects: Closes the connection on error. | |
1053 */ | |
1054 int | |
1055 pop_reset (server) | |
1056 popserver server; | |
1057 { | |
1058 if (pop_retrieve_flush (server)) | |
1059 { | |
1060 return (-1); | |
1061 } | |
1062 | |
1063 if (sendline (server, "RSET") || getok (server)) | |
1064 return (-1); | |
1065 | |
1066 return (0); | |
1067 } | |
1068 | |
1069 /* | |
1070 * Function: pop_quit | |
1071 * | |
1072 * Purpose: Quit the connection to the server, | |
1073 * | |
1074 * Arguments: | |
1075 * server The server to quit. | |
1076 * | |
1077 * Return value: 0 for success, non-zero otherwise with error in | |
1078 * pop_error. | |
1079 * | |
14036 | 1080 * Side Effects: The popserver passed in is unusable after this |
9158 | 1081 * function is called, even if an error occurs. |
1082 */ | |
1083 int | |
1084 pop_quit (server) | |
1085 popserver server; | |
1086 { | |
1087 int ret = 0; | |
1088 | |
1089 if (server->file >= 0) | |
1090 { | |
1091 if (pop_retrieve_flush (server)) | |
1092 { | |
1093 ret = -1; | |
1094 } | |
1095 | |
1096 if (sendline (server, "QUIT") || getok (server)) | |
1097 { | |
1098 ret = -1; | |
1099 } | |
1100 | |
1101 close (server->file); | |
1102 } | |
1103 | |
1104 if (server->buffer) | |
1105 free (server->buffer); | |
21397 | 1106 #ifdef GSSAPI |
1107 if (server->extra) | |
1108 { | |
1109 OM_uint32 minor; | |
1110 | |
1111 if (Gssapi (server->extra)->gss_context != GSS_C_NO_CONTEXT) | |
1112 gss_delete_sec_context (&minor, &(Gssapi (server->extra)->gss_context), | |
1113 GSS_C_NO_BUFFER); | |
1114 free ((char *) server->extra); | |
1115 } | |
1116 #endif /* GSSAPI */ | |
9158 | 1117 free ((char *) server); |
1118 | |
1119 return (ret); | |
1120 } | |
1121 | |
15102
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
1122 #ifdef WINDOWSNT |
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
1123 static int have_winsock = 0; |
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
1124 #endif |
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
1125 |
9158 | 1126 /* |
1127 * Function: socket_connection | |
1128 * | |
1129 * Purpose: Opens the network connection with the mail host, without | |
1130 * doing any sort of I/O with it or anything. | |
1131 * | |
1132 * Arguments: | |
1133 * host The host to which to connect. | |
1134 * flags Option flags. | |
1135 * | |
1136 * Return value: A file descriptor indicating the connection, or -1 | |
1137 * indicating failure, in which case an error has been copied | |
1138 * into pop_error. | |
1139 */ | |
1140 static int | |
1141 socket_connection (host, flags) | |
1142 char *host; | |
1143 int flags; | |
1144 { | |
1145 struct hostent *hostent; | |
1146 struct servent *servent; | |
1147 struct sockaddr_in addr; | |
1148 char found_port = 0; | |
1149 char *service; | |
1150 int sock; | |
1151 #ifdef KERBEROS | |
19018
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1152 #ifdef KERBEROS5 |
9158 | 1153 krb5_error_code rem; |
19018
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1154 krb5_context kcontext = 0; |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1155 krb5_auth_context auth_context = 0; |
9158 | 1156 krb5_ccache ccdef; |
1157 krb5_principal client, server; | |
1158 krb5_error *err_ret; | |
1159 register char *cp; | |
1160 #else | |
1161 KTEXT ticket; | |
1162 MSG_DAT msg_data; | |
1163 CREDENTIALS cred; | |
1164 Key_schedule schedule; | |
1165 int rem; | |
16603
a12b8815bcf0
gethostbyname() may return a pointer to static data, which is
Charles Hannum <mycroft@gnu.org>
parents:
15934
diff
changeset
|
1166 char *realhost; |
19018
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1167 #endif /* KERBEROS5 */ |
9158 | 1168 #endif /* KERBEROS */ |
1169 | |
1170 int try_count = 0; | |
1171 | |
15102
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
1172 #ifdef WINDOWSNT |
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
1173 { |
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
1174 WSADATA winsockData; |
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
1175 if (WSAStartup (0x101, &winsockData) == 0) |
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
1176 have_winsock = 1; |
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
1177 } |
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
1178 #endif |
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
1179 |
9158 | 1180 do |
1181 { | |
1182 hostent = gethostbyname (host); | |
1183 try_count++; | |
1184 if ((! hostent) && ((h_errno != TRY_AGAIN) || (try_count == 5))) | |
1185 { | |
1186 strcpy (pop_error, "Could not determine POP server's address"); | |
1187 return (-1); | |
1188 } | |
1189 } while (! hostent); | |
1190 | |
1191 bzero ((char *) &addr, sizeof (addr)); | |
1192 addr.sin_family = AF_INET; | |
1193 | |
1194 #ifdef KERBEROS | |
1195 service = (flags & POP_NO_KERBEROS) ? POP_SERVICE : KPOP_SERVICE; | |
1196 #else | |
1197 service = POP_SERVICE; | |
1198 #endif | |
1199 | |
1200 #ifdef HESIOD | |
1201 if (! (flags & POP_NO_HESIOD)) | |
1202 { | |
1203 servent = hes_getservbyname (service, "tcp"); | |
1204 if (servent) | |
1205 { | |
1206 addr.sin_port = servent->s_port; | |
1207 found_port = 1; | |
1208 } | |
1209 } | |
1210 #endif | |
1211 if (! found_port) | |
1212 { | |
1213 servent = getservbyname (service, "tcp"); | |
1214 if (servent) | |
1215 { | |
1216 addr.sin_port = servent->s_port; | |
1217 } | |
1218 else | |
1219 { | |
1220 #ifdef KERBEROS | |
1221 addr.sin_port = htons ((flags & POP_NO_KERBEROS) ? | |
1222 POP_PORT : KPOP_PORT); | |
1223 #else | |
1224 addr.sin_port = htons (POP_PORT); | |
1225 #endif | |
1226 } | |
1227 } | |
1228 | |
19018
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1229 #define POP_SOCKET_ERROR "Could not create socket for POP connection: " |
9158 | 1230 |
1231 sock = socket (PF_INET, SOCK_STREAM, 0); | |
1232 if (sock < 0) | |
1233 { | |
19018
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1234 strcpy (pop_error, POP_SOCKET_ERROR); |
9158 | 1235 strncat (pop_error, strerror (errno), |
19018
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1236 ERROR_MAX - sizeof (POP_SOCKET_ERROR)); |
9158 | 1237 return (-1); |
1238 | |
1239 } | |
1240 | |
1241 while (*hostent->h_addr_list) | |
1242 { | |
1243 bcopy (*hostent->h_addr_list, (char *) &addr.sin_addr, | |
1244 hostent->h_length); | |
1245 if (! connect (sock, (struct sockaddr *) &addr, sizeof (addr))) | |
1246 break; | |
1247 hostent->h_addr_list++; | |
1248 } | |
1249 | |
1250 #define CONNECT_ERROR "Could not connect to POP server: " | |
1251 | |
1252 if (! *hostent->h_addr_list) | |
1253 { | |
15108
442458addd50
(SEND, RECV): Renamed from send, recv.
Richard M. Stallman <rms@gnu.org>
parents:
15102
diff
changeset
|
1254 CLOSESOCKET (sock); |
9158 | 1255 strcpy (pop_error, CONNECT_ERROR); |
1256 strncat (pop_error, strerror (errno), | |
1257 ERROR_MAX - sizeof (CONNECT_ERROR)); | |
1258 return (-1); | |
1259 | |
1260 } | |
1261 | |
1262 #ifdef KERBEROS | |
1263 #define KRB_ERROR "Kerberos error connecting to POP server: " | |
1264 if (! (flags & POP_NO_KERBEROS)) | |
1265 { | |
19018
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1266 #ifdef KERBEROS5 |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1267 if ((rem = krb5_init_context (&kcontext))) |
9158 | 1268 { |
1269 krb5error: | |
19018
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1270 if (auth_context) |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1271 krb5_auth_con_free (kcontext, auth_context); |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1272 if (kcontext) |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1273 krb5_free_context (kcontext); |
9158 | 1274 strcpy (pop_error, KRB_ERROR); |
1275 strncat (pop_error, error_message (rem), | |
1276 ERROR_MAX - sizeof(KRB_ERROR)); | |
15108
442458addd50
(SEND, RECV): Renamed from send, recv.
Richard M. Stallman <rms@gnu.org>
parents:
15102
diff
changeset
|
1277 CLOSESOCKET (sock); |
9158 | 1278 return (-1); |
1279 } | |
1280 | |
19018
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1281 if ((rem = krb5_auth_con_init (kcontext, &auth_context))) |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1282 goto krb5error; |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1283 |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1284 if (rem = krb5_cc_default (kcontext, &ccdef)) |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1285 goto krb5error; |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1286 |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1287 if (rem = krb5_cc_get_principal (kcontext, ccdef, &client)) |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1288 goto krb5error; |
9158 | 1289 |
1290 for (cp = hostent->h_name; *cp; cp++) | |
1291 { | |
1292 if (isupper (*cp)) | |
1293 { | |
1294 *cp = tolower (*cp); | |
1295 } | |
1296 } | |
1297 | |
19018
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1298 if (rem = krb5_sname_to_principal (kcontext, hostent->h_name, |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1299 POP_SERVICE, FALSE, &server)) |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1300 goto krb5error; |
9158 | 1301 |
19018
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1302 rem = krb5_sendauth (kcontext, &auth_context, |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1303 (krb5_pointer) &sock, "KPOPV1.0", client, server, |
9158 | 1304 AP_OPTS_MUTUAL_REQUIRED, |
1305 0, /* no checksum */ | |
1306 0, /* no creds, use ccache instead */ | |
1307 ccdef, | |
19018
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1308 &err_ret, |
9158 | 1309 0, /* don't need subsession key */ |
1310 0); /* don't need reply */ | |
19018
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1311 krb5_free_principal (kcontext, server); |
9158 | 1312 if (rem) |
1313 { | |
1314 if (err_ret && err_ret->text.length) | |
1315 { | |
1316 strcpy (pop_error, KRB_ERROR); | |
1317 strncat (pop_error, error_message (rem), | |
1318 ERROR_MAX - sizeof (KRB_ERROR)); | |
1319 strncat (pop_error, " [server says '", | |
1320 ERROR_MAX - strlen (pop_error) - 1); | |
1321 strncat (pop_error, err_ret->text.data, | |
1322 min (ERROR_MAX - strlen (pop_error) - 1, | |
1323 err_ret->text.length)); | |
1324 strncat (pop_error, "']", | |
1325 ERROR_MAX - strlen (pop_error) - 1); | |
1326 } | |
1327 else | |
1328 { | |
1329 strcpy (pop_error, KRB_ERROR); | |
1330 strncat (pop_error, error_message (rem), | |
1331 ERROR_MAX - sizeof (KRB_ERROR)); | |
1332 } | |
1333 if (err_ret) | |
19018
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1334 krb5_free_error (kcontext, err_ret); |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1335 krb5_auth_con_free (kcontext, auth_context); |
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1336 krb5_free_context (kcontext); |
9158 | 1337 |
15108
442458addd50
(SEND, RECV): Renamed from send, recv.
Richard M. Stallman <rms@gnu.org>
parents:
15102
diff
changeset
|
1338 CLOSESOCKET (sock); |
9158 | 1339 return (-1); |
1340 } | |
19018
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1341 #else /* ! KERBEROS5 */ |
9158 | 1342 ticket = (KTEXT) malloc (sizeof (KTEXT_ST)); |
16603
a12b8815bcf0
gethostbyname() may return a pointer to static data, which is
Charles Hannum <mycroft@gnu.org>
parents:
15934
diff
changeset
|
1343 realhost = strdup (hostent->h_name); |
a12b8815bcf0
gethostbyname() may return a pointer to static data, which is
Charles Hannum <mycroft@gnu.org>
parents:
15934
diff
changeset
|
1344 rem = krb_sendauth (0L, sock, ticket, "pop", realhost, |
a12b8815bcf0
gethostbyname() may return a pointer to static data, which is
Charles Hannum <mycroft@gnu.org>
parents:
15934
diff
changeset
|
1345 (char *) krb_realmofhost (realhost), |
9158 | 1346 (unsigned long) 0, &msg_data, &cred, schedule, |
1347 (struct sockaddr_in *) 0, | |
1348 (struct sockaddr_in *) 0, | |
1349 "KPOPV0.1"); | |
1350 free ((char *) ticket); | |
16697
83946dc6f4e7
(socket_connection): Free realhost after using it.
Richard M. Stallman <rms@gnu.org>
parents:
16603
diff
changeset
|
1351 free (realhost); |
9158 | 1352 if (rem != KSUCCESS) |
1353 { | |
1354 strcpy (pop_error, KRB_ERROR); | |
1355 strncat (pop_error, krb_err_txt[rem], | |
1356 ERROR_MAX - sizeof (KRB_ERROR)); | |
15108
442458addd50
(SEND, RECV): Renamed from send, recv.
Richard M. Stallman <rms@gnu.org>
parents:
15102
diff
changeset
|
1357 CLOSESOCKET (sock); |
9158 | 1358 return (-1); |
1359 } | |
19018
f1f7c254aa77
Support auto-configuration of both Kerberos V4 and
Richard M. Stallman <rms@gnu.org>
parents:
17683
diff
changeset
|
1360 #endif /* KERBEROS5 */ |
9158 | 1361 } |
1362 #endif /* KERBEROS */ | |
1363 | |
1364 return (sock); | |
1365 } /* socket_connection */ | |
1366 | |
1367 /* | |
21295
f399e51d6d11
(pop_getline): Renamed from getline.
Richard M. Stallman <rms@gnu.org>
parents:
20418
diff
changeset
|
1368 * Function: pop_getline |
9158 | 1369 * |
1370 * Purpose: Get a line of text from the connection and return a | |
1371 * pointer to it. The carriage return and linefeed at the end of | |
1372 * the line are stripped, but periods at the beginnings of lines | |
1373 * are NOT dealt with in any special way. | |
1374 * | |
1375 * Arguments: | |
1376 * server The server from which to get the line of text. | |
1377 * | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
1378 * Returns: The number of characters in the line, which is returned in |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
1379 * LINE, not including the final null. A return value of 0 |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
1380 * indicates a blank line. A negative return value indicates an |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
1381 * error (in which case the contents of LINE are undefined. In |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
1382 * case of error, an error message is copied into pop_error. |
9158 | 1383 * |
21295
f399e51d6d11
(pop_getline): Renamed from getline.
Richard M. Stallman <rms@gnu.org>
parents:
20418
diff
changeset
|
1384 * Notes: The line returned is overwritten with each call to pop_getline. |
9158 | 1385 * |
1386 * Side effects: Closes the connection on error. | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
1387 * |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
1388 * THE RETURNED LINE MAY CONTAIN EMBEDDED NULLS! |
9158 | 1389 */ |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
1390 static int |
21295
f399e51d6d11
(pop_getline): Renamed from getline.
Richard M. Stallman <rms@gnu.org>
parents:
20418
diff
changeset
|
1391 pop_getline (server, line) |
9158 | 1392 popserver server; |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
1393 char **line; |
9158 | 1394 { |
1395 #define GETLINE_ERROR "Error reading from server: " | |
1396 | |
1397 int ret; | |
9674
e5a897cf215d
(getline): When a search of already-read input for CRLF
Richard M. Stallman <rms@gnu.org>
parents:
9613
diff
changeset
|
1398 int search_offset = 0; |
e5a897cf215d
(getline): When a search of already-read input for CRLF
Richard M. Stallman <rms@gnu.org>
parents:
9613
diff
changeset
|
1399 |
9158 | 1400 if (server->data) |
1401 { | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
1402 char *cp = find_crlf (server->buffer + server->buffer_index, |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
1403 server->data); |
9158 | 1404 if (cp) |
1405 { | |
1406 int found; | |
1407 int data_used; | |
1408 | |
1409 found = server->buffer_index; | |
1410 data_used = (cp + 2) - server->buffer - found; | |
1411 | |
1412 *cp = '\0'; /* terminate the string to be returned */ | |
1413 server->data -= data_used; | |
1414 server->buffer_index += data_used; | |
1415 | |
1416 if (pop_debug) | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
1417 /* Embedded nulls will truncate this output prematurely, |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
1418 but that's OK because it's just for debugging anyway. */ |
9158 | 1419 fprintf (stderr, "<<< %s\n", server->buffer + found); |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
1420 *line = server->buffer + found; |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
1421 return (data_used - 2); |
9158 | 1422 } |
1423 else | |
1424 { | |
1425 bcopy (server->buffer + server->buffer_index, | |
1426 server->buffer, server->data); | |
9674
e5a897cf215d
(getline): When a search of already-read input for CRLF
Richard M. Stallman <rms@gnu.org>
parents:
9613
diff
changeset
|
1427 /* Record the fact that we've searched the data already in |
e5a897cf215d
(getline): When a search of already-read input for CRLF
Richard M. Stallman <rms@gnu.org>
parents:
9613
diff
changeset
|
1428 the buffer for a CRLF, so that when we search below, we |
e5a897cf215d
(getline): When a search of already-read input for CRLF
Richard M. Stallman <rms@gnu.org>
parents:
9613
diff
changeset
|
1429 don't have to search the same data twice. There's a "- |
e5a897cf215d
(getline): When a search of already-read input for CRLF
Richard M. Stallman <rms@gnu.org>
parents:
9613
diff
changeset
|
1430 1" here to account for the fact that the last character |
e5a897cf215d
(getline): When a search of already-read input for CRLF
Richard M. Stallman <rms@gnu.org>
parents:
9613
diff
changeset
|
1431 of the data we have may be the CR of a CRLF pair, of |
e5a897cf215d
(getline): When a search of already-read input for CRLF
Richard M. Stallman <rms@gnu.org>
parents:
9613
diff
changeset
|
1432 which we haven't read the second half yet, so we may have |
e5a897cf215d
(getline): When a search of already-read input for CRLF
Richard M. Stallman <rms@gnu.org>
parents:
9613
diff
changeset
|
1433 to search it again when we read more data. */ |
e5a897cf215d
(getline): When a search of already-read input for CRLF
Richard M. Stallman <rms@gnu.org>
parents:
9613
diff
changeset
|
1434 search_offset = server->data - 1; |
9158 | 1435 server->buffer_index = 0; |
1436 } | |
1437 } | |
1438 else | |
1439 { | |
1440 server->buffer_index = 0; | |
1441 } | |
1442 | |
1443 while (1) | |
1444 { | |
21397 | 1445 #ifdef GSSAPI |
1446 /* | |
1447 * We might be playing with a protected connection. If we are, then | |
1448 * we need to first read a chunk of ciphertext from the server, | |
1449 * unwrap it, and stuff it into the buffer. | |
1450 */ | |
1451 if (server->extra && | |
1452 ((Gssapi (server->extra)->gss_flags) & GSSAPI_NEEDWRAP)) | |
9158 | 1453 { |
21397 | 1454 char rcvbuf[GSSAPI_RCVBUF]; |
1455 OM_uint32 major, minor, length; | |
1456 gss_buffer_desc in_tok, out_tok; | |
1457 struct _pop_gssapi *gss_data = Gssapi (server->extra); | |
1458 | |
1459 ret = fullread (server->file, (char *) &length, sizeof (length)); | |
1460 | |
1461 if (ret == sizeof (length)) | |
9158 | 1462 { |
21397 | 1463 in_tok.length = ntohl (length); |
1464 | |
1465 if (in_tok.length <= GSSAPI_RCVBUF) | |
1466 { | |
1467 ret = fullread (server->file, rcvbuf, in_tok.length); | |
1468 | |
1469 if (ret == in_tok.length) | |
1470 { | |
1471 in_tok.value = (void *) rcvbuf; | |
1472 | |
1473 major = gss_unwrap (&minor, gss_data->gss_context, | |
1474 &in_tok, &out_tok, 0, 0); | |
1475 | |
1476 if (major != GSS_S_COMPLETE) | |
1477 { | |
1478 pop_trash (server); | |
1479 gen_gss_error ("unwrapping", major, minor); | |
1480 return (-1); | |
1481 } | |
1482 | |
1483 while (server->data + out_tok.length >= | |
1484 server->buffer_size - 1) | |
1485 server->buffer_size += GETLINE_INCR; | |
1486 | |
1487 server->buffer = (char *)realloc (server->buffer, | |
1488 server->buffer_size); | |
1489 | |
1490 if (! server->buffer) | |
1491 { | |
1492 gss_release_buffer (&minor, &out_tok); | |
1493 pop_trash (server); | |
1494 strcpy (pop_error, "Out of memory in pop_getline"); | |
1495 return (-1); | |
1496 } | |
1497 | |
1498 bcopy (out_tok.value, server->buffer + server->data, | |
1499 out_tok.length); | |
1500 | |
1501 ret = out_tok.length; | |
1502 | |
1503 gss_release_buffer (&minor, &out_tok); | |
1504 } | |
1505 else | |
1506 ret = 0; /* force detection of unexpected EOF */ | |
1507 } | |
1508 else | |
1509 { | |
1510 pop_trash (server); | |
1511 strcpy (pop_error, "Token from server too long in pop_getline"); | |
1512 return (-1); | |
1513 } | |
9158 | 1514 } |
21397 | 1515 else |
1516 ret = 0; /* force detection of unexpected EOF */ | |
9158 | 1517 } |
21397 | 1518 else |
1519 { | |
1520 #endif /* GSSAPI */ | |
1521 /* There's a "- 1" here to leave room for the null that we put | |
1522 at the end of the read data below. We put the null there so | |
1523 that find_crlf knows where to stop when we call it. */ | |
1524 if (server->data == server->buffer_size - 1) | |
1525 { | |
1526 server->buffer_size += GETLINE_INCR; | |
1527 server->buffer = (char *)realloc (server->buffer, | |
1528 server->buffer_size); | |
1529 if (! server->buffer) | |
1530 { | |
1531 strcpy (pop_error, "Out of memory in pop_getline"); | |
1532 pop_trash (server); | |
1533 return (-1); | |
1534 } | |
1535 } | |
1536 ret = RECV (server->file, server->buffer + server->data, | |
1537 server->buffer_size - server->data - 1, 0); | |
1538 #ifdef GSSAPI | |
1539 } | |
1540 #endif /* GSSAPI */ | |
9158 | 1541 if (ret < 0) |
1542 { | |
1543 strcpy (pop_error, GETLINE_ERROR); | |
1544 strncat (pop_error, strerror (errno), | |
1545 ERROR_MAX - sizeof (GETLINE_ERROR)); | |
1546 pop_trash (server); | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
1547 return (-1); |
9158 | 1548 } |
1549 else if (ret == 0) | |
1550 { | |
21295
f399e51d6d11
(pop_getline): Renamed from getline.
Richard M. Stallman <rms@gnu.org>
parents:
20418
diff
changeset
|
1551 strcpy (pop_error, "Unexpected EOF from server in pop_getline"); |
9158 | 1552 pop_trash (server); |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
1553 return (-1); |
9158 | 1554 } |
1555 else | |
1556 { | |
9591
0774e217e8aa
Don't declare malloc, realloc, free.
Richard M. Stallman <rms@gnu.org>
parents:
9158
diff
changeset
|
1557 char *cp; |
9158 | 1558 server->data += ret; |
9591
0774e217e8aa
Don't declare malloc, realloc, free.
Richard M. Stallman <rms@gnu.org>
parents:
9158
diff
changeset
|
1559 server->buffer[server->data] = '\0'; |
9158 | 1560 |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
1561 cp = find_crlf (server->buffer + search_offset, |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
1562 server->data - search_offset); |
9158 | 1563 if (cp) |
1564 { | |
1565 int data_used = (cp + 2) - server->buffer; | |
1566 *cp = '\0'; | |
1567 server->data -= data_used; | |
1568 server->buffer_index = data_used; | |
1569 | |
1570 if (pop_debug) | |
1571 fprintf (stderr, "<<< %s\n", server->buffer); | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
1572 *line = server->buffer; |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
1573 return (data_used - 2); |
9158 | 1574 } |
17683
975d093d45fb
(getline): Don't miss CRLF pairs when the CR and LF are
Richard M. Stallman <rms@gnu.org>
parents:
16697
diff
changeset
|
1575 /* As above, the "- 1" here is to account for the fact that |
975d093d45fb
(getline): Don't miss CRLF pairs when the CR and LF are
Richard M. Stallman <rms@gnu.org>
parents:
16697
diff
changeset
|
1576 we may have read a CR without its accompanying LF. */ |
975d093d45fb
(getline): Don't miss CRLF pairs when the CR and LF are
Richard M. Stallman <rms@gnu.org>
parents:
16697
diff
changeset
|
1577 search_offset += ret - 1; |
9158 | 1578 } |
1579 } | |
1580 | |
1581 /* NOTREACHED */ | |
1582 } | |
1583 | |
21397 | 1584 #ifdef GSSAPI |
1585 /* | |
1586 * Function: fullread | |
1587 * | |
1588 * Purpose: Just like read, but keeps trying until the specified number | |
1589 * number of bytes has been read into the buffer. This function is | |
1590 * only needed if you are using the GSSAPI protection mechanisms. | |
1591 * | |
1592 * Return value: Same as read. Pop_error is not set. | |
1593 */ | |
1594 static int | |
1595 fullread (fd, buf, nbytes) | |
1596 int fd; | |
1597 char *buf; | |
1598 int nbytes; | |
1599 { | |
1600 char *cp; | |
1601 int ret; | |
1602 | |
1603 cp = buf; | |
1604 | |
1605 while (nbytes > 0 && (ret = RECV (fd, cp, nbytes, 0)) > 0) | |
1606 { | |
1607 cp += ret; | |
1608 nbytes -= ret; | |
1609 } | |
1610 | |
1611 return (ret); | |
1612 } | |
1613 #endif /* GSSAPI */ | |
1614 | |
9158 | 1615 /* |
1616 * Function: sendline | |
1617 * | |
1618 * Purpose: Sends a line of text to the POP server. The line of text | |
1619 * passed into this function should NOT have the carriage return | |
1620 * and linefeed on the end of it. Periods at beginnings of lines | |
1621 * will NOT be treated specially by this function. | |
1622 * | |
1623 * Arguments: | |
1624 * server The server to which to send the text. | |
1625 * line The line of text to send. | |
1626 * | |
1627 * Return value: Upon successful completion, a value of 0 will be | |
1628 * returned. Otherwise, a non-zero value will be returned, and | |
1629 * an error will be copied into pop_error. | |
1630 * | |
1631 * Side effects: Closes the connection on error. | |
1632 */ | |
1633 static int | |
1634 sendline (server, line) | |
1635 popserver server; | |
1636 char *line; | |
1637 { | |
1638 #define SENDLINE_ERROR "Error writing to POP server: " | |
1639 int ret; | |
1640 | |
21397 | 1641 #ifdef GSSAPI |
1642 /* | |
1643 * We might be playing with a protected connection. If we are, then we | |
1644 * need to build our full plaintext, parse it into chunks small enough | |
1645 * for the server to swallow, wrap each one, and send it over the net as | |
1646 * specified by the RFC. | |
1647 */ | |
1648 if (server->extra && ((Gssapi (server->extra)->gss_flags) & GSSAPI_NEEDWRAP)) | |
1649 { | |
1650 char *sendbuf, *ptr; | |
1651 OM_uint32 major, minor, length; | |
1652 gss_buffer_desc in_tok, out_tok; | |
1653 int len = 0, tot_len; | |
1654 struct _pop_gssapi *gss_data = Gssapi (server->extra); | |
1655 | |
1656 sendbuf = malloc (strlen (line) + 3); | |
1657 | |
1658 if (! sendbuf) | |
1659 { | |
1660 pop_trash (server); | |
1661 strcpy (pop_error, "Out of memory in sendline"); | |
1662 return (-1); | |
1663 } | |
1664 | |
1665 tot_len = sprintf (sendbuf, "%s\r\n", line); | |
1666 | |
1667 for (ptr = sendbuf; tot_len > 0; tot_len -= len, ptr += len) | |
1668 { | |
1669 len = ((tot_len > gss_data->max_size) ? | |
1670 gss_data->max_size : tot_len); | |
1671 | |
1672 in_tok.value = (void *) ptr; | |
1673 in_tok.length = len; | |
1674 | |
1675 major = gss_wrap (&minor, gss_data->gss_context, | |
1676 (gss_data->gss_flags & GSSAPI_PRIVACY) ? 1 : 0, | |
1677 GSS_C_QOP_DEFAULT, &in_tok, 0, &out_tok); | |
1678 | |
1679 if (major != GSS_S_COMPLETE) | |
1680 { | |
1681 free (sendbuf); | |
1682 pop_trash (server); | |
1683 gen_gss_error ("wrapping", major, minor); | |
1684 return (-1); | |
1685 } | |
1686 | |
1687 /* | |
1688 * "Once the protection mechanism is in effect, the stream of | |
1689 * command and response octets is processed into buffers of | |
1690 * ciphertext. Each buffer is transferred over the connection | |
1691 * as a stream of octets prepended with a four octet field in | |
1692 * network byte order that represents the length of the | |
1693 * following data." - RFC 1734, section 2 | |
1694 */ | |
1695 length = htonl (out_tok.length); | |
1696 ret = fullwrite (server->file, (char *) &length, sizeof (length)); | |
1697 if (ret == sizeof (length)) | |
1698 { | |
1699 ret = fullwrite (server->file, (char *) out_tok.value, | |
1700 out_tok.length); | |
1701 } | |
1702 | |
1703 gss_release_buffer (&minor, &out_tok); | |
1704 | |
1705 if (ret < 0) | |
1706 break; | |
1707 } | |
1708 | |
1709 free (sendbuf); | |
9158 | 1710 } |
21397 | 1711 else |
1712 { | |
1713 #endif /* GSSAPI */ | |
1714 ret = fullwrite (server->file, line, strlen (line)); | |
1715 if (ret >= 0) | |
1716 { /* 0 indicates that a blank line was written */ | |
1717 ret = fullwrite (server->file, "\r\n", 2); | |
1718 } | |
1719 #ifdef GSSAPI | |
1720 } | |
1721 #endif /* GSSAPI */ | |
9158 | 1722 |
1723 if (ret < 0) | |
1724 { | |
1725 pop_trash (server); | |
1726 strcpy (pop_error, SENDLINE_ERROR); | |
1727 strncat (pop_error, strerror (errno), | |
1728 ERROR_MAX - sizeof (SENDLINE_ERROR)); | |
1729 return (ret); | |
1730 } | |
1731 | |
1732 if (pop_debug) | |
1733 fprintf (stderr, ">>> %s\n", line); | |
1734 | |
1735 return (0); | |
1736 } | |
1737 | |
1738 /* | |
1739 * Procedure: fullwrite | |
1740 * | |
1741 * Purpose: Just like write, but keeps trying until the entire string | |
1742 * has been written. | |
1743 * | |
1744 * Return value: Same as write. Pop_error is not set. | |
1745 */ | |
1746 static int | |
1747 fullwrite (fd, buf, nbytes) | |
1748 int fd; | |
1749 char *buf; | |
1750 int nbytes; | |
1751 { | |
1752 char *cp; | |
20204
44f91b648e03
(fullwrite): Get rid of an extra call to write. Problem
Karl Heuer <kwzh@gnu.org>
parents:
19978
diff
changeset
|
1753 int ret = 0; |
9158 | 1754 |
1755 cp = buf; | |
20204
44f91b648e03
(fullwrite): Get rid of an extra call to write. Problem
Karl Heuer <kwzh@gnu.org>
parents:
19978
diff
changeset
|
1756 while (nbytes && ((ret = SEND (fd, cp, nbytes, 0)) > 0)) |
9158 | 1757 { |
1758 cp += ret; | |
1759 nbytes -= ret; | |
1760 } | |
1761 | |
1762 return (ret); | |
1763 } | |
1764 | |
1765 /* | |
1766 * Procedure getok | |
1767 * | |
1768 * Purpose: Reads a line from the server. If the return indicator is | |
1769 * positive, return with a zero exit status. If not, return with | |
1770 * a negative exit status. | |
1771 * | |
1772 * Arguments: | |
1773 * server The server to read from. | |
1774 * | |
1775 * Returns: 0 for success, else for failure and puts error in pop_error. | |
1776 * | |
14036 | 1777 * Side effects: On failure, may make the connection unusable. |
9158 | 1778 */ |
1779 static int | |
1780 getok (server) | |
1781 popserver server; | |
1782 { | |
1783 char *fromline; | |
1784 | |
21295
f399e51d6d11
(pop_getline): Renamed from getline.
Richard M. Stallman <rms@gnu.org>
parents:
20418
diff
changeset
|
1785 if (pop_getline (server, &fromline) < 0) |
9158 | 1786 { |
1787 return (-1); | |
1788 } | |
1789 | |
1790 if (! strncmp (fromline, "+OK", 3)) | |
1791 return (0); | |
1792 else if (! strncmp (fromline, "-ERR", 4)) | |
1793 { | |
1794 strncpy (pop_error, fromline, ERROR_MAX); | |
1795 pop_error[ERROR_MAX-1] = '\0'; | |
1796 return (-1); | |
1797 } | |
1798 else | |
1799 { | |
1800 strcpy (pop_error, | |
1801 "Unexpected response from server; expecting +OK or -ERR"); | |
1802 pop_trash (server); | |
1803 return (-1); | |
1804 } | |
1805 } | |
1806 | |
1807 #if 0 | |
1808 /* | |
1809 * Function: gettermination | |
1810 * | |
1811 * Purpose: Gets the next line and verifies that it is a termination | |
1812 * line (nothing but a dot). | |
1813 * | |
1814 * Return value: 0 on success, non-zero with pop_error set on error. | |
1815 * | |
1816 * Side effects: Closes the connection on error. | |
1817 */ | |
1818 static int | |
1819 gettermination (server) | |
1820 popserver server; | |
1821 { | |
1822 char *fromserver; | |
1823 | |
21295
f399e51d6d11
(pop_getline): Renamed from getline.
Richard M. Stallman <rms@gnu.org>
parents:
20418
diff
changeset
|
1824 if (pop_getline (server, &fromserver) < 0) |
9158 | 1825 return (-1); |
1826 | |
1827 if (strcmp (fromserver, ".")) | |
1828 { | |
1829 strcpy (pop_error, | |
1830 "Unexpected response from server in gettermination"); | |
1831 pop_trash (server); | |
1832 return (-1); | |
1833 } | |
1834 | |
1835 return (0); | |
1836 } | |
1837 #endif | |
1838 | |
1839 /* | |
1840 * Function pop_close | |
1841 * | |
1842 * Purpose: Close a pop connection, sending a "RSET" command to try to | |
1843 * preserve any changes that were made and a "QUIT" command to | |
1844 * try to get the server to quit, but ignoring any responses that | |
1845 * are received. | |
1846 * | |
14036 | 1847 * Side effects: The server is unusable after this function returns. |
9158 | 1848 * Changes made to the maildrop since the session was started (or |
1849 * since the last pop_reset) may be lost. | |
1850 */ | |
1851 void | |
1852 pop_close (server) | |
1853 popserver server; | |
1854 { | |
1855 pop_trash (server); | |
1856 free ((char *) server); | |
1857 | |
1858 return; | |
1859 } | |
1860 | |
1861 /* | |
1862 * Function: pop_trash | |
1863 * | |
1864 * Purpose: Like pop_close or pop_quit, but doesn't deallocate the | |
1865 * memory associated with the server. It is legal to call | |
1866 * pop_close or pop_quit after this function has been called. | |
1867 */ | |
1868 static void | |
1869 pop_trash (server) | |
1870 popserver server; | |
1871 { | |
1872 if (server->file >= 0) | |
1873 { | |
15102
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
1874 /* avoid recursion; sendline can call pop_trash */ |
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
1875 if (server->trash_started) |
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
1876 return; |
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
1877 server->trash_started = 1; |
15108
442458addd50
(SEND, RECV): Renamed from send, recv.
Richard M. Stallman <rms@gnu.org>
parents:
15102
diff
changeset
|
1878 |
9158 | 1879 sendline (server, "RSET"); |
1880 sendline (server, "QUIT"); | |
1881 | |
15108
442458addd50
(SEND, RECV): Renamed from send, recv.
Richard M. Stallman <rms@gnu.org>
parents:
15102
diff
changeset
|
1882 CLOSESOCKET (server->file); |
9158 | 1883 server->file = -1; |
1884 if (server->buffer) | |
1885 { | |
1886 free (server->buffer); | |
1887 server->buffer = 0; | |
1888 } | |
21397 | 1889 #ifdef GSSAPI |
1890 if (server->extra) | |
1891 { | |
1892 OM_uint32 minor; | |
1893 | |
1894 if (Gssapi (server->extra)->gss_context != GSS_C_NO_CONTEXT) | |
1895 gss_delete_sec_context (&minor, | |
1896 &(Gssapi (server->extra)->gss_context), | |
1897 GSS_C_NO_BUFFER); | |
1898 free ((char *) server->extra); | |
1899 server->extra = 0; | |
1900 } | |
1901 #endif /* GSSAPI */ | |
9158 | 1902 } |
15102
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
1903 |
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
1904 #ifdef WINDOWSNT |
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
1905 if (have_winsock) |
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
1906 WSACleanup (); |
ed550d0805ca
[WINDOWSNT]: Include winsock.h and ntlib.h.
Richard M. Stallman <rms@gnu.org>
parents:
14238
diff
changeset
|
1907 #endif |
9158 | 1908 } |
1909 | |
21397 | 1910 #ifdef GSSAPI |
1911 /* | |
1912 * Function: pop_auth | |
1913 * | |
1914 * Purpose: To perform a GSSAPI authentication handshake with a POP server. | |
1915 * If the negotiation is successful, it will return 0; otherwise, it | |
1916 * will fill in pop_error with the error message and return either -1, | |
1917 * indicating a potentially recoverable error, or -2, indicating an | |
1918 * unrecoverable error. | |
1919 * | |
1920 * Side effects: The server may choose to close the connection if the | |
1921 * handshake fails. The connection will be trashed if the error is | |
1922 * unrecoverable. | |
1923 */ | |
1924 static int | |
1925 pop_auth (server, username, host, flags) | |
1926 popserver server; | |
1927 char *username, *host; | |
1928 int flags; | |
1929 { | |
1930 int gss_flags, ret; | |
1931 char *fromserver; | |
1932 OM_uint32 max_size, t_flags; | |
1933 gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT; | |
1934 gss_buffer_desc in_tok, out_tok; | |
1935 gss_name_t svc_name; | |
1936 OM_uint32 major, minor, t_minor; | |
1937 | |
1938 /* calculate usable protection mechanisms */ | |
1939 gss_flags = (GSSAPI_PROTECTION & | |
1940 ~(((flags & POP_NO_NOPROT) ? GSSAPI_NOPROT : 0) | | |
1941 ((flags & POP_NO_INTEG) ? GSSAPI_INTEGRITY : 0) | | |
1942 ((flags & POP_NO_ENCRYPT) ? GSSAPI_PRIVACY : 0))); | |
1943 | |
1944 if (gss_flags == 0) | |
1945 { | |
1946 strcpy (pop_error, "Unable to provide selected protection level"); | |
1947 return (-1); | |
1948 } | |
1949 | |
1950 /* import service name of pop server */ | |
1951 in_tok.value = (void *) malloc (strlen (host) + sizeof (GSSAPI_SERVICE) + 2); | |
1952 | |
1953 if (! in_tok.value) | |
1954 { | |
1955 strcpy (pop_error, "Out of memory in pop_auth"); | |
1956 return (-1); | |
1957 } | |
1958 | |
1959 sprintf ((char *) in_tok.value, "%s@%s", GSSAPI_SERVICE, host); | |
1960 in_tok.length = strlen ((char *) in_tok.value); | |
1961 | |
1962 { | |
1963 gss_OID_desc svc_name_oid = GSSAPI_SVC_TYPE; | |
1964 | |
1965 major = gss_import_name (&minor, &in_tok, &svc_name_oid, &svc_name); | |
1966 } | |
1967 | |
1968 free ((char *) in_tok.value); | |
1969 | |
1970 if (major != GSS_S_COMPLETE) | |
1971 { | |
1972 gen_gss_error ("parsing name", major, minor); | |
1973 return (-1); | |
1974 } | |
1975 | |
1976 /* begin GSSAPI authentication handshake */ | |
1977 if (sendline (server, "AUTH GSSAPI") || (pop_getline (server, &fromserver) < 0)) | |
1978 { | |
1979 gss_release_name (&t_minor, &svc_name); | |
1980 return (-1); | |
1981 } | |
1982 | |
1983 do | |
1984 { | |
1985 /* sanity-check server response */ | |
1986 if (strncmp (fromserver, "+ ", 2)) | |
1987 { | |
1988 gss_release_name (&t_minor, &svc_name); | |
1989 if (gss_context != GSS_C_NO_CONTEXT) | |
1990 gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER); | |
1991 if (0 == strncmp (fromserver, "-ERR", 4)) | |
1992 { | |
1993 strncpy (pop_error, fromserver, ERROR_MAX); | |
1994 return (-1); | |
1995 } | |
1996 else | |
1997 { | |
1998 pop_trash (server); | |
1999 strcpy (pop_error, | |
2000 "Unexpected response from POP server in pop_auth"); | |
2001 return (-2); | |
2002 } | |
2003 } | |
2004 | |
2005 if (strlen (fromserver) > 2) | |
2006 { | |
2007 /* base 64 decode the response... */ | |
2008 ret = b64_decode (fromserver + 2, &in_tok); | |
2009 if (ret != B64_SUCCESS) | |
2010 { | |
2011 gss_release_name (&t_minor, &svc_name); | |
2012 if (gss_context != GSS_C_NO_CONTEXT) | |
2013 gss_delete_sec_context (&t_minor, &gss_context, | |
2014 GSS_C_NO_BUFFER); | |
2015 sendline (server, "*"); | |
2016 strcpy (pop_error, b64_error[ret]); | |
2017 return (-1); | |
2018 } | |
2019 } | |
2020 else | |
2021 { | |
2022 in_tok.length = 0; | |
2023 in_tok.value = 0; | |
2024 } | |
2025 | |
2026 /* call init_sec_context */ | |
2027 major = gss_init_sec_context (&minor, GSS_C_NO_CREDENTIAL, &gss_context, | |
2028 svc_name, GSS_C_NULL_OID, | |
2029 GSS_C_MUTUAL_FLAG, 0, | |
2030 GSS_C_NO_CHANNEL_BINDINGS, | |
2031 in_tok.length ? & in_tok : GSS_C_NO_BUFFER, | |
2032 0, &out_tok, 0, 0); | |
2033 | |
2034 if (in_tok.length != 0) | |
2035 free ((char *) in_tok.value); | |
2036 | |
2037 /* check for error */ | |
2038 if (GSS_ERROR (major)) | |
2039 { | |
2040 gss_release_name (&t_minor, &svc_name); | |
2041 if (gss_context != GSS_C_NO_CONTEXT) | |
2042 gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER); | |
2043 sendline (server, "*"); | |
2044 gen_gss_error ("in init_sec_context", major, minor); | |
2045 return (-1); | |
2046 } | |
2047 | |
2048 if (out_tok.length != 0) | |
2049 { | |
2050 /* base 64 encode output token, if any */ | |
2051 ret = b64_encode (&out_tok, &fromserver); | |
2052 | |
2053 gss_release_buffer (&t_minor, &out_tok); | |
2054 | |
2055 if (ret != B64_SUCCESS) | |
2056 { | |
2057 gss_release_name (&t_minor, &svc_name); | |
2058 if (gss_context != GSS_C_NO_CONTEXT) | |
2059 gss_delete_sec_context (&t_minor, &gss_context, | |
2060 GSS_C_NO_BUFFER); | |
2061 sendline (server, "*"); | |
2062 strcpy (pop_error, b64_error[ret]); | |
2063 return (-1); | |
2064 } | |
2065 | |
2066 /* send output token... */ | |
2067 ret = sendline (server, fromserver); | |
2068 | |
2069 free (fromserver); | |
2070 } | |
2071 else | |
2072 /* empty output token... */ | |
2073 ret = sendline (server, ""); | |
2074 | |
2075 /* get next token from server */ | |
2076 if (ret || (pop_getline (server, &fromserver) < 0)) | |
2077 { | |
2078 gss_release_name (&t_minor, &svc_name); | |
2079 if (gss_context != GSS_C_NO_CONTEXT) | |
2080 gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER); | |
2081 return (-1); | |
2082 } | |
2083 } while ((major & GSS_S_CONTINUE_NEEDED)); | |
2084 | |
2085 /* release name... */ | |
2086 gss_release_name (&t_minor, &svc_name); | |
2087 | |
2088 /* get final response from server */ | |
2089 if (strncmp (fromserver, "+ ", 2)) | |
2090 { | |
2091 gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER); | |
2092 if (0 == strncmp (fromserver, "-ERR", 4)) | |
2093 { | |
2094 strncpy (pop_error, fromserver, ERROR_MAX); | |
2095 return (-1); | |
2096 } | |
2097 else | |
2098 { | |
2099 pop_trash (server); | |
2100 strcpy (pop_error, | |
2101 "Unexpected response from POP server in pop_auth"); | |
2102 return (-2); | |
2103 } | |
2104 } | |
2105 | |
2106 /* base 64 decode... */ | |
2107 ret = b64_decode (fromserver + 2, &in_tok); | |
2108 if (ret != B64_SUCCESS) | |
2109 { | |
2110 gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER); | |
2111 sendline (server, "*"); | |
2112 strcpy (pop_error, b64_error[ret]); | |
2113 return (-1); | |
2114 } | |
2115 | |
2116 /* unwrap... */ | |
2117 major = gss_unwrap (&minor, gss_context, &in_tok, &out_tok, 0, 0); | |
2118 | |
2119 free ((char *) in_tok.value); | |
2120 | |
2121 if (major != GSS_S_COMPLETE || out_tok.length != sizeof (t_flags)) | |
2122 { | |
2123 if (out_tok.length != 0) | |
2124 gss_release_buffer (&t_minor, &out_tok); | |
2125 gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER); | |
2126 sendline (server, "*"); | |
2127 gen_gss_error ("in gss_unwrap", major, minor); | |
2128 return (-1); | |
2129 } | |
2130 | |
2131 /* get and check flags/size */ | |
2132 bcopy ((void *) out_tok.value, (void *) &t_flags, sizeof (t_flags)); | |
2133 | |
2134 gss_release_buffer (&t_minor, &out_tok); | |
2135 | |
2136 max_size = ntohl (t_flags); | |
2137 | |
2138 t_flags = ((max_size & 0xFF000000) >> 24) & gss_flags; | |
2139 max_size &= 0x00FFFFFF; | |
2140 | |
2141 if ((t_flags & GSSAPI_PRIVACY)) | |
2142 gss_flags = GSSAPI_PRIVACY; | |
2143 | |
2144 else if ((t_flags & GSSAPI_INTEGRITY)) | |
2145 gss_flags = GSSAPI_INTEGRITY; | |
2146 | |
2147 else if ((t_flags & GSSAPI_NOPROT)) | |
2148 gss_flags = GSSAPI_NOPROT; | |
2149 | |
2150 else | |
2151 { | |
2152 gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER); | |
2153 sendline (server, "*"); | |
2154 strcpy (pop_error, "Server does not provide selected protection level"); | |
2155 return (-1); | |
2156 } | |
2157 | |
2158 if (max_size == 0) | |
2159 { | |
2160 gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER); | |
2161 sendline (server, "*"); | |
2162 strcpy (pop_error, "Bad server max length"); | |
2163 return (-1); | |
2164 } | |
2165 | |
2166 if ((gss_flags & GSSAPI_NEEDWRAP)) | |
2167 { | |
2168 major = gss_wrap_size_limit (&t_minor, gss_context, | |
2169 (gss_flags & GSSAPI_PRIVACY) ? 1 : 0, | |
2170 GSS_C_QOP_DEFAULT, | |
2171 (max_size < GSSAPI_RCVBUF) ? max_size : | |
2172 GSSAPI_RCVBUF, &max_size); | |
2173 if (major != GSS_S_COMPLETE) | |
2174 { | |
2175 gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER); | |
2176 sendline (server, "*"); | |
2177 gen_gss_error ("getting max size", major, minor); | |
2178 return (-1); | |
2179 } | |
2180 } | |
2181 | |
2182 /* generate return flags */ | |
2183 { | |
2184 OM_uint32 tmp; | |
2185 | |
2186 tmp = (((gss_flags << 24) & 0xFF000000) | (GSSAPI_RCVBUF & 0x00FFFFFF)); | |
2187 t_flags = ntohl (tmp); | |
2188 } | |
2189 | |
2190 in_tok.length = sizeof (t_flags) + strlen (username); | |
2191 in_tok.value = (void *) malloc (in_tok.length); | |
2192 | |
2193 if (! in_tok.value) | |
2194 { | |
2195 gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER); | |
2196 sendline (server, "*"); | |
2197 strcpy (pop_error, "Out of memory in pop_auth"); | |
2198 return (-1); | |
2199 } | |
2200 | |
2201 bcopy ((void *) &t_flags, in_tok.value, sizeof (t_flags)); | |
2202 bcopy ((void *) username, | |
2203 (void *) (((char *) in_tok.value) + sizeof (t_flags)), | |
2204 in_tok.length - sizeof (t_flags)); | |
2205 | |
2206 /* wrap result */ | |
2207 major = gss_wrap (&minor, gss_context, 0, GSS_C_QOP_DEFAULT, | |
2208 &in_tok, 0, &out_tok); | |
2209 | |
2210 free ((char *) in_tok.value); | |
2211 | |
2212 if (major != GSS_S_COMPLETE || out_tok.length == 0) | |
2213 { | |
2214 if (out_tok.length != 0) | |
2215 gss_release_buffer (&t_minor, &out_tok); | |
2216 gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER); | |
2217 sendline (server, "*"); | |
2218 gen_gss_error ("in gss_wrap", major, minor); | |
2219 return (-1); | |
2220 } | |
2221 | |
2222 /* base 64 encode... */ | |
2223 ret = b64_encode (&out_tok, &fromserver); | |
2224 | |
2225 gss_release_buffer (&t_minor, &out_tok); | |
2226 | |
2227 if (ret != B64_SUCCESS) | |
2228 { | |
2229 gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER); | |
2230 sendline (server, "*"); | |
2231 strcpy (pop_error, b64_error[ret]); | |
2232 return (-1); | |
2233 } | |
2234 | |
2235 /* send to server */ | |
2236 ret = sendline (server, fromserver); | |
2237 | |
2238 free (fromserver); | |
2239 | |
2240 /* see if the server likes me... */ | |
2241 if (ret || getok (server)) | |
2242 { | |
2243 gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER); | |
2244 return (-1); | |
2245 } | |
2246 | |
2247 /* stash context */ | |
2248 { | |
2249 struct _pop_gssapi *gss_data; | |
2250 | |
2251 gss_data = (struct _pop_gssapi *) malloc (sizeof (struct _pop_gssapi)); | |
2252 | |
2253 if (! gss_data) | |
2254 { | |
2255 pop_trash (server); | |
2256 gss_delete_sec_context (&t_minor, &gss_context, GSS_C_NO_BUFFER); | |
2257 strcpy (pop_error, "Out of memory in pop_auth"); | |
2258 return (-2); | |
2259 } | |
2260 | |
2261 gss_data->gss_flags = gss_flags; | |
2262 gss_data->max_size = max_size; | |
2263 gss_data->gss_context = gss_context; | |
2264 | |
2265 server->extra = gss_data; | |
2266 } | |
2267 | |
2268 return (0); | |
2269 } | |
2270 | |
2271 /* | |
2272 * Add as much error text to pop_error as will fit, but only put complete | |
2273 * messages | |
2274 */ | |
2275 static void | |
2276 gen_gss_error (msg, major, minor) | |
2277 char *msg; | |
2278 OM_uint32 major, minor; | |
2279 { | |
2280 char *p = pop_error, *t, *saved; | |
2281 int max = ERROR_MAX - 1; /* for \0 */ | |
2282 OM_uint32 t_minor, msg_ctx = 0; | |
2283 gss_buffer_desc gss_msg; | |
2284 | |
2285 while (*msg && max) | |
2286 { | |
2287 *p++ = *msg++; | |
2288 max--; | |
2289 } | |
2290 | |
2291 if (max >= 2) | |
2292 { | |
2293 saved = p; | |
2294 *p++ = ':'; | |
2295 *p++ = ' '; | |
2296 max -= 2; | |
2297 } | |
2298 else | |
2299 { | |
2300 *p = '\0'; | |
2301 return; | |
2302 } | |
2303 | |
2304 do | |
2305 { | |
2306 gss_display_status (&t_minor, major, GSS_C_GSS_CODE, GSS_C_NO_OID, | |
2307 &msg_ctx, &gss_msg); | |
2308 for (t = (char *) gss_msg.value; *t && max; max--) | |
2309 { | |
2310 *p++ = *t++; | |
2311 } | |
2312 gss_release_buffer (&t_minor, &gss_msg); | |
2313 if (max == 0) | |
2314 { | |
2315 *saved = '\0'; | |
2316 return; | |
2317 } | |
2318 } while (msg_ctx); | |
2319 | |
2320 saved = p; | |
2321 | |
2322 do | |
2323 { | |
2324 gss_display_status (&t_minor, minor, GSS_C_MECH_CODE, GSS_C_NO_OID, | |
2325 &msg_ctx, &gss_msg); | |
2326 for (t = (char *) gss_msg.value; *t && max; max--) | |
2327 { | |
2328 *p++ = *t++; | |
2329 } | |
2330 gss_release_buffer (&t_minor, &gss_msg); | |
2331 if (max == 0) | |
2332 { | |
2333 *saved = '\0'; | |
2334 return; | |
2335 } | |
2336 } while (msg_ctx); | |
2337 | |
2338 *p = '\0'; | |
2339 return; | |
2340 } | |
2341 | |
2342 /* | |
2343 * table-based base64 decoding function; takes 4 characters from in and | |
2344 * writes from 1 to 3 bytes to out, storing the amount written in len | |
2345 */ | |
2346 static int | |
2347 b64_d (in, out, len) | |
2348 char *in, *out; | |
2349 int *len; | |
2350 { | |
2351 int decodearray[] = | |
2352 { | |
2353 0x3e, -1, -1, -1, 0x3f, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, | |
2354 0x3b, 0x3c, 0x3d, -1, -1, -1, -1, -1, -1, -1, 0x00, 0x01, | |
2355 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, | |
2356 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, | |
2357 -1, -1, -1, -1, -1, -1, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, | |
2358 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, | |
2359 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33 | |
2360 }; | |
2361 | |
2362 int d; | |
2363 | |
2364 if (!in || !out || !len) | |
2365 return (B64_BADPARAM); | |
2366 | |
2367 if (*in < '+' || *in > 'z') | |
2368 return (B64_BADCHAR); | |
2369 | |
2370 d = decodearray[*(in++) - '+']; | |
2371 if (d == -1) | |
2372 return (B64_BADCHAR); | |
2373 *out = d << 2; | |
2374 | |
2375 if (*in < '+' || *in > 'z') | |
2376 return (B64_BADCHAR); | |
2377 | |
2378 d = decodearray[*(in++) - '+']; | |
2379 if (d == -1) | |
2380 return (B64_BADCHAR); | |
2381 *(out++) |= d >> 4; | |
2382 *out = (d & 15) << 4; | |
2383 | |
2384 if (*in < '+' || *in > 'z') | |
2385 return (B64_BADCHAR); | |
2386 else if (*in == '=') | |
2387 if (*(in + 1) != '=') | |
2388 return (B64_BADPAD); | |
2389 else | |
2390 { | |
2391 *len = 1; | |
2392 return (B64_SUCCESS); | |
2393 } | |
2394 | |
2395 d = decodearray[*(in++) - '+']; | |
2396 if (d == -1) | |
2397 return (B64_BADCHAR); | |
2398 *(out++) |= d >> 2; | |
2399 *out = (d & 3) << 6; | |
2400 | |
2401 if (*in < '+' || *in > 'z') | |
2402 return (B64_BADCHAR); | |
2403 else if (*in == '=') | |
2404 { | |
2405 *len = 2; | |
2406 return (B64_SUCCESS); | |
2407 } | |
2408 | |
2409 d = decodearray[*in - '+']; | |
2410 if (d == -1) | |
2411 return (B64_BADCHAR); | |
2412 *out |= d; | |
2413 | |
2414 *len = 3; | |
2415 return (B64_SUCCESS); | |
2416 } | |
2417 | |
2418 /* | |
2419 * simple base64 encoding function that takes from 0 to 3 bytes and | |
2420 * outputs 4 encoded characters, with appropriate padding | |
2421 */ | |
2422 static int | |
2423 b64_e (in, out, len) | |
2424 unsigned char *in, *out; | |
2425 int len; | |
2426 { | |
2427 unsigned char codearray[] = | |
2428 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | |
2429 | |
2430 if (!in || !out || len <= 0 || len > 3) | |
2431 return (B64_BADPARAM); | |
2432 | |
2433 *(out++) = codearray[((*in) >> 2)]; | |
2434 | |
2435 if (--len == 0) | |
2436 { | |
2437 *(out++) = codearray[(((*in) & 3) << 4)]; | |
2438 *(out++) = '='; | |
2439 *out = '='; | |
2440 return (B64_SUCCESS); | |
2441 } | |
2442 | |
2443 *(out++) = codearray[(((*in) & 3) << 4) | ((*(in + 1)) >> 4)]; | |
2444 in++; | |
2445 | |
2446 if (--len == 0) | |
2447 { | |
2448 *(out++) = codearray[(((*in) & 15) << 2)]; | |
2449 *out = '='; | |
2450 return (B64_SUCCESS); | |
2451 } | |
2452 | |
2453 *(out++) = codearray[(((*in) & 15) << 2) | ((*(in + 1)) >> 6)]; | |
2454 *out = codearray[((*(in + 1)) & 63)]; | |
2455 | |
2456 return (B64_SUCCESS); | |
2457 } | |
2458 | |
2459 /* | |
2460 * given an input string, generate an output gss_buffer_t containing the | |
2461 * decoded data and correct length; works by repeatedly driving b64_d () | |
2462 * over the input string | |
2463 */ | |
2464 static int | |
2465 b64_decode (enc, dec) | |
2466 char *enc; | |
2467 gss_buffer_t dec; | |
2468 { | |
2469 char *tmp; | |
2470 int inlen, outlen = 0, t_len, ret; | |
2471 | |
2472 if (!enc || !dec) | |
2473 return (B64_BADPARAM); | |
2474 | |
2475 dec->value = 0; | |
2476 dec->length = 0; | |
2477 | |
2478 inlen = strlen (enc); | |
2479 if ((inlen % 4)) | |
2480 return (B64_BADLEN); | |
2481 | |
2482 dec->value = (void *) (tmp = (char *) malloc ((inlen / 4) * 3)); | |
2483 | |
2484 if (! tmp) | |
2485 return (B64_NOMEM); | |
2486 | |
2487 for (; inlen; inlen -= 4) | |
2488 { | |
2489 ret = b64_d (enc, tmp, &t_len); | |
2490 if (ret != B64_SUCCESS) | |
2491 { | |
2492 free ((char *) dec->value); | |
2493 dec->value = 0; | |
2494 return (ret); | |
2495 } | |
2496 else if (t_len != 3) | |
2497 { | |
2498 dec->length = outlen + t_len; | |
2499 return (B64_SUCCESS); | |
2500 } | |
2501 else | |
2502 { | |
2503 enc += 4; | |
2504 tmp += t_len; | |
2505 outlen += t_len; | |
2506 } | |
2507 } | |
2508 | |
2509 dec->length = outlen; | |
2510 return (B64_SUCCESS); | |
2511 } | |
2512 | |
2513 /* | |
2514 * given a gss_buffer_t, generate an encoded string containing the data. | |
2515 * works by repeatedly driving b64_e () over the contents of the buffer_t | |
2516 */ | |
2517 static int | |
2518 b64_encode (dec, enc) | |
2519 gss_buffer_t dec; | |
2520 char **enc; | |
2521 { | |
2522 unsigned char *tmp, *in; | |
2523 int ret, len; | |
2524 | |
2525 if (!dec || !enc) | |
2526 return (B64_BADPARAM); | |
2527 | |
2528 in = (unsigned char *) dec->value; | |
2529 len = dec->length; | |
2530 *enc = (char *) (tmp = (unsigned char *) malloc (((len * 4) / 3) + 5)); | |
2531 | |
2532 if (! tmp) | |
2533 return (B64_NOMEM); | |
2534 | |
2535 do | |
2536 { | |
2537 ret = b64_e (in, tmp, len >= 3 ? 3 : len); | |
2538 if (ret != B64_SUCCESS) | |
2539 { | |
2540 free (*enc); | |
2541 *enc = 0; | |
2542 return (ret); | |
2543 } | |
2544 else | |
2545 { | |
2546 in += 3; | |
2547 tmp += 4; | |
2548 } | |
2549 } while ((len -= 3) > 0); | |
2550 | |
2551 *tmp = '\0'; | |
2552 | |
2553 return (B64_SUCCESS); | |
2554 } | |
2555 | |
2556 #endif /* GSSAPI */ | |
2557 | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
2558 /* Return a pointer to the first CRLF in IN_STRING, which can contain |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
2559 embedded nulls and has LEN characters in it not including the final |
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
2560 null, or 0 if it does not contain one. */ |
9158 | 2561 |
2562 static char * | |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
2563 find_crlf (in_string, len) |
9613
530b4511e5b3
Only include ../src/config.h if HAVE_CONFIG_H is
Richard M. Stallman <rms@gnu.org>
parents:
9600
diff
changeset
|
2564 char *in_string; |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
2565 int len; |
9158 | 2566 { |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
2567 while (len--) |
9158 | 2568 { |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
2569 if (*in_string == '\r') |
9613
530b4511e5b3
Only include ../src/config.h if HAVE_CONFIG_H is
Richard M. Stallman <rms@gnu.org>
parents:
9600
diff
changeset
|
2570 { |
530b4511e5b3
Only include ../src/config.h if HAVE_CONFIG_H is
Richard M. Stallman <rms@gnu.org>
parents:
9600
diff
changeset
|
2571 if (*++in_string == '\n') |
530b4511e5b3
Only include ../src/config.h if HAVE_CONFIG_H is
Richard M. Stallman <rms@gnu.org>
parents:
9600
diff
changeset
|
2572 return (in_string - 1); |
530b4511e5b3
Only include ../src/config.h if HAVE_CONFIG_H is
Richard M. Stallman <rms@gnu.org>
parents:
9600
diff
changeset
|
2573 } |
530b4511e5b3
Only include ../src/config.h if HAVE_CONFIG_H is
Richard M. Stallman <rms@gnu.org>
parents:
9600
diff
changeset
|
2574 else |
530b4511e5b3
Only include ../src/config.h if HAVE_CONFIG_H is
Richard M. Stallman <rms@gnu.org>
parents:
9600
diff
changeset
|
2575 in_string++; |
9158 | 2576 } |
20418
7e1538a45702
Allow messages retrieved from the POP
Karl Heuer <kwzh@gnu.org>
parents:
20204
diff
changeset
|
2577 return (0); |
9158 | 2578 } |
2579 | |
2580 #endif /* MAIL_USE_POP */ |