EXPORTED int command_pclose(struct command **cmdp) { struct command *cmd = (cmdp ? *cmdp : NULL); int r; if (!cmd) return 0; if (cmd->stdin_prot) { prot_flush(cmd->stdin_prot); close(cmd->stdin_prot->fd); prot_free(cmd->stdin_prot); } if (cmd->stdout_prot) { close(cmd->stdout_prot->fd); prot_free(cmd->stdout_prot); } r = wait_for_child(cmd->argv0, cmd->pid); free(cmd->argv0); free(cmd); *cmdp = NULL; return r; }
int deleteascript(int version, struct protstream *pout, struct protstream *pin, const char *name, char **refer_to, char **errstrp) { lexstate_t state; int res; int ret; char *errstr = NULL; prot_printf(pout,"DELETESCRIPT \"%s\"\r\n",name); prot_flush(pout); res=yylex(&state, pin); ret = handle_response(res,version,pin,refer_to,&errstr); if(ret == -2 && *refer_to) { return -2; } else if (ret!=0) { *errstrp = strconcat("Deleting script: ", errstr, (char *)NULL); return -1; } return 0; }
/* Proxy GETANNOTATION commands to backend */ int annotate_fetch_proxy(const char *server, const char *mbox_pat, const strarray_t *entry_pat, const strarray_t *attribute_pat) { struct backend *be; int i; char mytag[128]; assert(server && mbox_pat && entry_pat && attribute_pat); be = proxy_findserver(server, &imap_protocol, proxy_userid, &backend_cached, &backend_current, &backend_inbox, imapd_in); if (!be) return IMAP_SERVER_UNAVAILABLE; /* Send command to remote */ proxy_gentag(mytag, sizeof(mytag)); prot_printf(be->out, "%s GETANNOTATION \"%s\" (", mytag, mbox_pat); for (i = 0 ; i < entry_pat->count ; i++) { prot_printf(be->out, "%s\"%s\"", i ? " " : "", entry_pat->data[i]); } prot_printf(be->out, ") ("); for (i = 0 ; i < attribute_pat->count ; i++) { prot_printf(be->out, "%s\"%s\"", i ? " " : "", attribute_pat->data[i]); } prot_printf(be->out, ")\r\n"); prot_flush(be->out); /* Pipe the results. Note that backend-current may also pipe us other messages. */ pipe_until_tag(be, mytag, 0); return 0; }
static int ping(struct backend *s, const char *userid) { unsigned code = 0; const char *errstr; hdrcache_t resp_hdrs = NULL; struct body_t resp_body; /* Send Authorization request to server */ prot_puts(s->out, "OPTIONS * HTTP/1.1\r\n"); prot_printf(s->out, "Host: %s\r\n", s->hostname); prot_printf(s->out, "User-Agent: %s\r\n", buf_cstring(&serverinfo)); prot_printf(s->out, "Authorize-As: %s\r\n", userid ? userid : "anonymous"); prot_puts(s->out, "\r\n"); prot_flush(s->out); /* Read response(s) from backend until final response or error */ do { resp_body.flags = BODY_DISCARD; if (http_read_response(s, METH_OPTIONS, &code, NULL, &resp_hdrs, &resp_body, &errstr)) { break; } } while (code < 200); if (resp_hdrs) spool_free_hdrcache(resp_hdrs); return (code != 200); }
int installdata(int version,struct protstream *pout, struct protstream *pin, char *scriptname, char *data, int len, char **refer_to, char **errstrp) { int res; int ret; char *errstr=NULL; lexstate_t state; prot_printf(pout, "PUTSCRIPT \"%s\" ",scriptname); prot_printf(pout, "{%d+}\r\n",len); prot_write(pout, data, len); prot_printf(pout,"\r\n"); prot_flush(pout); /* now let's see what the server said */ res=yylex(&state,pin); ret = handle_response(res,version,pin,refer_to,&errstr); /* if command failed */ if(ret == -2 && *refer_to) { return -2; } else if (ret!=0) { *errstrp = strconcat("Putting script: ", errstr, (char *)NULL); return -1; } return 0; }
void shut_down(int code) { /* free interpreter */ if (interp) sieve_interp_free(&interp); /* close backend connection */ if (backend) { backend_disconnect(backend); free(backend); } /* close mailboxes */ mboxlist_close(); mboxlist_done(); /* cleanup */ if (sieved_out) { prot_flush(sieved_out); prot_free(sieved_out); } if (sieved_in) prot_free(sieved_in); if (sieved_logfd != -1) close(sieved_logfd); #ifdef HAVE_SSL tls_shutdown_serverengine(); #endif cyrus_done(); cyrus_reset_stdio(); /* done */ exit(code); }
int detect_mitm(isieve_t *obj, char *mechlist) { char *new_mechlist; int ch, r = 0; /* wait and probe for possible automatic capability response */ usleep(250000); prot_NONBLOCK(obj->pin); if ((ch = prot_getc(obj->pin)) != EOF) { /* automatic capability response */ prot_ungetc(ch, obj->pin); } else { /* manually ask for capabilities */ prot_printf(obj->pout, "CAPABILITY\r\n"); prot_flush(obj->pout); } prot_BLOCK(obj->pin); if ((new_mechlist = read_capability(obj))) { /* if the server still advertises SASL mechs, compare lists */ r = strcmp(new_mechlist, mechlist); free(new_mechlist); } return r; }
EXPORTED int backend_ping(struct backend *s, const char *userid) { char buf[1024]; struct simple_cmd_t *ping_cmd; if (!s) return 0; if (s->sock == -1) return -1; /* Disconnected Socket */ if (s->prot->type == TYPE_SPEC) return s->prot->u.spec.ping(s, userid); ping_cmd = &s->prot->u.std.ping_cmd; if (!ping_cmd->cmd) return 0; prot_printf(s->out, "%s\r\n", ping_cmd->cmd); prot_flush(s->out); for (;;) { if (!prot_fgets(buf, sizeof(buf), s->in)) { /* connection closed? */ return -1; } else if (ping_cmd->unsol && !strncmp(ping_cmd->unsol, buf, strlen(ping_cmd->unsol))) { /* unsolicited response */ continue; } else { /* success/fail response */ return strncmp(ping_cmd->ok, buf, strlen(ping_cmd->ok)); } } }
int setscriptactive(int version, struct protstream *pout, struct protstream *pin,char *name, char **refer_to, char **errstrp) { lexstate_t state; int res; int ret; char *errstr=NULL; /* tell server we want "name" to be the active script */ prot_printf(pout, "SETACTIVE \"%s\"\r\n",name); prot_flush(pout); /* now let's see what the server said */ res=yylex(&state, pin); ret = handle_response(res, version, pin, refer_to, &errstr); /* if command failed */ if(ret == -2 && *refer_to) { return -2; } else if (ret != 0) { *errstrp = strconcat("Setting script active: ", errstr, (char *)NULL); return -1; } return 0; }
int backend_ping(struct backend *s) { char buf[1024]; if (!s || !s->prot->ping_cmd.cmd) return 0; if (s->sock == -1) return -1; /* Disconnected Socket */ prot_printf(s->out, "%s\r\n", s->prot->ping_cmd.cmd); prot_flush(s->out); for (;;) { if (!prot_fgets(buf, sizeof(buf), s->in)) { /* connection closed? */ return -1; } else if (s->prot->ping_cmd.unsol && !strncmp(s->prot->ping_cmd.unsol, buf, strlen(s->prot->ping_cmd.unsol))) { /* unsolicited response */ continue; } else { /* success/fail response */ return strncmp(s->prot->ping_cmd.ok, buf, strlen(s->prot->ping_cmd.ok)); } } }
void backend_disconnect(struct backend *s) { char buf[1024]; if (!s || s->sock == -1) return; if (!prot_error(s->in)) { if (s->prot->logout_cmd.cmd) { prot_printf(s->out, "%s\r\n", s->prot->logout_cmd.cmd); prot_flush(s->out); for (;;) { if (!prot_fgets(buf, sizeof(buf), s->in)) { /* connection closed? */ break; } else if (s->prot->logout_cmd.unsol && !strncmp(s->prot->logout_cmd.unsol, buf, strlen(s->prot->logout_cmd.unsol))) { /* unsolicited response */ continue; } else { /* success/fail response -- don't care either way */ break; } } } } /* Flush the incoming buffer */ prot_NONBLOCK(s->in); prot_fill(s->in); #ifdef HAVE_SSL /* Free tlsconn */ if (s->tlsconn) { tls_reset_servertls(&s->tlsconn); s->tlsconn = NULL; } #endif /* HAVE_SSL */ /* close/free socket & prot layer */ cyrus_close_sock(s->sock); s->sock = -1; prot_free(s->in); prot_free(s->out); s->in = s->out = NULL; /* Free saslconn */ if(s->saslconn) { sasl_dispose(&(s->saslconn)); s->saslconn = NULL; } /* free last_result buffer */ buf_free(&s->last_result); forget_capabilities(s); }
EXPORTED void dlist_printbuf(const struct dlist *dl, int printkeys, struct buf *outbuf) { struct protstream *outstream; outstream = prot_writebuf(outbuf); dlist_print(dl, printkeys, outstream); prot_flush(outstream); prot_free(outstream); }
/* * Here we're just an intermediatory piping stdin to lmtp socket * and lmtp socket to stdout */ void pipe_through(struct backend *conn) { struct protgroup *protin = protgroup_new(2); protgroup_insert(protin, deliver_in); protgroup_insert(protin, conn->in); do { /* Flush any buffered output */ prot_flush(deliver_out); prot_flush(conn->out); } while (!proxy_check_input(protin, deliver_in, deliver_out, conn->in, conn->out, 0)); /* ok, we're done. */ protgroup_free(protin); return; }
int isieve_logout(isieve_t **obj) { prot_printf((*obj)->pout, "LOGOUT"); prot_flush((*obj)->pout); close((*obj)->sock); sieve_free_net(*obj); *obj = NULL; return STAT_OK; }
static int do_restart() { static int restartcnt = 0; if (sync_out->userdata) { /* IMAP flavor (w/ tag) */ prot_printf(sync_out, "R%d SYNC", restartcnt++); } prot_printf(sync_out, "RESTART\r\n"); prot_flush(sync_out); return sync_parse_response("RESTART", sync_in, NULL); }
int list_wcb(int version, struct protstream *pout, struct protstream *pin,isieve_listcb_t *cb ,void *rock, char **refer_to) { lexstate_t state; int end=0; int res; int ret = 0; prot_printf(pout, "LISTSCRIPTS\r\n"); prot_flush(pout); do { if ((res=yylex(&state, pin))==STRING) { char *str=state.str; if (yylex(&state, pin)==' ') { if (yylex(&state, pin)!=TOKEN_ACTIVE) printf("Expected ACTIVE\n"); if (yylex(&state, pin)!=EOL) printf("Expected EOL\n"); cb(str, 1, rock); } else { /* in old version we had that '*' means active script thing */ if (version == OLD_VERSION) { if (str[strlen(str)-1]=='*') { str[strlen(str)-1]='\0'; cb(str, 1, rock); } else { cb(str, 0, rock); } } else { /* NEW_VERSION */ /* assume it's a EOL */ cb(str, 0, rock); } } } else { ret = handle_response(res,version,pin,refer_to,NULL); end=1; } } while (end==0); return ret; }
EXPORTED int command_done_stdin(struct command *cmd) { int r = 0; if (cmd->stdin_prot) { r = prot_flush(cmd->stdin_prot); close(cmd->stdin_prot->fd); prot_free(cmd->stdin_prot); cmd->stdin_prot = NULL; } return r; }
void fatal(const char* s, int code) { static int recurse_code = 0; if(recurse_code) exit(code); else recurse_code = 0; prot_printf(deliver_out,"421 4.3.0 deliver: %s\r\n", s); prot_flush(deliver_out); cyrus_done(); exit(code); }
static void sync_reset(void) { proc_cleanup(); if (sync_in) { prot_NONBLOCK(sync_in); prot_fill(sync_in); prot_free(sync_in); } if (sync_out) { prot_flush(sync_out); prot_free(sync_out); } sync_in = sync_out = NULL; #ifdef HAVE_SSL if (tls_conn) { tls_reset_servertls(&tls_conn); tls_conn = NULL; } #endif cyrus_reset_stdio(); sync_clienthost = "[local]"; if (sync_logfd != -1) { close(sync_logfd); sync_logfd = -1; } if (sync_userid != NULL) { free(sync_userid); sync_userid = NULL; } if (sync_authstate) { auth_freestate(sync_authstate); sync_authstate = NULL; } if (sync_saslconn) { sasl_dispose(&sync_saslconn); sync_saslconn = NULL; } sync_starttls_done = 0; sync_compress_done = 0; saslprops_reset(&saslprops); }
EXPORTED int backend_starttls( struct backend *s, struct tls_cmd_t *tls_cmd, const char *c_cert_file, const char *c_key_file) { #ifndef HAVE_SSL return -1; #else char *auth_id = NULL; int *layerp = NULL; int r = 0; if (tls_cmd) { char buf[2048]; /* send starttls command */ prot_printf(s->out, "%s\r\n", tls_cmd->cmd); prot_flush(s->out); /* check response */ if (!prot_fgets(buf, sizeof(buf), s->in) || strncmp(buf, tls_cmd->ok, strlen(tls_cmd->ok))) return -1; } r = tls_init_clientengine(5, c_cert_file, c_key_file); if (r == -1) return -1; /* SASL and openssl have different ideas about whether ssf is signed */ layerp = (int *) &s->ext_ssf; r = tls_start_clienttls(s->in->fd, s->out->fd, layerp, &auth_id, &s->tlsconn, &s->tlssess); if (r == -1) return -1; if (s->saslconn) { r = sasl_setprop(s->saslconn, SASL_SSF_EXTERNAL, &s->ext_ssf); if (r == SASL_OK) r = sasl_setprop(s->saslconn, SASL_AUTH_EXTERNAL, auth_id); if (auth_id) free(auth_id); if (r != SASL_OK) return -1; } prot_settls(s->in, s->tlsconn); prot_settls(s->out, s->tlsconn); ask_capability(s, /*dobanner*/1, tls_cmd->auto_capa); return 0; #endif /* HAVE_SSL */ }
EXPORTED void fatal(const char *s, int code) { static int recurse_code = 0; if (recurse_code) { /* We were called recursively. Just give up */ exit(recurse_code); } recurse_code = code; prot_printf(sieved_out, "NO Fatal error: %s\r\n", s); prot_flush(sieved_out); shut_down(EC_TEMPFAIL); }
static int do_restart() { static int restartcnt = 0; if (sync_out->userdata) { /* IMAP flavor (w/ tag) */ struct buf *tag = (struct buf *) sync_out->userdata; buf_reset(tag); buf_printf(tag, "R%d", restartcnt++); prot_printf(sync_out, "%s SYNC", buf_cstring(tag)); } prot_printf(sync_out, "RESTART\r\n"); prot_flush(sync_out); return sync_parse_response("RESTART", sync_in, NULL); }
static int do_starttls(struct backend *s) { #ifndef HAVE_SSL return -1; #else const struct tls_cmd_t *tls_cmd = &s->prot->tls_cmd; char buf[2048]; int r; int *layerp; char *auth_id; sasl_ssf_t ssf; /* send starttls command */ prot_printf(s->out, "%s\r\n", tls_cmd->cmd); prot_flush(s->out); /* check response */ if (!prot_fgets(buf, sizeof(buf), s->in) || strncmp(buf, tls_cmd->ok, strlen(tls_cmd->ok))) return -1; r = tls_init_clientengine(5, "", ""); if (r == -1) return -1; /* SASL and openssl have different ideas about whether ssf is signed */ layerp = (int *) &ssf; r = tls_start_clienttls(s->in->fd, s->out->fd, layerp, &auth_id, &s->tlsconn, &s->tlssess); if (r == -1) return -1; r = sasl_setprop(s->saslconn, SASL_SSF_EXTERNAL, &ssf); if (r == SASL_OK) r = sasl_setprop(s->saslconn, SASL_AUTH_EXTERNAL, auth_id); if (auth_id) free(auth_id); if (r != SASL_OK) return -1; prot_settls(s->in, s->tlsconn); prot_settls(s->out, s->tlsconn); ask_capability(s, /*dobanner*/1, s->prot->tls_cmd.auto_capa); return 0; #endif /* HAVE_SSL */ }
/* * Get capabilities from the server, and parse them according to * details in the protocol_t, so that the CAPA() macro and perhaps * the backend_get_cap_params() function will notice them. Any * capabilities previously parsed are forgotten. * * The server might give us capabilities for free just because we * connected (or did a STARTTLS or logged in); in this case, call * with a non-zero value for @automatic. Otherwise, we send a * protocol-specific command to the server to tickle it into * disgorging some capabilities. * * Returns: 1 if any capabilities were found, 0 otherwise. */ static int ask_capability(struct backend *s, int dobanner, int automatic) { struct protstream *pout = s->out, *pin = s->in; const struct protocol_t *prot = s->prot; int matches = 0; char str[4096]; const char *resp; resp = (automatic == AUTO_CAPA_BANNER) ? prot->banner.resp : prot->capa_cmd.resp; if (!automatic) { /* no capability command */ if (!prot->capa_cmd.cmd) return -1; /* request capabilities of server */ prot_printf(pout, "%s", prot->capa_cmd.cmd); if (prot->capa_cmd.arg) prot_printf(pout, " %s", prot->capa_cmd.arg); prot_printf(pout, "\r\n"); prot_flush(pout); } forget_capabilities(s); do { if (prot_fgets(str, sizeof(str), pin) == NULL) break; matches |= parse_capability(s, str); if (!resp) { /* multiline response with no distinct end (IMAP banner) */ prot_NONBLOCK(pin); } if (dobanner) strncpy(s->banner, str, sizeof(s->banner)); /* look for the end of the capabilities */ } while (!resp || strncasecmp(str, resp, strlen(resp))); prot_BLOCK(pin); post_parse_capability(s); return matches; }
EXPORTED void fatal(const char* s, int code) { static int recurse_code = 0; if (recurse_code) { /* We were called recursively. Just give up */ proc_cleanup(); exit(recurse_code); } recurse_code = code; open_backups_list_close(&backupd_open_backups, 0); if (backupd_out) { prot_printf(backupd_out, "* Fatal error: %s\r\n", s); prot_flush(backupd_out); } syslog(LOG_ERR, "Fatal error: %s", s); shut_down(code); }
static int do_compress(struct backend *s, struct simple_cmd_t *compress_cmd) { #ifndef HAVE_ZLIB return -1; #else char buf[1024]; /* send compress command */ prot_printf(s->out, "%s\r\n", compress_cmd->cmd); prot_flush(s->out); /* check response */ if (!prot_fgets(buf, sizeof(buf), s->in) || strncmp(buf, compress_cmd->ok, strlen(compress_cmd->ok))) return -1; prot_setcompress(s->in); prot_setcompress(s->out); return 0; #endif /* HAVE_ZLIB */ }
/* Proxy SETANNOTATION commands to backend */ int annotate_store_proxy(const char *server, const char *mbox_pat, struct entryattlist *entryatts) { struct backend *be; struct entryattlist *e; struct attvaluelist *av; char mytag[128]; assert(server && mbox_pat && entryatts); be = proxy_findserver(server, &imap_protocol, proxy_userid, &backend_cached, &backend_current, &backend_inbox, imapd_in); if (!be) return IMAP_SERVER_UNAVAILABLE; /* Send command to remote */ proxy_gentag(mytag, sizeof(mytag)); prot_printf(be->out, "%s SETANNOTATION \"%s\" (", mytag, mbox_pat); for (e = entryatts; e; e = e->next) { prot_printf(be->out, "\"%s\" (", e->entry); for (av = e->attvalues; av; av = av->next) { prot_printf(be->out, "\"%s\" ", av->attrib); prot_printmap(be->out, av->value.s, av->value.len); prot_printf(be->out, "%s", av->next ? " " : ""); } prot_printf(be->out, ")"); if (e->next) prot_printf(be->out, " "); } prot_printf(be->out, ")\r\n"); prot_flush(be->out); /* Pipe the results. Note that backend-current may also pipe us other messages. */ pipe_until_tag(be, mytag, 0); return 0; }
static void test_printstring(void) { PROLOG; struct protstream *p; int len; struct buf b = BUF_INITIALIZER; int i; char str[2600]; p = prot_new(_fd, 1); CU_ASSERT_PTR_NOT_NULL_FATAL(p); /* NULL string */ BEGIN; prot_printstring(p, NULL); prot_flush(p); END(str, len); CU_ASSERT_EQUAL(len, 3); CU_ASSERT_STRING_EQUAL(str, "NIL"); /* Zero length string */ BEGIN; prot_printstring(p, ""); prot_flush(p); END(str, len); CU_ASSERT_EQUAL(len, 2); CU_ASSERT_STRING_EQUAL(str, "\"\""); /* Boring string */ BEGIN; prot_printstring(p, "Hello"); prot_flush(p); END(str, len); CU_ASSERT_EQUAL(len, 7); CU_ASSERT_STRING_EQUAL(str, "\"Hello\""); /* String with non-dangerous whitespace */ BEGIN; prot_printstring(p, "Hello World\tagain"); prot_flush(p); END(str, len); CU_ASSERT_EQUAL(len, 19); CU_ASSERT_STRING_EQUAL(str, "\"Hello World\tagain\""); /* String with dangerous whitespace */ BEGIN; prot_printstring(p, "Good\rBye\nEarth"); prot_flush(p); END(str, len); CU_ASSERT_EQUAL(len, 20); CU_ASSERT_STRING_EQUAL(str, "{14}\r\nGood\rBye\nEarth"); /* String with embedded dquote */ BEGIN; prot_printstring(p, "Quot\"able"); prot_flush(p); END(str, len); CU_ASSERT_EQUAL(len, 14); CU_ASSERT_STRING_EQUAL(str, "{9}\r\nQuot\"able"); /* String with embedded percent */ BEGIN; prot_printstring(p, "per%ent"); prot_flush(p); END(str, len); CU_ASSERT_EQUAL(len, 12); CU_ASSERT(!strcmp(str, "{7}\r\nper%ent")); /* String with embedded backslash */ BEGIN; prot_printstring(p, "slash\\dot"); prot_flush(p); END(str, len); CU_ASSERT_EQUAL(len, 14); CU_ASSERT_STRING_EQUAL(str, "{9}\r\nslash\\dot"); /* String with embedded 8-bit chars */ BEGIN; prot_printstring(p, "Hi I'm \330l\345f"); prot_flush(p); END(str, len); CU_ASSERT_EQUAL(len, 17); CU_ASSERT_STRING_EQUAL(str, "{11}\r\nHi I'm \330l\345f"); /* Boring but overly long string */ for (i = 0 ; i<500 ; i++) buf_appendcstr(&b, "blah "); buf_cstring(&b); BEGIN; prot_printstring(p, b.s); prot_flush(p); END(str, len); CU_ASSERT_EQUAL(len, b.len+8); CU_ASSERT_STRING_EQUAL(str+8, b.s); str[8] = '\0'; CU_ASSERT_STRING_EQUAL(str, "{2500}\r\n"); buf_free(&b); prot_free(p); EPILOG; }
/* NOTE: success_data will need to be free()d by the caller */ int saslserver(sasl_conn_t *conn, const char *mech, const char *init_resp, const char *resp_prefix, const char *continuation, const char *empty_chal, struct protstream *pin, struct protstream *pout, int *sasl_result, char **success_data) { char base64[BASE64_BUF_SIZE+1]; char *clientin = NULL; unsigned int clientinlen = 0; const char *serverout = NULL; unsigned int serveroutlen = 0; int r = SASL_OK; if (success_data) *success_data = NULL; /* initial response */ if (init_resp) { clientin = base64; if (!strcmp(init_resp, "=")) { /* zero-length initial response */ base64[0] = '\0'; } else { r = sasl_decode64(init_resp, strlen(init_resp), clientin, BASE64_BUF_SIZE, &clientinlen); } } /* start the exchange */ if (r == SASL_OK) r = sasl_server_start(conn, mech, clientin, clientinlen, &serverout, &serveroutlen); while (r == SASL_CONTINUE) { char *p; /* send the challenge to the client */ if (serveroutlen) { r = sasl_encode64(serverout, serveroutlen, base64, BASE64_BUF_SIZE, NULL); if (r != SASL_OK) break; serverout = base64; } else { serverout = empty_chal; } prot_printf(pout, "%s%s\r\n", continuation, serverout); prot_flush(pout); /* get response from the client */ if (!prot_fgets(base64, BASE64_BUF_SIZE, pin) || strncasecmp(base64, resp_prefix, strlen(resp_prefix))) { if (sasl_result) *sasl_result = SASL_FAIL; return IMAP_SASL_PROTERR; } /* trim CRLF */ p = base64 + strlen(base64) - 1; if (p >= base64 && *p == '\n') *p-- = '\0'; if (p >= base64 && *p == '\r') *p-- = '\0'; /* trim prefix */ p = base64 + strlen(resp_prefix); /* check if client cancelled */ if (p[0] == '*') { if(sasl_result) *sasl_result = SASL_BADPROT; return IMAP_SASL_CANCEL; } /* decode the response */ clientin = base64; r = sasl_decode64(p, strlen(p), clientin, BASE64_BUF_SIZE, &clientinlen); if (r != SASL_OK) break; /* do the next step */ r = sasl_server_step(conn, clientin, clientinlen, &serverout, &serveroutlen); } /* success data */ if (r == SASL_OK && serverout && success_data) { r = sasl_encode64(serverout, serveroutlen, base64, BASE64_BUF_SIZE, NULL); if (r == SASL_OK) *success_data = (char *) xstrdup(base64); } if (sasl_result) *sasl_result = r; return (r == SASL_OK ? 0 : IMAP_SASL_FAIL); }
int installafile(int version,struct protstream *pout, struct protstream *pin, char *filename, char *destname, char **refer_to, char **errstrp) { FILE *stream; struct stat filestats; /* returned by stat */ int size; /* size of the file */ int result; int cnt; int res; int ret; char *errstr=NULL; lexstate_t state; char *sievename; if(!destname) destname = filename; result=stat(filename,&filestats); if (result!=0) { *errstrp = xstrdup(strerror(errno)); return -1; } size=filestats.st_size; stream=fopen(filename, "r"); if (stream==NULL) { *errstrp = xstrdup( "put script: internal error: couldn't open temporary file"); return -1; } sievename=getsievename(destname); prot_printf(pout, "PUTSCRIPT \"%s\" ",sievename); prot_printf(pout, "{%d+}\r\n",size); cnt=0; while (cnt < size) { char buf[BLOCKSIZE]; int amount=BLOCKSIZE; int n; if (size-cnt < BLOCKSIZE) amount=size-cnt; n = fread(buf, 1, BLOCKSIZE, stream); if (!n) { *errstrp = xstrdup("put script: failed to finish reading"); fclose(stream); free(sievename); return -1; } prot_write(pout, buf, n); cnt+=amount; } prot_printf(pout,"\r\n"); prot_flush(pout); fclose(stream); free(sievename); /* now let's see what the server said */ res=yylex(&state,pin); ret = handle_response(res,version,pin,refer_to,&errstr); /* if command failed */ if(ret == -2 && *refer_to) { return -2; } else if (ret!=0) { *errstrp = strconcat("put script: ", errstr, (char *)NULL); return -1; } return 0; }