int handle_egress(struct __sk_buff *skb) { int ret = 0, nh_off = BPF_LL_OFF + ETH_HLEN; if (likely(skb->protocol == __constant_htons(ETH_P_IP))) ret = do_redirect(skb, nh_off, 1); return ret; }
static int execute(int argc, char *argv[], redirect_map_t *map) { int status, pid; cmd_t *cmd; for (cmd = builtin_cmds; cmd->cmd_name; cmd++) { if (!strcmp(cmd->cmd_name, argv[0])) break; } if (cmd->cmd_name) { ioenv_t io; build_ioenv(map, &io); status = builtin_exec(cmd, argc, argv, &io); destroy_ioenv(&io); cleanup_redirects(map); return 0; } if (!(pid = fork())) { if (do_redirect(map) < 0) exit(1); execve(argv[0], argv, my_envp); if (errno == ENOENT) { char buf[256]; snprintf(buf, 255, "/usr/bin/%s", argv[0]); execve(buf, argv, my_envp); fprintf(stderr, "sh: command not found: %s\n", argv[0]); } else fprintf(stderr, "sh: exec failed for %s: %s\n", argv[0], strerror(errno)); exit(1); } else { if (0 > pid) { fprintf(stderr, "sh: fork failed errno = %d\n", errno); } } cleanup_redirects(map); int ret = wait(&status); if (status == EFAULT) { fprintf(stderr, "sh: child process accessed invalid memory\n"); } return ret; }
static unsigned int fw_in(unsigned int hooknum, struct sk_buff **pskb, const struct net_device *in, const struct net_device *out, int (*okfn)(struct sk_buff *)) { int ret = FW_BLOCK; u_int16_t redirpt; /* Assume worse case: any hook could change packet */ (*pskb)->nfcache |= NFC_UNKNOWN | NFC_ALTERED; if ((*pskb)->ip_summed == CHECKSUM_HW) if (skb_checksum_help(*pskb, (out == NULL))) return NF_DROP; switch (hooknum) { case NF_IP_PRE_ROUTING: if (fwops->fw_acct_in) fwops->fw_acct_in(fwops, PF_INET, (struct net_device *)in, &redirpt, pskb); if ((*pskb)->nh.iph->frag_off & htons(IP_MF|IP_OFFSET)) { *pskb = ip_ct_gather_frags(*pskb); if (!*pskb) return NF_STOLEN; } ret = fwops->fw_input(fwops, PF_INET, (struct net_device *)in, &redirpt, pskb); break; case NF_IP_FORWARD: /* Connection will only be set if it was demasqueraded: if so, skip forward chain. */ if ((*pskb)->nfct) ret = FW_ACCEPT; else ret = fwops->fw_forward(fwops, PF_INET, (struct net_device *)out, &redirpt, pskb); break; case NF_IP_POST_ROUTING: ret = fwops->fw_output(fwops, PF_INET, (struct net_device *)out, &redirpt, pskb); if (ret == FW_ACCEPT || ret == FW_SKIP) { if (fwops->fw_acct_out) fwops->fw_acct_out(fwops, PF_INET, (struct net_device *)out, &redirpt, pskb); /* ip_conntrack_confirm return NF_DROP or NF_ACCEPT */ if (ip_conntrack_confirm(*pskb) == NF_DROP) ret = FW_BLOCK; } break; } switch (ret) { case FW_REJECT: { /* Alexey says: * * Generally, routing is THE FIRST thing to make, when * packet enters IP stack. Before packet is routed you * cannot call any service routines from IP stack. */ struct iphdr *iph = (*pskb)->nh.iph; if ((*pskb)->dst != NULL || ip_route_input(*pskb, iph->daddr, iph->saddr, iph->tos, (struct net_device *)in) == 0) icmp_send(*pskb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); return NF_DROP; } case FW_ACCEPT: case FW_SKIP: if (hooknum == NF_IP_PRE_ROUTING) { check_for_demasq(pskb); check_for_redirect(*pskb); } else if (hooknum == NF_IP_POST_ROUTING) { check_for_unredirect(*pskb); /* Handle ICMP errors from client here */ if ((*pskb)->nh.iph->protocol == IPPROTO_ICMP && (*pskb)->nfct) check_for_masq_error(pskb); } return NF_ACCEPT; case FW_MASQUERADE: if (hooknum == NF_IP_FORWARD) { #ifdef CONFIG_IP_VS /* check if it is for ip_vs */ if (check_for_ip_vs_out(pskb, okfn) == NF_STOLEN) return NF_STOLEN; #endif return do_masquerade(pskb, out); } else return NF_ACCEPT; case FW_REDIRECT: if (hooknum == NF_IP_PRE_ROUTING) return do_redirect(*pskb, in, redirpt); else return NF_ACCEPT; default: /* FW_BLOCK */ return NF_DROP; } }
/* * Function Name: validate_session_policy * This is the NSAPI directive funtion which gets called for each request * It does session validation and policy check for each request. * Input: As defined by a SAF * Output: As defined by a SAF */ NSAPI_PUBLIC int validate_session_policy(pblock *param, Session *sn, Request *rq) { const char *thisfunc = "validate_session_policy()"; char *dpro_cookie = NULL; am_status_t status = AM_SUCCESS; int requestResult = REQ_ABORTED; int notifResult = REQ_ABORTED; const char *ruser = NULL; am_map_t env_parameter_map = NULL; am_policy_result_t result = AM_POLICY_RESULT_INITIALIZER; void *args[] = { (void *)rq }; char *request_url = NULL; char *orig_req = NULL ; char *response = NULL; char *clf_req = NULL; char *server_protocol = NULL; void *agent_config = NULL; char *logout_url = NULL; char *uri_hdr = NULL; char *pathInfo_hdr = NULL; char *method_hdr = NULL; char *method = NULL; char *virtHost_hdr = NULL; char *query_hdr = NULL; char *query = NULL; char *protocol = "HTTP"; const char *clientIP_hdr_name = NULL; char *clientIP_hdr = NULL; char *clientIP = NULL; const char *clientHostname_hdr_name = NULL; char *clientHostname_hdr = NULL; char *clientHostname = NULL; am_status_t cdStatus = AM_FAILURE; // check if agent is initialized. // if not initialized, then call agent init function // This needs to be synchronized as only one time agent // initialization needs to be done. if(agentInitialized != B_TRUE){ //Start critical section crit_enter(initLock); if(agentInitialized != B_TRUE){ am_web_log_debug("%s: Will call init.", thisfunc); init_at_request(); if(agentInitialized != B_TRUE){ am_web_log_error("%s: Agent is still not intialized", thisfunc); //deny the access requestResult = do_deny(sn, rq, status); status = AM_FAILURE; } else { am_web_log_debug("%s: Agent intialized"); } } //end critical section crit_exit(initLock); } if (status == AM_SUCCESS) { // Get the agent configuration agent_config = am_web_get_agent_configuration(); // Dump the entire set of request headers if (am_web_is_max_debug_on()) { char *header_str = pblock_pblock2str(rq->reqpb, NULL); am_web_log_max_debug("%s: Headers: %s", thisfunc, header_str); system_free(header_str); } } // Get header values if (status == AM_SUCCESS) { status = get_header_value(rq->reqpb, REQUEST_URI, B_TRUE, &uri_hdr, B_FALSE, NULL); } if (status == AM_SUCCESS) { status = get_header_value(rq->vars, PATH_INFO, B_FALSE, &pathInfo_hdr, B_FALSE, NULL); } if (status == AM_SUCCESS) { status = get_header_value(rq->reqpb, REQUEST_METHOD, B_TRUE, &method_hdr, B_TRUE, &method); } if (status == AM_SUCCESS) { status = get_header_value(rq->headers, "ampxy_host", B_TRUE, &virtHost_hdr, B_FALSE, NULL); } if (status == AM_SUCCESS) { status = get_header_value(rq->reqpb, REQUEST_QUERY, B_FALSE, &query_hdr, B_TRUE, &query); } if (security_active) { protocol = "HTTPS"; } // Get the request URL if (status == AM_SUCCESS) { if (am_web_is_proxy_override_host_port_set(agent_config) == AM_FALSE) { status = am_web_get_request_url(virtHost_hdr, protocol, NULL, 0, uri_hdr, query, &request_url, agent_config); if(status == AM_SUCCESS) { am_web_log_debug("%s: Request_url: %s", thisfunc, request_url); } else { am_web_log_error("%s: Could not get the request URL. " "Failed with error: %s.", thisfunc, am_status_to_string(status)); } } } if (status == AM_SUCCESS) { if (am_web_is_proxy_override_host_port_set(agent_config) == AM_TRUE) { const char *agent_host = am_web_get_agent_server_host(agent_config); int agent_port = am_web_get_agent_server_port(agent_config); if (agent_host != NULL) { char *temp = NULL; temp = replace_host_port(request_url, agent_host, agent_port, agent_config); if (temp != NULL) { free(request_url); request_url = temp; } } am_web_log_debug("%s: Request_url after overriding " "host and port: %s", thisfunc, request_url); } } if (status == AM_SUCCESS) { // Check for magic notification URL if (B_TRUE == am_web_is_notification(request_url, agent_config)) { am_web_free_memory(request_url); am_web_delete_agent_configuration(agent_config); if(query != NULL) { free(query); query = NULL; } if(method != NULL) { free(method); method = NULL; } return REQ_PROCEED; } } // Check if the SSO token is in the cookie header if (status == AM_SUCCESS) { requestResult = getISCookie(pblock_findval(COOKIE_HDR, rq->headers), &dpro_cookie, agent_config); if (requestResult == REQ_ABORTED) { status = AM_FAILURE; } else if (dpro_cookie != NULL) { am_web_log_debug("%s: SSO token found in cookie header.", thisfunc); } } // Create the environment map if( status == AM_SUCCESS) { status = am_map_create(&env_parameter_map); if( status != AM_SUCCESS) { am_web_log_error("%s: Unable to create map, status = %s (%d)", thisfunc, am_status_to_string(status), status); } } // If there is a proxy in front of the agent, the user can set in the // properties file the name of the headers that the proxy uses to set // the real client IP and host name. In that case the agent needs // to use the value of these headers to process the request // // Get the client IP address header set by the proxy, if there is one if (status == AM_SUCCESS) { clientIP_hdr_name = am_web_get_client_ip_header_name(agent_config); if (clientIP_hdr_name != NULL) { status = get_header_value(rq->headers, clientIP_hdr_name, B_FALSE, &clientIP_hdr, B_FALSE, NULL); } } // Get the client host name header set by the proxy, if there is one if (status == AM_SUCCESS) { clientHostname_hdr_name = am_web_get_client_hostname_header_name(agent_config); if (clientHostname_hdr_name != NULL) { status = get_header_value(rq->headers, clientHostname_hdr_name, B_FALSE, &clientHostname_hdr, B_FALSE, NULL); } } // If the client IP and host name headers contain more than one // value, take the first value. if (status == AM_SUCCESS) { if ((clientIP_hdr != NULL) || (clientHostname_hdr != NULL)) { status = am_web_get_client_ip_host(clientIP_hdr, clientHostname_hdr, &clientIP, &clientHostname); } } // Set the IP address and host name in the environment map if ((status == AM_SUCCESS) && (clientIP != NULL)) { status = am_web_set_host_ip_in_env_map(clientIP, clientHostname, env_parameter_map, agent_config); } // If the client IP was not obtained previously, // get it from the REMOTE_ADDR header. if ((status == AM_SUCCESS) && (clientIP == NULL)) { status = get_header_value(sn->client, REQUEST_IP_ADDR, B_FALSE, &clientIP_hdr, B_TRUE, &clientIP); } // In CDSSO mode, check if the sso token is in the post data if( status == AM_SUCCESS) { if((am_web_is_cdsso_enabled(agent_config) == B_TRUE) && (strcmp(method, REQUEST_METHOD_POST) == 0)) { if((dpro_cookie == NULL) && (am_web_is_url_enforced(request_url, pathInfo_hdr, clientIP, agent_config) == B_TRUE)) { // Set original method to GET orig_req = strdup(REQUEST_METHOD_GET); if (orig_req != NULL) { am_web_log_debug("%s: Request method set to GET.", thisfunc); } else { am_web_log_error("%s: Not enough memory to ", "allocate orig_req.", thisfunc); status = AM_NO_MEMORY; } // Check if dpro_cookie is in post data if( status == AM_SUCCESS) { response = get_post_assertion_data(sn, rq, request_url); status = am_web_check_cookie_in_post(args, &dpro_cookie, &request_url, &orig_req, method, response, B_FALSE, set_cookie, set_method, agent_config); if( status == AM_SUCCESS) { am_web_log_debug("%s: SSO token found in " "assertion.",thisfunc); } else { am_web_log_debug("%s: SSO token not found in " "assertion. Redirecting to login page.", thisfunc); status = AM_INVALID_SESSION; } } // Set back the original clf-request attribute if (status == AM_SUCCESS) { int clf_reqSize = 0; if ((query != NULL) && (strlen(query) > 0)) { clf_reqSize = strlen(orig_req) + strlen(uri_hdr) + strlen (query) + strlen(protocol) + 4; } else { clf_reqSize = strlen(orig_req) + strlen(uri_hdr) + strlen(protocol) + 3; } clf_req = malloc(clf_reqSize); if (clf_req == NULL) { am_web_log_error("%s: Unable to allocate %i " "bytes for clf_req", thisfunc, clf_reqSize); status = AM_NO_MEMORY; } else { memset (clf_req,'\0',clf_reqSize); strcpy(clf_req, orig_req); strcat(clf_req, " "); strcat(clf_req, uri_hdr); if ((query != NULL) && (strlen(query) > 0)) { strcat(clf_req, "?"); strcat(clf_req, query); } strcat(clf_req, " "); strcat(clf_req, protocol); am_web_log_debug("%s: clf-request set to %s", thisfunc, clf_req); } pblock_nvinsert(REQUEST_CLF, clf_req, rq->reqpb); } } } } // Check if access is allowed. if( status == AM_SUCCESS) { if (dpro_cookie != NULL) { am_web_log_debug("%s: SSO token = %s", thisfunc, dpro_cookie); } else { am_web_log_debug("%s: SSO token not found.", thisfunc); } status = am_web_is_access_allowed(dpro_cookie, request_url, pathInfo_hdr, method, clientIP, env_parameter_map, &result, agent_config); am_map_destroy(env_parameter_map); } switch(status) { case AM_SUCCESS: // Set remote user and authentication type ruser = result.remote_user; if (ruser != NULL) { pb_param *pbuser = pblock_remove(AUTH_USER_VAR, rq->vars); pb_param *pbauth = pblock_remove(AUTH_TYPE_VAR, rq->vars); if (pbuser != NULL) { param_free(pbuser); } pblock_nvinsert(AUTH_USER_VAR, ruser, rq->vars); if (pbauth != NULL) { param_free(pbauth); } pblock_nvinsert(AUTH_TYPE_VAR, AM_WEB_AUTH_TYPE_VALUE, rq->vars); am_web_log_debug("%s: access allowed to %s", thisfunc, ruser); } else { am_web_log_debug("%s: Remote user not set, " "allowing access to the url as it is in not " "enforced list", thisfunc); } if (am_web_is_logout_url(request_url, agent_config) == B_TRUE) { (void)am_web_logout_cookies_reset(reset_cookie, args, agent_config); } // set LDAP user attributes to http header status = am_web_result_attr_map_set(&result, set_header, set_cookie_in_response, set_header_attr_as_cookie, get_cookie_sync, args, agent_config); if (status != AM_SUCCESS) { am_web_log_error("%s: am_web_result_attr_map_set failed, " "status = %s (%d)", thisfunc, am_status_to_string(status), status); requestResult = REQ_ABORTED; } else { requestResult = REQ_PROCEED; } break; case AM_ACCESS_DENIED: am_web_log_debug("%s: Access denied to %s", thisfunc, result.remote_user ? result.remote_user : "******"); requestResult = do_redirect(sn, rq, status, &result, request_url, method, agent_config); break; case AM_INVALID_SESSION: if (am_web_is_cdsso_enabled(agent_config) == B_TRUE) { cdStatus = am_web_do_cookie_domain_set(set_cookie, args, EMPTY_STRING, agent_config); if(cdStatus != AM_SUCCESS) { am_web_log_error("%s: CDSSO reset cookie failed", thisfunc); } } am_web_do_cookies_reset(reset_cookie, args, agent_config); requestResult = do_redirect(sn, rq, status, &result, request_url, method, agent_config); break; case AM_INVALID_FQDN_ACCESS: // Redirect to self with correct FQDN - no post preservation requestResult = do_redirect(sn, rq, status, &result, request_url, method, agent_config); break; case AM_REDIRECT_LOGOUT: status = am_web_get_logout_url(&logout_url, agent_config); if(status == AM_SUCCESS) { do_url_redirect(sn,rq,logout_url); } else { requestResult = REQ_ABORTED; am_web_log_debug("validate_session_policy(): " "am_web_get_logout_url failed. "); } break; case AM_INVALID_ARGUMENT: case AM_NO_MEMORY: default: am_web_log_error("validate_session_policy() Status: %s (%d)", am_status_to_string(status), status); requestResult = REQ_ABORTED; break; } // Cleaning am_web_clear_attributes_map(&result); am_policy_result_destroy(&result); am_web_free_memory(dpro_cookie); am_web_free_memory(request_url); am_web_free_memory(logout_url); am_web_delete_agent_configuration(agent_config); if (orig_req != NULL) { free(orig_req); orig_req = NULL; } if (response != NULL) { free(response); response = NULL; } if (clf_req != NULL) { free(clf_req); clf_req = NULL; } if(query != NULL) { free(query); query = NULL; } if(method != NULL) { free(method); method = NULL; } if(clientIP != NULL) { am_web_free_memory(clientIP); } if(clientHostname != NULL) { am_web_free_memory(clientHostname); } am_web_log_max_debug("%s: Completed handling request with status: %s.", thisfunc, am_status_to_string(status)); return requestResult; }
/** * determines to grant access */ int dsame_check_access(request_rec *r) { char *dpro_cookie = get_cookie(r, am_web_get_cookie_name()); char *url = get_request_url(r); char *content; am_status_t status = AM_FAILURE; int ret = OK; const char *ruser = NULL; int bytesRead; am_map_t env_parameter_map = NULL; am_policy_result_t result = AM_POLICY_RESULT_INITIALIZER; void *args[1] = { (void *)r }; am_web_log_debug("Apache Agent: %s request for URL %s", r->method, url); if (B_TRUE==am_web_is_notification(url)) { bytesRead = content_read(r, &content); am_web_log_max_debug("Apache Agent: Content is %s", content); am_web_handle_notification(content, bytesRead); ap_rputs("OK",r); return OK; } if (dpro_cookie != NULL){ am_web_log_debug("Apache Agent: cookie value is: %s", dpro_cookie); } else { am_web_log_debug("Apache Agent: cookie is null"); } status = am_map_create(&env_parameter_map); if( status != AM_SUCCESS) { am_web_log_error("Apache Agent: unable to create map, " "status = %s (%d)", am_status_to_string(status), status); } else { am_web_log_debug("Apache Agent: am_map_create returned status=%s", am_status_to_string(status)); } if(status == AM_SUCCESS) { status = am_web_is_access_allowed(dpro_cookie, url, r->method, (char *)r->connection->remote_ip, env_parameter_map, &result); am_map_destroy(env_parameter_map); } am_web_log_debug("Apache Agent: am_web_is_access_allowed returned status=%s", am_status_to_string(status)); switch (status) { case AM_SUCCESS: ruser = result.remote_user; if (ruser != NULL) { r->connection->user = ap_pstrdup(r->pool, ruser); r->connection->ap_auth_type = ap_pstrdup(r->pool, DSAME); am_web_log_debug("URL Access Agent: access allowed to %s", ruser); } else { am_web_log_error("URL Access Agent: access allowed to unknown " "user"); } /* set LDAP user attributes to http header */ status = am_web_do_result_attr_map_set(&result, set_header, args); if (status != AM_SUCCESS) { am_web_log_error("URL Access Agent: am_web_do_result_attr_map_set " "failed, status = %s (%d)", am_status_to_string(status), status); } ret = OK; break; case AM_ACCESS_DENIED: am_web_log_always("URL Access Agent: access denied to %s", result.remote_user ? result.remote_user : "******"); ret = do_redirect(r, status, result.advice_map, url); break; case AM_INVALID_SESSION: /* XXX - Add POST Cache code here. */ ret = do_redirect(r, status, result.advice_map, url); break; case AM_INVALID_FQDN_ACCESS: // Redirect to self with correct FQDN - no post preservation ret = do_redirect(r, status, result.advice_map, url); break; case AM_INVALID_ARGUMENT: case AM_NO_MEMORY: default: am_web_log_error("URL Access Agent: status: %s (%d)", am_status_to_string(status), status); ret = SERVER_ERROR; break; } am_policy_result_destroy(&result); return ret; }
/* The entrypoint for bytecode evaluation */ int sieve_eval_bc(sieve_execute_t *exe, int is_incl, sieve_interp_t *i, void *sc, void *m, strarray_t *imapflags, action_list_t *actions, notify_list_t *notify_list, const char **errmsg) { const char *data; int res=0; int op; int version; sieve_bytecode_t *bc_cur = exe->bc_cur; bytecode_input_t *bc = (bytecode_input_t *) bc_cur->data; int ip = 0, ip_max = (bc_cur->len/sizeof(bytecode_input_t)); if (bc_cur->is_executing) { *errmsg = "Recursive Include"; return SIEVE_RUN_ERROR; } bc_cur->is_executing = 1; /* Check that we * a) have bytecode * b) it is atleast long enough for the magic number, the version * and one opcode */ if(!bc) return SIEVE_FAIL; if(bc_cur->len < (BYTECODE_MAGIC_LEN + 2*sizeof(bytecode_input_t))) return SIEVE_FAIL; if(memcmp(bc, BYTECODE_MAGIC, BYTECODE_MAGIC_LEN)) { *errmsg = "Not a bytecode file"; return SIEVE_FAIL; } ip = BYTECODE_MAGIC_LEN / sizeof(bytecode_input_t); version= ntohl(bc[ip].op); /* this is because there was a time where integers were not network byte order. all the scripts written then would have version 0x01 written in host byte order.*/ if(version == (int)ntohl(1)) { if(errmsg) { *errmsg = "Incorrect Bytecode Version, please recompile (use sievec)"; } return SIEVE_FAIL; } if((version < BYTECODE_MIN_VERSION) || (version > BYTECODE_VERSION)) { if(errmsg) { *errmsg = "Incorrect Bytecode Version, please recompile (use sievec)"; } return SIEVE_FAIL; } #if VERBOSE printf("version number %d\n",version); #endif for(ip++; ip<ip_max; ) { int copy = 0; op=ntohl(bc[ip].op); switch(op) { case B_STOP:/*0*/ res=1; break; case B_KEEP:/*1*/ res = do_keep(actions, imapflags); if (res == SIEVE_RUN_ERROR) *errmsg = "Keep can not be used with Reject"; ip++; break; case B_DISCARD:/*2*/ res=do_discard(actions); ip++; break; case B_REJECT:/*3*/ ip = unwrap_string(bc, ip+1, &data, NULL); res = do_reject(actions, data); if (res == SIEVE_RUN_ERROR) *errmsg = "Reject can not be used with any other action"; break; case B_FILEINTO:/*19*/ copy = ntohl(bc[ip+1].value); ip+=1; /* fall through */ case B_FILEINTO_ORIG:/*4*/ { ip = unwrap_string(bc, ip+1, &data, NULL); res = do_fileinto(actions, data, !copy, imapflags); if (res == SIEVE_RUN_ERROR) *errmsg = "Fileinto can not be used with Reject"; break; } case B_REDIRECT:/*20*/ copy = ntohl(bc[ip+1].value); ip+=1; /* fall through */ case B_REDIRECT_ORIG:/*5*/ { ip = unwrap_string(bc, ip+1, &data, NULL); res = do_redirect(actions, data, !copy); if (res == SIEVE_RUN_ERROR) *errmsg = "Redirect can not be used with Reject"; break; } case B_IF:/*6*/ { int testend=ntohl(bc[ip+1].value); int result; ip+=2; result=eval_bc_test(i, m, bc, &ip); if (result<0) { *errmsg = "Invalid test"; return SIEVE_FAIL; } else if (result) { /*skip over jump instruction*/ testend+=2; } ip=testend; break; } case B_MARK:/*8*/ res = do_mark(actions); ip++; break; case B_UNMARK:/*9*/ res = do_unmark(actions); ip++; break; case B_ADDFLAG:/*10*/ { int x; int list_len=ntohl(bc[ip+1].len); ip+=3; /* skip opcode, list_len, and list data len */ for (x=0; x<list_len; x++) { ip = unwrap_string(bc, ip, &data, NULL); res = do_addflag(actions, data); if (res == SIEVE_RUN_ERROR) *errmsg = "addflag can not be used with Reject"; } break; } case B_SETFLAG: { int x; int list_len=ntohl(bc[ip+1].len); ip+=3; /* skip opcode, list_len, and list data len */ ip = unwrap_string(bc, ip, &data, NULL); res = do_setflag(actions, data); if (res == SIEVE_RUN_ERROR) { *errmsg = "setflag can not be used with Reject"; } else { for (x=1; x<list_len; x++) { ip = unwrap_string(bc, ip, &data, NULL); res = do_addflag(actions, data); if (res == SIEVE_RUN_ERROR) *errmsg = "setflag can not be used with Reject"; } } break; } case B_REMOVEFLAG: { int x; int list_len=ntohl(bc[ip+1].len); ip+=3; /* skip opcode, list_len, and list data len */ for (x=0; x<list_len; x++) { ip = unwrap_string(bc, ip, &data, NULL); res = do_removeflag(actions, data); if (res == SIEVE_RUN_ERROR) *errmsg = "removeflag can not be used with Reject"; } break; } case B_NOTIFY: { const char * id; const char * method; const char **options = NULL; const char *priority = NULL; const char * message; int pri; ip++; /* method */ ip = unwrap_string(bc, ip, &method, NULL); /* id */ ip = unwrap_string(bc, ip, &id, NULL); /*options*/ options=bc_makeArray(bc, &ip); /* priority */ pri=ntohl(bc[ip].value); ip++; switch (pri) { case B_LOW: priority="low"; break; case B_NORMAL: priority="normal"; break; case B_HIGH: priority="high"; break; case B_ANY: priority="any"; break; default: res=SIEVE_RUN_ERROR; } /* message */ ip = unwrap_string(bc, ip, &message, NULL); res = do_notify(notify_list, id, method, options, priority, message); break; } case B_DENOTIFY: { /* * i really have no idea what the count matchtype should do here. * the sanest thing would be to use 1. * however that would require passing on the match type to do_notify. * -jsmith2 */ comparator_t *comp = NULL; const char *pattern; regex_t *reg; const char *priority = NULL; void *comprock = NULL; int comparator; int pri; ip++; pri=ntohl(bc[ip].value); ip++; switch (pri) { case B_LOW: priority="low"; break; case B_NORMAL: priority="normal"; break; case B_HIGH: priority="high"; break; case B_ANY: priority="any"; break; default: res=SIEVE_RUN_ERROR; } if(res == SIEVE_RUN_ERROR) break; comparator =ntohl( bc[ip].value); ip++; if (comparator == B_ANY) { ip++;/* skip placeholder this has no comparator function */ comp=NULL; } else { int x= ntohl(bc[ip].value); ip++; comp=lookup_comp(B_ASCIICASEMAP,comparator, x, &comprock); } ip = unwrap_string(bc, ip, &pattern, NULL); if (comparator == B_REGEX) { char errmsg[1024]; /* Basically unused */ reg=bc_compile_regex(pattern, REG_EXTENDED | REG_NOSUB | REG_ICASE, errmsg, sizeof(errmsg)); if (!reg) { res = SIEVE_RUN_ERROR; } else { res = do_denotify(notify_list, comp, reg, comprock, priority); free(reg); } } else { res = do_denotify(notify_list, comp, pattern, comprock, priority); } break; } case B_VACATION_ORIG: case B_VACATION: { int respond; char *fromaddr = NULL; /* relative to message we send */ char *toaddr = NULL; /* relative to message we send */ const char *handle = NULL; const char *message = NULL; int seconds, mime; char buf[128]; char subject[1024]; int x; ip++; x = ntohl(bc[ip].len); respond = shouldRespond(m, i, x, bc, ip+2, &fromaddr, &toaddr); ip = ntohl(bc[ip+1].value) / 4; if (respond==SIEVE_OK) { ip = unwrap_string(bc, ip, &data, NULL); if (!data) { /* we have to generate a subject */ const char **s; strlcpy(buf, "subject", sizeof(buf)); if (i->getheader(m, buf, &s) != SIEVE_OK || s[0] == NULL) { strlcpy(subject, "Automated reply", sizeof(subject)); } else { /* s[0] contains the original subject */ const char *origsubj = s[0]; snprintf(subject, sizeof(subject), "Auto: %s", origsubj); } } else { /* user specified subject */ strlcpy(subject, data, sizeof(subject)); } ip = unwrap_string(bc, ip, &message, NULL); seconds = ntohl(bc[ip].value); if (op == B_VACATION_ORIG) { seconds *= DAY2SEC; } mime = ntohl(bc[ip+1].value); ip+=2; if (version >= 0x05) { ip = unwrap_string(bc, ip, &data, NULL); if (data) { /* user specified from address */ free(fromaddr); fromaddr = xstrdup(data); } ip = unwrap_string(bc, ip, &data, NULL); if (data) { /* user specified handle */ handle = data; } } res = do_vacation(actions, toaddr, fromaddr, xstrdup(subject), message, seconds, mime, handle); if (res == SIEVE_RUN_ERROR) *errmsg = "Vacation can not be used with Reject or Vacation"; } else if (respond == SIEVE_DONE) { /* skip subject and message */ ip = unwrap_string(bc, ip, &data, NULL); ip = unwrap_string(bc, ip, &data, NULL); ip+=2;/*skip days and mime flag*/ if (version >= 0x05) { /* skip from and handle */ ip = unwrap_string(bc, ip, &data, NULL); ip = unwrap_string(bc, ip, &data, NULL); } } else { res = SIEVE_RUN_ERROR; /* something is bad */ } break; } case B_NULL:/*15*/ ip++; break; case B_JUMP:/*16*/ ip= ntohl(bc[ip+1].jump); break; case B_INCLUDE:/*17*/ { int isglobal = (ntohl(bc[ip+1].value) & 63) == B_GLOBAL; int once = ntohl(bc[ip+1].value) & 64 ? 1 : 0; int isoptional = ntohl(bc[ip+1].value) & 128 ? 1 : 0; char fpath[4096]; ip = unwrap_string(bc, ip+2, &data, NULL); res = i->getinclude(sc, data, isglobal, fpath, sizeof(fpath)); if (res != SIEVE_OK) { if (isoptional == 0) *errmsg = "Include can not find script"; else res = SIEVE_OK; break; } res = sieve_script_load(fpath, &exe); if (res == SIEVE_SCRIPT_RELOADED) { if (once == 1) { res = SIEVE_OK; break; } } else if (res != SIEVE_OK) { /* SIEVE_FAIL */ if (isoptional == 0) *errmsg = "Include can not load script"; else res = SIEVE_OK; break; } res = sieve_eval_bc(exe, 1, i, sc, m, imapflags, actions, notify_list, errmsg); break; } case B_RETURN:/*18*/ if (is_incl) goto done; else res=1; break; default: if(errmsg) *errmsg = "Invalid sieve bytecode"; return SIEVE_FAIL; } if (res) /* we've either encountered an error or a stop */ break; } done: bc_cur->is_executing = 0; return res; }