+static int do_apop(int sock, struct query *ctl, char *greeting)
+{
+ char *start, *end;
+
+ /* build MD5 digest from greeting timestamp + password */
+ /* find start of timestamp */
+ start = strchr(greeting, '<');
+ if (!start) {
+ if (ctl->server.authenticate == A_APOP || outlevel >= O_DEBUG) {
+ report(ctl->server.authenticate == A_APOP ? stderr : stdout,
+ GT_("Required APOP timestamp not found in greeting\n"));
+ }
+ return PS_AUTHFAIL;
+ }
+
+ /* find end of timestamp */
+ end = strchr(start + 1, '>');
+
+ if (!end || end == start + 1) {
+ report(stderr,
+ GT_("Timestamp syntax error in greeting\n"));
+ return(PS_AUTHFAIL);
+ } else {
+ *++end = '\0';
+ }
+
+ /* SECURITY: 2007-03-17
+ * Strictly validating the presented challenge for RFC-822
+ * conformity (it must be a msg-id in terms of that standard) is
+ * supposed to make attacks against the MD5 implementation
+ * harder[1]
+ *
+ * [1] "Security vulnerability in APOP authentication",
+ * Gaëtan Leurent, fetchmail-devel, 2007-03-17 */
+ if (!rfc822_valid_msgid((unsigned char *)start)) {
+ report(stderr,
+ GT_("Invalid APOP timestamp.\n"));
+ return PS_AUTHFAIL;
+ }
+
+ /* copy timestamp and password into digestion buffer */
+ char *msg = (char *)xmalloc((end-start+1) + strlen(ctl->password) + 1);
+ strcpy(msg,start);
+ strcat(msg,ctl->password);
+ strcpy((char *)ctl->digest, MD5Digest((unsigned char *)msg));
+ free(msg);
+
+ return gen_transact(sock, "APOP %s %s", ctl->remotename, (char *)ctl->digest);
+}
+