/* * Receiving side of the chat window. * This does JavaScript writes to * other divs whenever it refreshes and finds new data. */ void chat_recv(void) { char buf[SIZ]; char cl_user[SIZ]; serv_printf("RCHT poll|%d", WC->last_chat_seq); serv_getln(buf, sizeof buf); if (buf[0] == '1') { WC->last_chat_seq = extract_int(&buf[4], 0); extract_token(cl_user, &buf[4], 2, '|', sizeof cl_user); /* who is speaking ... */ if (strcasecmp(cl_user, WC->last_chat_user)) { wc_printf("<br>\n"); if (!strcasecmp(cl_user, ChrPtr(WC->wc_fullname))) { wc_printf("<span class=\"chat_myname_class\">"); } else { wc_printf("<span class=\"chat_notmyname_class\">"); } escputs(cl_user); strcpy(WC->last_chat_user, cl_user); wc_printf(": </span>"); } else { wc_printf(" "); } /* what did they say ... */ wc_printf("<span class=\"chat_text_class\">"); while (serv_getln(buf, sizeof buf), strcmp(buf, "000")) { escputs(buf); } wc_printf("<br></span>\n"); } }
/* * Determine whether a given Internet address belongs to the current user */ int CtdlIsMe(char *addr, int addr_buf_len) { recptypes *recp; int i; recp = validate_recipients(addr, NULL, 0); if (recp == NULL) return(0); if (recp->num_local == 0) { free_recipients(recp); return(0); } for (i=0; i<recp->num_local; ++i) { extract_token(addr, recp->recp_local, i, '|', addr_buf_len); if (!strcasecmp(addr, CC->user.fullname)) { free_recipients(recp); return(1); } } free_recipients(recp); return(0); }
void load_plugin_filters(int link_type) { struct plugins_list_entry *list = plugins_list; while (list) { if ((*list->type.func)) { /* compiling aggregation filter if needed */ if (list->cfg.a_filter) { pcap_t *dev_desc; bpf_u_int32 localnet, netmask = 0; /* pcap library stuff */ char errbuf[PCAP_ERRBUF_SIZE], *count_token; int idx = 0; dev_desc = pcap_open_dead(link_type, 128); /* 128 bytes should be long enough */ if (config.dev) pcap_lookupnet(config.dev, &localnet, &netmask, errbuf); list->cfg.bpfp_a_table[idx] = malloc(sizeof(struct bpf_program)); while ( (count_token = extract_token(&list->cfg.a_filter, ',')) && idx < AGG_FILTER_ENTRIES ) { if (pcap_compile(dev_desc, list->cfg.bpfp_a_table[idx], count_token, 0, netmask) < 0) { Log(LOG_WARNING, "WARN: %s\nWARN ( %s/%s ): aggregation filter disabled.\n", pcap_geterr(dev_desc), list->cfg.name, list->cfg.type); } else { idx++; list->cfg.bpfp_a_table[idx] = malloc(sizeof(struct bpf_program)); } } list->cfg.bpfp_a_num = idx; } } list = list->next; } }
static int parse_media(char *start, char *end, struct sdp_media *output) { char *ep; str s, *sp; EXTRACT_TOKEN(media_type); EXTRACT_TOKEN(port); EXTRACT_TOKEN(transport); str_init_len(&output->formats, start, end - start); output->port_num = strtol(output->port.s, &ep, 10); if (ep == output->port.s) return -1; if (output->port_num < 0 || output->port_num > 0xffff) return -1; if (*ep == '/') { output->port_count = atoi(ep + 1); if (output->port_count <= 0) return -1; if (output->port_count > 10) /* unsupported */ return -1; } else output->port_count = 1; /* to split the "formats" list into tokens, we abuse some vars */ start = output->formats.s; end = start + output->formats.len; while (!extract_token(&start, end, &s)) { sp = g_slice_alloc(sizeof(*sp)); *sp = s; g_queue_push_tail(&output->format_list, sp); } return 0; }
/* Special decoder for syscheck * Not using the default decoding lib for simplicity * and to be less resource intensive */ int DecodeSyscheck(Eventinfo *lf) { const char *c_sum; char *f_name; #ifdef SQLITE_ENABLED char *p; char stmt[OS_MAXSTR + 1]; sqlite3_stmt *res; int error = 0; int rec_count = 0; const char *tail; #endif // SQLITE_ENABLED /* Every syscheck message must be in the following format: * checksum filename */ f_name = strchr(lf->log, ' '); if (f_name == NULL) { /* If we don't have a valid syscheck message, it may be * a database completed message */ if (strcmp(lf->log, HC_SK_DB_COMPLETED) == 0) { DB_SetCompleted(lf); return (0); } merror(SK_INV_MSG, ARGV0); return (0); } /* Zero to get the check sum */ *f_name = '\0'; f_name++; /* Get diff */ lf->data = strchr(f_name, '\n'); if (lf->data) { *lf->data = '\0'; lf->data++; } else { lf->data = NULL; } /* Check if file is supposed to be ignored */ if (Config.syscheck_ignore) { char **ff_ig = Config.syscheck_ignore; while (*ff_ig) { if (strncasecmp(*ff_ig, f_name, strlen(*ff_ig)) == 0) { lf->data = NULL; return (0); } ff_ig++; } } /* Checksum is at the beginning of the log */ c_sum = lf->log; /* Extract the MD5 hash and search for it in the allowlist * Sample message: * 0:0:0:0:78f5c869675b1d09ddad870adad073f9:bd6c8d7a58b462aac86475e59af0e22954039c50 */ #ifdef SQLITE_ENABLED if (Config.md5_allowlist) { extern sqlite3 *conn; if ((p = extract_token(c_sum, ":", 4))) { if (!validate_md5(p)) { /* Never trust input from other origin */ merror("%s: Not a valid MD5 hash: '%s'", ARGV0, p); return(0); } debug1("%s: Checking MD5 '%s' in %s", ARGV0, p, Config.md5_allowlist); sprintf(stmt, "select md5sum from files where md5sum = \"%s\"", p); error = sqlite3_prepare_v2(conn, stmt, 1000, &res, &tail); if (error == SQLITE_OK) { while (sqlite3_step(res) == SQLITE_ROW) { rec_count++; } if (rec_count) { sqlite3_finalize(res); //sqlite3_close(conn); merror(MD5_NOT_CHECKED, ARGV0, p); return(0); } } sqlite3_finalize(res); } } #endif /* Search for file changes */ return (DB_Search(f_name, c_sum, lf)); }
// // Implements the ARTICLE, HEAD, BODY, and STAT commands. // (These commands all accept the same parameters; they differ only in how they output the retrieved message.) // void nntp_article(const char *cmd) { if (CtdlAccessCheck(ac_logged_in_or_guest)) return; citnntp *nntpstate = (citnntp *) CC->session_specific_data; char which_command[16]; int acmd = 0; char requested_article[256]; long requested_msgnum = 0; char *lb, *rb = NULL; int must_change_currently_selected_article = 0; // We're going to store one of these values in the variable 'acmd' so that // we can quickly check later which version of the output we want. enum { ARTICLE, HEAD, BODY, STAT }; extract_token(which_command, cmd, 0, ' ', sizeof which_command); if (!strcasecmp(which_command, "article")) { acmd = ARTICLE; } else if (!strcasecmp(which_command, "head")) { acmd = HEAD; } else if (!strcasecmp(which_command, "body")) { acmd = BODY; } else if (!strcasecmp(which_command, "stat")) { acmd = STAT; } else { cprintf("500 I'm afraid I can't do that.\r\n"); return; } // Which NNTP command was issued, determines whether we will fetch headers, body, or both. int headers_only = HEADERS_ALL; if (acmd == HEAD) headers_only = HEADERS_FAST; else if (acmd == BODY) headers_only = HEADERS_NONE; else if (acmd == STAT) headers_only = HEADERS_FAST; // now figure out what the client is asking for. extract_token(requested_article, cmd, 1, ' ', sizeof requested_article); lb = strchr(requested_article, '<'); rb = strchr(requested_article, '>'); requested_msgnum = atol(requested_article); // If no article number or message-id is specified, the client wants the "currently selected article" if (IsEmptyStr(requested_article)) { if (nntpstate->current_article_number < 1) { cprintf("420 No current article selected\r\n"); return; } requested_msgnum = nntpstate->current_article_number; must_change_currently_selected_article = 1; // got it -- now fall through and keep going } // If the requested article is numeric, it maps directly to a message number. Good. else if (requested_msgnum > 0) { must_change_currently_selected_article = 1; // good -- fall through and keep going } // If the requested article has angle brackets, the client wants a specific message-id. // We don't know how to do that yet. else if ( (lb != NULL) && (rb != NULL) && (lb < rb) ) { must_change_currently_selected_article = 0; cprintf("500 I don't know how to fetch by message-id yet.\r\n"); // FIXME return; } // Anything else is noncompliant gobbledygook and should die in a car fire. else { must_change_currently_selected_article = 0; cprintf("500 syntax error\r\n"); return; } // At this point we know the message number of the "article" being requested. // We have an awesome API call that does all the heavy lifting for us. char *fetched_message_id = NULL; CC->redirect_buffer = NewStrBufPlain(NULL, SIZ); int fetch = CtdlOutputMsg(requested_msgnum, MT_RFC822, // output in RFC822 format ... sort of headers_only, // headers, body, or both? 0, // don't do Citadel protocol responses 1, // CRLF newlines NULL, // teh whole thing, not just a section 0, // no flags yet ... maybe new ones for Path: etc ? NULL, NULL, &fetched_message_id // extract the message ID from the message as we go... ); StrBuf *msgtext = CC->redirect_buffer; CC->redirect_buffer = NULL; if (fetch != om_ok) { cprintf("423 no article with that number\r\n"); FreeStrBuf(&msgtext); return; } // RFC3977 6.2.1.2 specifes conditions under which the "currently selected article" // MUST or MUST NOT be set to the message we just referenced. if (must_change_currently_selected_article) { nntpstate->current_article_number = requested_msgnum; } // Now give the client what it asked for. if (acmd == ARTICLE) { cprintf("220 %ld <%s>\r\n", requested_msgnum, fetched_message_id); } if (acmd == HEAD) { cprintf("221 %ld <%s>\r\n", requested_msgnum, fetched_message_id); } if (acmd == BODY) { cprintf("222 %ld <%s>\r\n", requested_msgnum, fetched_message_id); } if (acmd == STAT) { cprintf("223 %ld <%s>\r\n", requested_msgnum, fetched_message_id); FreeStrBuf(&msgtext); return; } client_write(SKEY(msgtext)); cprintf(".\r\n"); // this protocol uses a dot terminator FreeStrBuf(&msgtext); if (fetched_message_id) free(fetched_message_id); }
/* * Finalize an OpenID authentication */ void cmd_oidf(char *argbuf) { long len; char buf[2048]; char thiskey[1024]; char thisdata[1024]; HashList *keys = NULL; const char *Key; void *Value; ctdl_openid *oiddata = (ctdl_openid *) CC->openid_data; if (CtdlGetConfigInt("c_disable_newu")) { cprintf("%d this system does not support openid.\n", ERROR + CMD_NOT_SUPPORTED); return; } if (oiddata == NULL) { cprintf("%d run OIDS first.\n", ERROR + INTERNAL_ERROR); return; } if (StrLength(oiddata->op_url) == 0){ cprintf("%d No OpenID Endpoint URL has been obtained.\n", ERROR + ILLEGAL_VALUE); return; } keys = NewHash(1, NULL); if (!keys) { cprintf("%d NewHash() failed\n", ERROR + INTERNAL_ERROR); return; } cprintf("%d Transmit OpenID data now\n", START_CHAT_MODE); while (client_getln(buf, sizeof buf), strcmp(buf, "000")) { len = extract_token(thiskey, buf, 0, '|', sizeof thiskey); if (len < 0) { len = sizeof(thiskey) - 1; } extract_token(thisdata, buf, 1, '|', sizeof thisdata); Put(keys, thiskey, len, strdup(thisdata), NULL); } /* Check to see if this is a correct response. * Start with verified=1 but then set it to 0 if anything looks wrong. */ oiddata->verified = 1; char *openid_ns = NULL; if ( (!GetHash(keys, "ns", 2, (void *) &openid_ns)) || (strcasecmp(openid_ns, "http://specs.openid.net/auth/2.0")) ) { syslog(LOG_DEBUG, "This is not an an OpenID assertion"); oiddata->verified = 0; } char *openid_mode = NULL; if ( (!GetHash(keys, "mode", 4, (void *) &openid_mode)) || (strcasecmp(openid_mode, "id_res")) ) { oiddata->verified = 0; } char *openid_claimed_id = NULL; if (GetHash(keys, "claimed_id", 10, (void *) &openid_claimed_id)) { FreeStrBuf(&oiddata->claimed_id); oiddata->claimed_id = NewStrBufPlain(openid_claimed_id, -1); syslog(LOG_DEBUG, "Provider is asserting the Claimed ID '%s'", ChrPtr(oiddata->claimed_id)); } /* Validate the assertion against the server */ syslog(LOG_DEBUG, "Validating..."); CURL *curl; CURLcode res; struct curl_httppost *formpost = NULL; struct curl_httppost *lastptr = NULL; char errmsg[1024] = ""; StrBuf *ReplyBuf = NewStrBuf(); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, "openid.mode", CURLFORM_COPYCONTENTS, "check_authentication", CURLFORM_END ); HashPos *HashPos = GetNewHashPos(keys, 0); while (GetNextHashPos(keys, HashPos, &len, &Key, &Value) != 0) { if (strcasecmp(Key, "mode")) { char k_o_keyname[1024]; snprintf(k_o_keyname, sizeof k_o_keyname, "openid.%s", (const char *)Key); curl_formadd(&formpost, &lastptr, CURLFORM_COPYNAME, k_o_keyname, CURLFORM_COPYCONTENTS, (char *)Value, CURLFORM_END ); } } DeleteHashPos(&HashPos); curl = ctdl_openid_curl_easy_init(errmsg); curl_easy_setopt(curl, CURLOPT_URL, ChrPtr(oiddata->op_url)); curl_easy_setopt(curl, CURLOPT_WRITEDATA, ReplyBuf); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlFillStrBuf_callback); curl_easy_setopt(curl, CURLOPT_HTTPPOST, formpost); res = curl_easy_perform(curl); if (res) { syslog(LOG_DEBUG, "cmd_oidf() libcurl error %d: %s", res, errmsg); oiddata->verified = 0; } curl_easy_cleanup(curl); curl_formfree(formpost); /* syslog(LOG_DEBUG, "Validation reply: \n%s", ChrPtr(ReplyBuf)); */ if (cbmstrcasestr(ChrPtr(ReplyBuf), "is_valid:true") == NULL) { oiddata->verified = 0; } FreeStrBuf(&ReplyBuf); syslog(LOG_DEBUG, "OpenID authentication %s", (oiddata->verified ? "succeeded" : "failed") ); /* Respond to the client */ if (oiddata->verified) { /* If we were already logged in, attach the OpenID to the user's account */ if (CC->logged_in) { if (attach_openid(&CC->user, oiddata->claimed_id) == 0) { cprintf("attach\n"); syslog(LOG_DEBUG, "OpenID attach succeeded"); } else { cprintf("fail\n"); syslog(LOG_DEBUG, "OpenID attach failed"); } } /* Otherwise, a user is attempting to log in using the verified OpenID */ else { /* * Existing user who has claimed this OpenID? * * Note: if you think that sending the password back over the wire is insecure, * check your assumptions. If someone has successfully asserted an OpenID that * is associated with the account, they already have password equivalency and can * login, so they could just as easily change the password, etc. */ if (login_via_openid(oiddata->claimed_id) == 0) { cprintf("authenticate\n%s\n%s\n", CC->user.fullname, CC->user.password); logged_in_response(); syslog(LOG_DEBUG, "Logged in using previously claimed OpenID"); } /* * If this system does not allow self-service new user registration, the * remaining modes do not apply, so fail here and now. */ else if (CtdlGetConfigInt("c_disable_newu")) { cprintf("fail\n"); syslog(LOG_DEBUG, "Creating user failed due to local policy"); } /* * New user whose OpenID is verified and Attribute Exchange gave us a name? */ else if (openid_create_user_via_ax(oiddata->claimed_id, keys) == 0) { cprintf("authenticate\n%s\n%s\n", CC->user.fullname, CC->user.password); logged_in_response(); syslog(LOG_DEBUG, "Successfully auto-created new user"); } /* * OpenID is verified, but the desired username either was not specified or * conflicts with an existing user. Manual account creation is required. */ else { char *desired_name = NULL; cprintf("verify_only\n"); cprintf("%s\n", ChrPtr(oiddata->claimed_id)); if (GetHash(keys, "sreg.nickname", 13, (void *) &desired_name)) { cprintf("%s\n", desired_name); } else { cprintf("\n"); } syslog(LOG_DEBUG, "The desired display name is already taken."); } } } else { cprintf("fail\n"); } cprintf("000\n"); if (oiddata->sreg_keys != NULL) { DeleteHash(&oiddata->sreg_keys); oiddata->sreg_keys = NULL; } oiddata->sreg_keys = keys; }
inline int Gq_add_media_component_description(AAAMessage *msg,str sdpinvite,str sdp200,char *mline,int number,int tag) { str data; AAA_AVP_LIST list; AAA_AVP *media_component_number,*media_type; AAA_AVP *codec_data1,*codec_data2; AAA_AVP *media_sub_component[Gq_Media_Sub_Components]; AAA_AVP *Max_DL,*Max_UL; AAA_AVP *RR,*RS; AAA_AVP *flow_status; bandwidth bwUL,bwDL; char *ptr; char port[Gq_MAX_Char]; int type,i,n,a; char x[4]; /*needed to use AAA_AVP-LIST!!*/ list.head=0; list.tail=0; /*media-component-number*/ set_4bytes(x,number); media_component_number=cdpb.AAACreateAVP(AVP_IMS_Media_Component_Number, AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC, IMS_vendor_id_3GPP,x,4, AVP_DUPLICATE_DATA); if (media_component_number!=NULL) { AAAAddAVPToAVPList(&list,media_component_number); } else { LOG(L_INFO, ANSI_RED"INF:"M_NAME"Unable to create media_component_number AVP"); return 0; } /*media-sub-component*/ n=Gq_create_add_media_subcomponents(&list,sdpinvite,sdp200,number,media_sub_component,tag); if(n==-1) { LOG(L_INFO, ANSI_RED"INF:"M_NAME"Unable to create media_sub_components list AVP"); cdpb.AAAFreeAVP(&media_component_number); list.head=0; list.tail=0; return 0; } if (n==0) { /*we don't create a Media Description for this media line*/ /*because answerer rejected the offer!*/ cdpb.AAAFreeAVP(&media_component_number); list.head=0; list.tail=0; return 1; } /*if n=-1 then its error*/ /*if n=0 is because answerer rejected this media offer*/ /*or offerer wanted it to be disabled*/ /*media-type*/ ptr=mline; ptr+=2; /*skip m=*/ if (strncmp(ptr,"audio",5)==0) { type=AVP_IMS_Media_Type_Audio; } else if(strncmp(ptr,"video",5)==0) { type=AVP_IMS_Media_Type_Video; }else if(strncmp(ptr,"data",4)==0) { type=AVP_IMS_Media_Type_Data; }else if(strncmp(ptr,"application",11)==0) { type=AVP_IMS_Media_Type_Application; }else if(strncmp(ptr,"control",7)==0) { type=AVP_IMS_Media_Type_Control; }else if(strncmp(ptr,"text",4)==0) { type=AVP_IMS_Media_Type_Text; }else if(strncmp(ptr,"message",7)==0) { type=AVP_IMS_Media_Type_Message; } else { type=AVP_IMS_Media_Type_Other; } set_4bytes(x,type); media_type=cdpb.AAACreateAVP(AVP_IMS_Media_Type, AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC, IMS_vendor_id_3GPP,x,4, AVP_DUPLICATE_DATA); AAAAddAVPToAVPList(&list,media_type); /*Max-Requested-Bandwidth-UL*/ /*Max-Requested-Bandwidth-DL*/ /*SDP bodies have been check by gq_create_add_media_subcomponents*/ i=1; ptr=find_sdp_line(sdp200.s,(sdp200.s+sdp200.len),'m'); while(i!=number) { ptr=find_next_sdp_line(ptr,(sdp200.s+sdp200.len),'m',NULL); i++; } if(tag==1) { /*in the invite its defined how much bandwidth * you want in the downlink!*/ extract_bandwidth(&bwDL,sdpinvite,mline); extract_bandwidth(&bwUL,sdp200,ptr); } else { extract_bandwidth(&bwDL,sdp200,ptr); extract_bandwidth(&bwUL,sdpinvite,mline); } /* * IN a SDP b=AS:x line the x is the amount of bandwidth * the sender of the SDP body is willing to RECEIVE * therefor the next code is right * * */ if (bwDL.bAS!=0) { set_4bytes(x,bwDL.bAS); Max_UL=cdpb.AAACreateAVP(AVP_IMS_Max_Requested_Bandwidth_UL, AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC, IMS_vendor_id_3GPP,x,4, AVP_DUPLICATE_DATA); AAAAddAVPToAVPList(&list,Max_UL); } if (bwUL.bAS!=0) { set_4bytes(x,bwUL.bAS); Max_DL=cdpb.AAACreateAVP(AVP_IMS_Max_Requested_Bandwidth_DL, AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC, IMS_vendor_id_3GPP,x,4, AVP_DUPLICATE_DATA); AAAAddAVPToAVPList(&list,Max_DL); } /*Flow-Status*/ /*lets follow the specs*/ if (tag==0) { extract_token(mline,port,Gq_MAX_Char,2); } else { extract_token(ptr,port,Gq_MAX_Char,2); } if(strncmp(port,"0",1)==0) { set_4bytes(x,AVP_IMS_Flow_Status_Removed); } else { if (tag==1) { a=check_atributes(sdp200,ptr); } else { a=check_atributes(sdpinvite,mline); } if (a==1) { set_4bytes(x,AVP_IMS_Flow_Status_Enabled_Uplink); } else if(a==2) { set_4bytes(x,AVP_IMS_Flow_Status_Enabled_Downlink); } else { set_4bytes(x,AVP_IMS_Flow_Status_Enabled); } } flow_status=cdpb.AAACreateAVP(AVP_IMS_Flow_Status, AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC, IMS_vendor_id_3GPP,x,4, AVP_DUPLICATE_DATA); AAAAddAVPToAVPList(&list,flow_status); /*RR and RS*/ x[0]=0; x[1]=0; x[2]=0; x[3]=0; if(bwUL.bRR!=0) { set_4bytes(x,bwUL.bRR); } /*else if (bwDL.bRS!=0) { set_4bytes(x,bwDL.bRS); }*/ RR=0; if (x[0]!=0 || x[1]!=0 || x[2]!=0 || x[3]!=0) { RR=cdpb.AAACreateAVP(AVP_IMS_RR_Bandwidth, AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC, IMS_vendor_id_3GPP,x,4, AVP_DUPLICATE_DATA); AAAAddAVPToAVPList(&list,RR); } x[0]=0; x[1]=0; x[2]=0; x[3]=0; if(bwUL.bRS!=0) { set_4bytes(x,bwUL.bRS); } /*else if(bwDL.bRR!=0){ set_4bytes(x,bwDL.bRR); }*/ RS=0; if (x[0]!=0 || x[1]!=0 || x[2]!=0 || x[3]!=0) { RS=cdpb.AAACreateAVP(AVP_IMS_RS_Bandwidth, AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC, IMS_vendor_id_3GPP,x,4, AVP_DUPLICATE_DATA); AAAAddAVPToAVPList(&list,RS); } /*codec-data*/ if (tag==0) { /*0 means uplink offer*/ codec_data1=Gq_create_codec_data(sdpinvite,number,0); AAAAddAVPToAVPList(&list,codec_data1); /*3 means downlink answer*/ codec_data2=Gq_create_codec_data(sdp200,number,3); AAAAddAVPToAVPList(&list,codec_data2); } else { /*2 means downlink offer*/ codec_data1=Gq_create_codec_data(sdpinvite,number,2); AAAAddAVPToAVPList(&list,codec_data1); /*1 means uplink answer*/ codec_data2=Gq_create_codec_data(sdp200,number,1); AAAAddAVPToAVPList(&list,codec_data2); } /*now group them in one big AVP and free them*/ data=cdpb.AAAGroupAVPS(list); Gq_add_avp(msg,data.s,data.len,AVP_IMS_Media_Component_Description, AAA_AVP_FLAG_MANDATORY|AAA_AVP_FLAG_VENDOR_SPECIFIC, IMS_vendor_id_3GPP, AVP_DUPLICATE_DATA, __FUNCTION__); cdpb.AAAFreeAVP(&media_component_number); for(i=0;i<n;i++) { cdpb.AAAFreeAVP(&media_sub_component[i]); } if (bwUL.bAS!=0) { cdpb.AAAFreeAVP(&Max_UL); } if (bwDL.bAS!=0) { cdpb.AAAFreeAVP(&Max_DL); } cdpb.AAAFreeAVP(&flow_status); if (RS!=0) { cdpb.AAAFreeAVP(&RS); } if (RR!=0) { cdpb.AAAFreeAVP(&RR); } cdpb.AAAFreeAVP(&media_type); cdpb.AAAFreeAVP(&codec_data1); cdpb.AAAFreeAVP(&codec_data2); list.tail=0; list.head=0; return 1; }
/* * Converts a PEM encoded file into its binary form * * RFC 1421 Privacy Enhancement for Electronic Mail, February 1993 * RFC 934 Message Encapsulation, January 1985 * * We no longer support decrypting PEM files - those can only come in via NSS */ err_t pemtobin(chunk_t *blob) { typedef enum { PEM_PRE = 0, PEM_MSG = 1, PEM_HEADER = 2, PEM_BODY = 3, PEM_POST = 4, PEM_ABORT = 5 } state_t; state_t state = PEM_PRE; chunk_t src = *blob; chunk_t dst = *blob; chunk_t line = empty_chunk; /* zero size of converted blob */ dst.len = 0; while (fetchline(&src, &line)) { if (state == PEM_PRE) { if (find_boundary("BEGIN", &line)) { state = PEM_MSG; } continue; } else { if (find_boundary("END", &line)) { state = PEM_POST; break; } if (state == PEM_MSG) { state = (memchr(line.ptr, ':', line.len) == NULL) ? PEM_BODY : PEM_HEADER; } if (state == PEM_HEADER) { chunk_t name = empty_chunk; chunk_t value = empty_chunk; /* an empty line separates HEADER and BODY */ if (line.len == 0) { state = PEM_BODY; continue; } /* we are looking for a name: value pair */ if (!extract_parameter(&name, &value, &line)) continue; if (match("Proc-Type", &name) && *value.ptr == '4') return "Proc-Type: encrypted files no longer supported outside of the NSS database, please import these into NSS"; else if (match("DEK-Info", &name)) return "DEK-Info: encrypted files no longer supported outside of the NSS database, please import these into NSS"; } else { /* state is PEM_BODY */ const char *ugh = NULL; size_t len = 0; chunk_t data; /* remove any trailing whitespace */ if (!extract_token(&data, ' ', &line)) data = line; ugh = ttodata((char *)data.ptr, data.len, 64, (char *)dst.ptr, blob->len - dst.len, &len); if (ugh) { DBG(DBG_PARSING, DBG_log(" %s", ugh)); state = PEM_ABORT; break; } else { dst.ptr += len; dst.len += len; } } } } /* set length to size of binary blob */ blob->len = dst.len; if (state != PEM_POST) return "file coded in unknown format, discarded"; return NULL; }
static int parse_attribute_crypto(struct sdp_attribute *output) { PARSE_DECL; char *endp; struct attribute_crypto *c; int salt_key_len, enc_salt_key_len; int b64_state = 0; unsigned int b64_save = 0; gsize ret; str s; u_int32_t u32; const char *err; output->attr = ATTR_CRYPTO; PARSE_INIT; EXTRACT_TOKEN(u.crypto.tag_str); EXTRACT_TOKEN(u.crypto.crypto_suite_str); EXTRACT_TOKEN(u.crypto.key_params_str); c = &output->u.crypto; c->tag = strtoul(c->tag_str.s, &endp, 10); err = "invalid 'tag'"; if (endp == c->tag_str.s) goto error; c->crypto_suite = crypto_find_suite(&c->crypto_suite_str); err = "unknown crypto suite"; if (!c->crypto_suite) goto error; salt_key_len = c->crypto_suite->master_key_len + c->crypto_suite->master_salt_len; enc_salt_key_len = ceil((double) salt_key_len * 4.0/3.0); err = "invalid key parameter length"; if (c->key_params_str.len < 7 + enc_salt_key_len) goto error; err = "unknown key method"; if (strncasecmp(c->key_params_str.s, "inline:", 7)) goto error; c->key_base64_str = c->key_params_str; str_shift(&c->key_base64_str, 7); ret = g_base64_decode_step(c->key_base64_str.s, enc_salt_key_len, (guchar *) c->key_salt_buf, &b64_state, &b64_save); err = "invalid base64 encoding"; if (ret != salt_key_len) goto error; c->master_key.s = c->key_salt_buf; c->master_key.len = c->crypto_suite->master_key_len; c->salt.s = c->master_key.s + c->master_key.len; c->salt.len = c->crypto_suite->master_salt_len; c->lifetime_str = c->key_params_str; str_shift(&c->lifetime_str, 7 + enc_salt_key_len); if (c->lifetime_str.len >= 2) { err = "invalid key parameter syntax"; if (c->lifetime_str.s[0] != '|') goto error; str_shift(&c->lifetime_str, 1); str_chr_str(&c->mki_str, &c->lifetime_str, '|'); if (!c->mki_str.s) { if (str_chr(&c->lifetime_str, ':')) { c->mki_str = c->lifetime_str; c->lifetime_str = STR_NULL; } } else { c->lifetime_str.len = c->mki_str.s - c->lifetime_str.s; str_shift(&c->mki_str, 1); } } else c->lifetime_str = STR_NULL; if (c->lifetime_str.s) { if (c->lifetime_str.len >= 3 && !memcmp(c->lifetime_str.s, "2^", 2)) { c->lifetime = strtoull(c->lifetime_str.s + 2, NULL, 10); err = "invalid key lifetime"; if (!c->lifetime || c->lifetime > 64) goto error; c->lifetime = 1ULL << c->lifetime; } else c->lifetime = strtoull(c->lifetime_str.s, NULL, 10); err = "invalid key lifetime"; if (!c->lifetime || c->lifetime > c->crypto_suite->srtp_lifetime #ifdef STRICT_SDES_KEY_LIFETIME || c->lifetime > c->crypto_suite->srtcp_lifetime #endif ) goto error; } if (c->mki_str.s) { str_chr_str(&s, &c->mki_str, ':'); err = "invalid MKI specification"; if (!s.s) goto error; u32 = htonl(strtoul(c->mki_str.s, NULL, 10)); c->mki_len = strtoul(s.s + 1, NULL, 10); err = "MKI too long"; if (c->mki_len > sizeof(c->mki)) goto error; memset(c->mki, 0, c->mki_len); if (sizeof(u32) >= c->mki_len) memcpy(c->mki, ((void *) &u32) + (sizeof(u32) - c->mki_len), c->mki_len); else memcpy(c->mki + (c->mki_len - sizeof(u32)), &u32, sizeof(u32)); } while (extract_token(&start, end, &s) == 0) { if (!str_cmp(&s, "UNENCRYPTED_SRTCP")) c->unencrypted_srtcp = 1; else if (!str_cmp(&s, "UNENCRYPTED_SRTP")) c->unencrypted_srtp = 1; else if (!str_cmp(&s, "UNAUTHENTICATED_SRTP")) c->unauthenticated_srtp = 1; } return 0; error: ilog(LOG_ERROR, "Failed to parse a=crypto attribute: %s", err); return -1; }
/** * Converts a PEM encoded file into its binary form (RFC 1421, RFC 934) */ static status_t pem_to_bin(chunk_t *blob, bool *pgp) { typedef enum { PEM_PRE = 0, PEM_MSG = 1, PEM_HEADER = 2, PEM_BODY = 3, PEM_POST = 4, PEM_ABORT = 5 } state_t; encryption_algorithm_t alg = ENCR_UNDEFINED; size_t key_size = 0; bool encrypted = FALSE; state_t state = PEM_PRE; chunk_t src = *blob; chunk_t dst = *blob; chunk_t line = chunk_empty; chunk_t iv = chunk_empty; u_char iv_buf[HASH_SIZE_MD5]; status_t status = NOT_FOUND; enumerator_t *enumerator; shared_key_t *shared; dst.len = 0; iv.ptr = iv_buf; iv.len = 0; while (fetchline(&src, &line)) { if (state == PEM_PRE) { if (find_boundary("BEGIN", &line)) { state = PEM_MSG; } continue; } else { if (find_boundary("END", &line)) { state = PEM_POST; break; } if (state == PEM_MSG) { state = PEM_HEADER; if (memchr(line.ptr, ':', line.len) == NULL) { state = PEM_BODY; } } if (state == PEM_HEADER) { err_t ugh = NULL; chunk_t name = chunk_empty; chunk_t value = chunk_empty; /* an empty line separates HEADER and BODY */ if (line.len == 0) { state = PEM_BODY; continue; } /* we are looking for a parameter: value pair */ DBG2(DBG_ASN, " %.*s", (int)line.len, line.ptr); ugh = extract_parameter_value(&name, &value, &line); if (ugh != NULL) { continue; } if (match("Proc-Type", &name) && *value.ptr == '4') { encrypted = TRUE; } else if (match("DEK-Info", &name)) { chunk_t dek; if (!extract_token(&dek, ',', &value)) { dek = value; } if (match("DES-EDE3-CBC", &dek)) { alg = ENCR_3DES; key_size = 24; } else if (match("AES-128-CBC", &dek)) { alg = ENCR_AES_CBC; key_size = 16; } else if (match("AES-192-CBC", &dek)) { alg = ENCR_AES_CBC; key_size = 24; } else if (match("AES-256-CBC", &dek)) { alg = ENCR_AES_CBC; key_size = 32; } else { DBG1(DBG_ASN, " encryption algorithm '%.*s'" " not supported", (int)dek.len, dek.ptr); return NOT_SUPPORTED; } if (!eat_whitespace(&value) || value.len > 2*sizeof(iv_buf)) { return PARSE_ERROR; } iv = chunk_from_hex(value, iv_buf); } } else /* state is PEM_BODY */ { chunk_t data; /* remove any trailing whitespace */ if (!extract_token(&data ,' ', &line)) { data = line; } /* check for PGP armor checksum */ if (*data.ptr == '=') { *pgp = TRUE; data.ptr++; data.len--; DBG2(DBG_ASN, " armor checksum: %.*s", (int)data.len, data.ptr); continue; } if (blob->len - dst.len < data.len / 4 * 3) { state = PEM_ABORT; } data = chunk_from_base64(data, dst.ptr); dst.ptr += data.len; dst.len += data.len; } } } /* set length to size of binary blob */ blob->len = dst.len; if (state != PEM_POST) { DBG1(DBG_LIB, " file coded in unknown format, discarded"); return PARSE_ERROR; } if (!encrypted) { return SUCCESS; } enumerator = lib->credmgr->create_shared_enumerator(lib->credmgr, SHARED_PRIVATE_KEY_PASS, NULL, NULL); while (enumerator->enumerate(enumerator, &shared, NULL, NULL)) { chunk_t passphrase, chunk; passphrase = shared->get_key(shared); chunk = chunk_clone(*blob); status = pem_decrypt(&chunk, alg, key_size, iv, passphrase); if (status == SUCCESS) { memcpy(blob->ptr, chunk.ptr, chunk.len); blob->len = chunk.len; } free(chunk.ptr); if (status != INVALID_ARG) { /* try again only if passphrase invalid */ break; } } enumerator->destroy(enumerator); return status; }
/* * create a new room */ void cmd_cre8(char *args) { int cre8_ok; char new_room_name[ROOMNAMELEN]; int new_room_type; char new_room_pass[32]; int new_room_floor; int new_room_view; char *notification_message = NULL; unsigned newflags; struct floor *fl; int avoid_access = 0; cre8_ok = extract_int(args, 0); extract_token(new_room_name, args, 1, '|', sizeof new_room_name); new_room_name[ROOMNAMELEN - 1] = 0; new_room_type = extract_int(args, 2); extract_token(new_room_pass, args, 3, '|', sizeof new_room_pass); avoid_access = extract_int(args, 5); new_room_view = extract_int(args, 6); new_room_pass[9] = 0; new_room_floor = 0; if ((IsEmptyStr(new_room_name)) && (cre8_ok == 1)) { cprintf("%d Invalid room name.\n", ERROR + ILLEGAL_VALUE); return; } if (!strcasecmp(new_room_name, MAILROOM)) { cprintf("%d '%s' already exists.\n", ERROR + ALREADY_EXISTS, new_room_name); return; } if (num_parms(args) >= 5) { fl = CtdlGetCachedFloor(extract_int(args, 4)); if (fl == NULL) { cprintf("%d Invalid floor number.\n", ERROR + INVALID_FLOOR_OPERATION); return; } else if ((fl->f_flags & F_INUSE) == 0) { cprintf("%d Invalid floor number.\n", ERROR + INVALID_FLOOR_OPERATION); return; } else { new_room_floor = extract_int(args, 4); } } if (CtdlAccessCheck(ac_logged_in)) return; if (CC->user.axlevel < CtdlGetConfigInt("c_createax") && !CC->internal_pgm) { cprintf("%d You need higher access to create rooms.\n", ERROR + HIGHER_ACCESS_REQUIRED); return; } if ((IsEmptyStr(new_room_name)) && (cre8_ok == 0)) { cprintf("%d Ok to create rooms.\n", CIT_OK); return; } if ((new_room_type < 0) || (new_room_type > 5)) { cprintf("%d Invalid room type.\n", ERROR + ILLEGAL_VALUE); return; } if (new_room_type == 5) { if (CC->user.axlevel < AxAideU) { cprintf("%d Higher access required\n", ERROR + HIGHER_ACCESS_REQUIRED); return; } } /* Check to make sure the requested room name doesn't already exist */ newflags = CtdlCreateRoom(new_room_name, new_room_type, new_room_pass, new_room_floor, 0, avoid_access, new_room_view); if (newflags == 0) { cprintf("%d '%s' already exists.\n", ERROR + ALREADY_EXISTS, new_room_name); return; } if (cre8_ok == 0) { cprintf("%d OK to create '%s'\n", CIT_OK, new_room_name); return; } /* If we reach this point, the room needs to be created. */ newflags = CtdlCreateRoom(new_room_name, new_room_type, new_room_pass, new_room_floor, 1, 0, new_room_view); /* post a message in Aide> describing the new room */ notification_message = malloc(1024); snprintf(notification_message, 1024, "A new room called \"%s\" has been created by %s%s%s%s%s%s\n", new_room_name, (CC->logged_in ? CC->curr_user : "******"), ((newflags & QR_MAILBOX) ? " [personal]" : ""), ((newflags & QR_PRIVATE) ? " [private]" : ""), ((newflags & QR_GUESSNAME) ? " [hidden]" : ""), ((newflags & QR_PASSWORDED) ? " Password: "******""), ((newflags & QR_PASSWORDED) ? new_room_pass : "") ); CtdlAideMessage(notification_message, "Room Creation Message"); free(notification_message); cprintf("%d '%s' has been created.\n", CIT_OK, new_room_name); }
/** * Converts a PEM encoded file into its binary form (RFC 1421, RFC 934) */ static status_t pem_to_bin(chunk_t *blob, chunk_t(*cb)(void*,int), void *cb_data, bool *pgp) { typedef enum { PEM_PRE = 0, PEM_MSG = 1, PEM_HEADER = 2, PEM_BODY = 3, PEM_POST = 4, PEM_ABORT = 5 } state_t; encryption_algorithm_t alg = ENCR_UNDEFINED; size_t key_size = 0; bool encrypted = FALSE; state_t state = PEM_PRE; chunk_t src = *blob; chunk_t dst = *blob; chunk_t line = chunk_empty; chunk_t iv = chunk_empty; chunk_t passphrase; int try = 0; u_char iv_buf[HASH_SIZE_MD5]; dst.len = 0; iv.ptr = iv_buf; iv.len = 0; while (fetchline(&src, &line)) { if (state == PEM_PRE) { if (find_boundary("BEGIN", &line)) { state = PEM_MSG; } continue; } else { if (find_boundary("END", &line)) { state = PEM_POST; break; } if (state == PEM_MSG) { state = PEM_HEADER; if (memchr(line.ptr, ':', line.len) == NULL) { state = PEM_BODY; } } if (state == PEM_HEADER) { err_t ugh = NULL; chunk_t name = chunk_empty; chunk_t value = chunk_empty; /* an empty line separates HEADER and BODY */ if (line.len == 0) { state = PEM_BODY; continue; } /* we are looking for a parameter: value pair */ DBG2(DBG_LIB, " %.*s", (int)line.len, line.ptr); ugh = extract_parameter_value(&name, &value, &line); if (ugh != NULL) { continue; } if (match("Proc-Type", &name) && *value.ptr == '4') { encrypted = TRUE; } else if (match("DEK-Info", &name)) { chunk_t dek; if (!extract_token(&dek, ',', &value)) { dek = value; } if (match("DES-EDE3-CBC", &dek)) { alg = ENCR_3DES; key_size = 24; } else if (match("AES-128-CBC", &dek)) { alg = ENCR_AES_CBC; key_size = 16; } else if (match("AES-192-CBC", &dek)) { alg = ENCR_AES_CBC; key_size = 24; } else if (match("AES-256-CBC", &dek)) { alg = ENCR_AES_CBC; key_size = 32; } else { DBG1(DBG_LIB, " encryption algorithm '%.*s'" " not supported", dek.len, dek.ptr); return NOT_SUPPORTED; } eat_whitespace(&value); iv = chunk_from_hex(value, iv.ptr); } } else /* state is PEM_BODY */ { chunk_t data; /* remove any trailing whitespace */ if (!extract_token(&data ,' ', &line)) { data = line; } /* check for PGP armor checksum */ if (*data.ptr == '=') { *pgp = TRUE; data.ptr++; data.len--; DBG2(DBG_LIB, " armor checksum: %.*s", (int)data.len, data.ptr); continue; } if (blob->len - dst.len < data.len / 4 * 3) { state = PEM_ABORT; } data = chunk_from_base64(data, dst.ptr); dst.ptr += data.len; dst.len += data.len; } } } /* set length to size of binary blob */ blob->len = dst.len; if (state != PEM_POST) { DBG1(DBG_LIB, " file coded in unknown format, discarded"); return PARSE_ERROR; } if (!encrypted) { return SUCCESS; } if (!cb) { DBG1(DBG_LIB, " missing passphrase"); return INVALID_ARG; } while (TRUE) { passphrase = cb(cb_data, ++try); if (!passphrase.len || !passphrase.ptr) { return INVALID_ARG; } switch (pem_decrypt(blob, alg, key_size, iv, passphrase)) { case INVALID_ARG: /* bad passphrase, retry */ continue; case SUCCESS: return SUCCESS; default: return FAILED; } } }
/* * set room parameters (admin or room admin command) */ void cmd_setr(char *args) { char buf[256]; int new_order = 0; int r; int new_floor; char new_name[ROOMNAMELEN]; if (CtdlAccessCheck(ac_logged_in)) return; if (num_parms(args) >= 6) { new_floor = extract_int(args, 5); } else { new_floor = (-1); /* don't change the floor */ } /* When is a new name more than just a new name? When the old name * has a namespace prefix. */ if (CC->room.QRflags & QR_MAILBOX) { sprintf(new_name, "%010ld.", atol(CC->room.QRname) ); } else { safestrncpy(new_name, "", sizeof new_name); } extract_token(&new_name[strlen(new_name)], args, 0, '|', (sizeof new_name - strlen(new_name))); r = CtdlRenameRoom(CC->room.QRname, new_name, new_floor); if (r == crr_room_not_found) { cprintf("%d Internal error - room not found?\n", ERROR + INTERNAL_ERROR); } else if (r == crr_already_exists) { cprintf("%d '%s' already exists.\n", ERROR + ALREADY_EXISTS, new_name); } else if (r == crr_noneditable) { cprintf("%d Cannot edit this room.\n", ERROR + NOT_HERE); } else if (r == crr_invalid_floor) { cprintf("%d Target floor does not exist.\n", ERROR + INVALID_FLOOR_OPERATION); } else if (r == crr_access_denied) { cprintf("%d You do not have permission to edit '%s'\n", ERROR + HIGHER_ACCESS_REQUIRED, CC->room.QRname); } else if (r != crr_ok) { cprintf("%d Error: CtdlRenameRoom() returned %d\n", ERROR + INTERNAL_ERROR, r); } if (r != crr_ok) { return; } CtdlGetRoom(&CC->room, new_name); /* Now we have to do a bunch of other stuff */ if (num_parms(args) >= 7) { new_order = extract_int(args, 6); if (new_order < 1) new_order = 1; if (new_order > 127) new_order = 127; } CtdlGetRoomLock(&CC->room, CC->room.QRname); /* Directory room */ extract_token(buf, args, 2, '|', sizeof buf); buf[15] = 0; safestrncpy(CC->room.QRdirname, buf, sizeof CC->room.QRdirname); /* Default view */ if (num_parms(args) >= 8) { CC->room.QRdefaultview = extract_int(args, 7); } /* Second set of flags */ if (num_parms(args) >= 9) { CC->room.QRflags2 = extract_int(args, 8); } /* Misc. flags */ CC->room.QRflags = (extract_int(args, 3) | QR_INUSE); /* Clean up a client boo-boo: if the client set the room to * guess-name or passworded, ensure that the private flag is * also set. */ if ((CC->room.QRflags & QR_GUESSNAME) || (CC->room.QRflags & QR_PASSWORDED)) CC->room.QRflags |= QR_PRIVATE; /* Some changes can't apply to BASEROOM */ if (!strncasecmp(CC->room.QRname, CtdlGetConfigStr("c_baseroom"), ROOMNAMELEN)) { CC->room.QRorder = 0; CC->room.QRpasswd[0] = '\0'; CC->room.QRflags &= ~(QR_PRIVATE & QR_PASSWORDED & QR_GUESSNAME & QR_PREFONLY & QR_MAILBOX); CC->room.QRflags |= QR_PERMANENT; } else { /* March order (doesn't apply to AIDEROOM) */ if (num_parms(args) >= 7) CC->room.QRorder = (char) new_order; /* Room password */ extract_token(buf, args, 1, '|', sizeof buf); buf[10] = 0; safestrncpy(CC->room.QRpasswd, buf, sizeof CC->room.QRpasswd); /* Kick everyone out if the client requested it * (by changing the room's generation number) */ if (extract_int(args, 4)) { time(&CC->room.QRgen); } } /* Some changes can't apply to AIDEROOM */ if (!strncasecmp(CC->room.QRname, CtdlGetConfigStr("c_baseroom"), ROOMNAMELEN)) { CC->room.QRorder = 0; CC->room.QRflags &= ~QR_MAILBOX; CC->room.QRflags |= QR_PERMANENT; } /* Write the room record back to disk */ CtdlPutRoomLock(&CC->room); /* Create a room directory if necessary */ if (CC->room.QRflags & QR_DIRECTORY) { snprintf(buf, sizeof buf,"%s/%s", ctdl_file_dir, CC->room.QRdirname); mkdir(buf, 0755); } snprintf(buf, sizeof buf, "The room \"%s\" has been edited by %s.\n", CC->room.QRname, (CC->logged_in ? CC->curr_user : "******") ); CtdlAideMessage(buf, "Room modification Message"); cprintf("%d Ok\n", CIT_OK); }
/* * RDIR command for room directory */ void cmd_rdir(char *cmdbuf) { char buf[256]; char comment[256]; FILE *fd; struct stat statbuf; DIR *filedir = NULL; struct dirent *filedir_entry; int d_namelen; char buf2[SIZ]; char mimebuf[64]; long len; if (CtdlAccessCheck(ac_logged_in)) return; CtdlGetRoom(&CC->room, CC->room.QRname); CtdlGetUser(&CC->user, CC->curr_user); if ((CC->room.QRflags & QR_DIRECTORY) == 0) { cprintf("%d not here.\n", ERROR + NOT_HERE); return; } if (((CC->room.QRflags & QR_VISDIR) == 0) && (CC->user.axlevel < AxAideU) && (CC->user.usernum != CC->room.QRroomaide)) { cprintf("%d not here.\n", ERROR + HIGHER_ACCESS_REQUIRED); return; } snprintf(buf, sizeof buf, "%s/%s", ctdl_file_dir, CC->room.QRdirname); filedir = opendir (buf); if (filedir == NULL) { cprintf("%d not here.\n", ERROR + HIGHER_ACCESS_REQUIRED); return; } cprintf("%d %s|%s/%s\n", LISTING_FOLLOWS, CtdlGetConfigStr("c_fqdn"), ctdl_file_dir, CC->room.QRdirname); snprintf(buf, sizeof buf, "%s/%s/filedir", ctdl_file_dir, CC->room.QRdirname); fd = fopen(buf, "r"); if (fd == NULL) fd = fopen("/dev/null", "r"); while ((filedir_entry = readdir(filedir))) { if (strcasecmp(filedir_entry->d_name, "filedir") && filedir_entry->d_name[0] != '.') { #ifdef _DIRENT_HAVE_D_NAMELEN d_namelen = filedir_entry->d_namlen; #else d_namelen = strlen(filedir_entry->d_name); #endif snprintf(buf, sizeof buf, "%s/%s/%s", ctdl_file_dir, CC->room.QRdirname, filedir_entry->d_name); stat(buf, &statbuf); /* stat the file */ if (!(statbuf.st_mode & S_IFREG)) { snprintf(buf2, sizeof buf2, "\"%s\" appears in the file directory for room \"%s\" but is not a regular file. Directories, named pipes, sockets, etc. are not usable in Citadel room directories.\n", buf, CC->room.QRname ); CtdlAideMessage(buf2, "Unusable data found in room directory"); continue; /* not a useable file type so don't show it */ } safestrncpy(comment, "", sizeof comment); fseek(fd, 0L, 0); /* rewind descriptions file */ /* Get the description from the descriptions file */ while ((fgets(buf, sizeof buf, fd) != NULL) && (IsEmptyStr(comment))) { buf[strlen(buf) - 1] = 0; if ((!strncasecmp(buf, filedir_entry->d_name, d_namelen)) && (buf[d_namelen] == ' ')) safestrncpy(comment, &buf[d_namelen + 1], sizeof comment); } len = extract_token (mimebuf, comment, 0,' ', 64); if ((len <0) || strchr(mimebuf, '/') == NULL) { snprintf (mimebuf, 64, "application/octetstream"); len = 0; } cprintf("%s|%ld|%s|%s\n", filedir_entry->d_name, (long)statbuf.st_size, mimebuf, &comment[len]); } } fclose(fd); closedir(filedir); cprintf("000\n"); }
/* * cmd_goto() - goto a new room */ void cmd_goto(char *gargs) { struct ctdlroom QRscratch; int c; int ok = 0; int ra; char augmented_roomname[ROOMNAMELEN]; char towhere[ROOMNAMELEN]; char password[32]; int transiently = 0; if (CtdlAccessCheck(ac_logged_in_or_guest)) return; extract_token(towhere, gargs, 0, '|', sizeof towhere); extract_token(password, gargs, 1, '|', sizeof password); transiently = extract_int(gargs, 2); CtdlGetUser(&CC->user, CC->curr_user); /* * Handle some of the macro named rooms */ convert_room_name_macros(towhere, sizeof towhere); /* First try a regular match */ c = CtdlGetRoom(&QRscratch, towhere); /* Then try a mailbox name match */ if (c != 0) { CtdlMailboxName(augmented_roomname, sizeof augmented_roomname, &CC->user, towhere); c = CtdlGetRoom(&QRscratch, augmented_roomname); if (c == 0) safestrncpy(towhere, augmented_roomname, sizeof towhere); } /* And if the room was found... */ if (c == 0) { /* Let internal programs go directly to any room. */ if (CC->internal_pgm) { memcpy(&CC->room, &QRscratch, sizeof(struct ctdlroom)); CtdlUserGoto(NULL, 1, transiently, NULL, NULL, NULL, NULL); return; } /* See if there is an existing user/room relationship */ CtdlRoomAccess(&QRscratch, &CC->user, &ra, NULL); /* normal clients have to pass through security */ if (ra & UA_GOTOALLOWED) { ok = 1; } if (ok == 1) { if ((QRscratch.QRflags & QR_MAILBOX) && ((ra & UA_GOTOALLOWED))) { memcpy(&CC->room, &QRscratch, sizeof(struct ctdlroom)); CtdlUserGoto(NULL, 1, transiently, NULL, NULL, NULL, NULL); return; } else if ((QRscratch.QRflags & QR_PASSWORDED) && ((ra & UA_KNOWN) == 0) && (strcasecmp(QRscratch.QRpasswd, password)) && (CC->user.axlevel < AxAideU) ) { cprintf("%d wrong or missing passwd\n", ERROR + PASSWORD_REQUIRED); return; } else if ((QRscratch.QRflags & QR_PRIVATE) && ((QRscratch.QRflags & QR_PASSWORDED) == 0) && ((QRscratch.QRflags & QR_GUESSNAME) == 0) && ((ra & UA_KNOWN) == 0) && (CC->user.axlevel < AxAideU) ) { syslog(LOG_DEBUG, "Failed to acquire private room\n"); } else { memcpy(&CC->room, &QRscratch, sizeof(struct ctdlroom)); CtdlUserGoto(NULL, 1, transiently, NULL, NULL, NULL, NULL); return; } } } cprintf("%d room '%s' not found\n", ERROR + ROOM_NOT_FOUND, towhere); }
/** * Determine all TCP and UDP server sockets listening on physical interfaces */ static bool do_netstat(ietf_attr_port_filter_t *attr) { FILE *file; char buf[BUF_LEN]; chunk_t line, token; int n = 0; bool success = FALSE; const char system_v4[] = "127.0.1.1"; const char loopback_v4[] = "127.0.0.1"; const char loopback_v6[] = "::1"; /* Open a pipe stream for reading the output of the netstat commmand */ file = popen("/bin/netstat -n -l -p -4 -6 --inet", "r"); if (!file) { DBG1(DBG_IMC, "failed to run netstat command"); return FALSE; } /* Read the output a line at a time */ while (fgets(buf, sizeof(buf), file)) { u_char *pos; u_int8_t new_protocol, protocol; u_int16_t new_port, port; int i; enumerator_t *enumerator; bool allowed, found = FALSE; DBG2(DBG_IMC, "%.*s", (int)(strlen(buf)-1), buf); if (n++ < 2) { /* skip the first two header lines */ continue; } line = chunk_create(buf, strlen(buf)); /* Extract the IP protocol type */ if (!extract_token(&token, ' ', &line)) { DBG1(DBG_IMC, "protocol field in netstat output not found"); goto end; } if (match("tcp", &token) || match("tcp6", &token)) { new_protocol = IPPROTO_TCP; } else if (match("udp", &token) || match("udp6", &token)) { new_protocol = IPPROTO_UDP; } else { DBG1(DBG_IMC, "skipped unknown IP protocol in netstat output"); continue; } /* Skip the Recv-Q and Send-Q fields */ for (i = 0; i < 3; i++) { if (!eat_whitespace(&line) || !extract_token(&token, ' ', &line)) { token = chunk_empty; break; } } if (token.len == 0) { DBG1(DBG_IMC, "local address field in netstat output not found"); goto end; } /* Find the local port appended to the local address */ pos = token.ptr + token.len; while (*--pos != ':' && --token.len); if (*pos != ':') { DBG1(DBG_IMC, "local port field in netstat output not found"); goto end; } token.len--; /* ignore ports of IPv4 and IPv6 loopback interfaces and the internal system IPv4 address */ if ((token.len == strlen(system_v4) && memeq(system_v4, token.ptr, token.len)) || (token.len == strlen(loopback_v4) && memeq(loopback_v4, token.ptr, token.len)) || (token.len == strlen(loopback_v6) && memeq(loopback_v6, token.ptr, token.len))) { continue; } /* convert the port string to an integer */ new_port = atoi(pos+1); /* check if the there is already a port entry */ enumerator = attr->create_port_enumerator(attr); while (enumerator->enumerate(enumerator, &allowed, &protocol, &port)) { if (new_port == port && new_protocol == protocol) { found = TRUE; } } enumerator->destroy(enumerator); /* Skip the duplicate port entry */ if (found) { continue; } /* Add new port entry */ attr->add_port(attr, FALSE, new_protocol, new_port); } /* Successfully completed the parsing of the netstat output */ success = TRUE; end: /* Close the pipe stream */ pclose(file); return success; }
int SLcmd_execute_string (char *str, SLcmd_Cmd_Table_Type *table) { char *s, *arg_type, *last_str, *cmd_name; SLcmd_Cmd_Type *cmd; char *buf; int token_present; int i; int status; unsigned int len; int argc; unsigned int space; table->argc = 0; table->string_args = NULL; table->int_args = NULL; table->double_args = NULL; table->arg_type = NULL; buf = SLmake_string (str); if (buf == NULL) return -1; status = extract_token (&str, buf); if (status <= 0) { SLfree (buf); return status; } if (((len = strlen (buf)) >= 32) || (NULL == (cmd = SLcmd_find_command (buf, table->table)))) { SLang_verror (SL_UNDEFINED_NAME,"%s: invalid command", buf); SLfree (buf); return -1; } if (NULL == (cmd_name = SLmake_string (buf))) { SLfree (buf); return -1; } space = 0; argc = 0; if (-1 == allocate_arg_space (table, argc, &space)) { SLfree (buf); return -1; } table->arg_type[argc] = SLANG_STRING_TYPE; table->string_args[argc++] = cmd_name; arg_type = cmd->arg_type; status = -1; while (*arg_type) { int guess_type = 0; last_str = str; if (-1 == allocate_arg_space (table, argc, &space)) goto error; if (-1 == (token_present = extract_token (&str, buf))) goto error; table->string_args[argc] = NULL; if (token_present) { char *b = buf; len = strlen (b); if ((*b == '"') && (len > 1)) { b++; len -= 2; b[len] = 0; guess_type = SLANG_STRING_TYPE; SLexpand_escaped_string (buf, b, b + len); len = strlen (buf); } else if ((*b == '\'') && (len > 1)) { char ch; b++; len -= 2; b[len] = 0; guess_type = SLANG_INT_TYPE; ch = *b; if (ch == '\\') (void) _SLexpand_escaped_char (b, &ch); sprintf (buf, "%d", (unsigned char) ch); len = strlen (buf); } else guess_type = SLang_guess_type (buf); } switch (*arg_type++) { /* variable argument number */ case 'v': if (token_present == 0) break; case 'V': if (token_present == 0) { SLang_verror (SL_INVALID_PARM, "%s: Expecting argument", cmd_name); goto error; } while (*last_str == ' ') last_str++; len = strlen (last_str); str = last_str + len; s = SLmake_nstring (last_str, len); if (s == NULL) goto error; table->arg_type[argc] = SLANG_STRING_TYPE; table->string_args[argc++] = s; break; case 's': if (token_present == 0) break; case 'S': if (token_present == 0) { SLang_verror (SL_TYPE_MISMATCH, "%s: Expecting string argument", cmd_name); goto error; } s = SLmake_nstring (buf, len); if (s == NULL) goto error; table->arg_type[argc] = SLANG_STRING_TYPE; table->string_args[argc++] = s; break; /* integer argument */ case 'i': if (token_present == 0) break; case 'I': if ((token_present == 0) || (SLANG_INT_TYPE != guess_type)) { SLang_verror (SL_TYPE_MISMATCH, "%s: Expecting integer argument", cmd_name); goto error; } table->arg_type[argc] = SLANG_INT_TYPE; table->int_args[argc++] = SLatoi((unsigned char *) buf); break; /* floating point arg */ #if SLANG_HAS_FLOAT case 'f': if (token_present == 0) break; case 'F': if ((token_present == 0) || (SLANG_STRING_TYPE == guess_type)) { SLang_verror (SL_TYPE_MISMATCH, "%s: Expecting double argument", cmd_name); goto error; } table->arg_type[argc] = SLANG_DOUBLE_TYPE; table->double_args[argc++] = atof(buf); break; #endif /* Generic type */ case 'g': if (token_present == 0) break; case 'G': if (token_present == 0) { SLang_verror (SL_TYPE_MISMATCH, "%s: Expecting argument", cmd_name); goto error; } switch (guess_type) { case SLANG_INT_TYPE: table->arg_type[argc] = SLANG_INT_TYPE; table->int_args[argc++] = SLatoi((unsigned char *) buf); break; case SLANG_STRING_TYPE: s = SLmake_nstring (buf, len); if (s == NULL) goto error; table->arg_type[argc] = SLANG_STRING_TYPE; table->string_args[argc++] = s; break; #if SLANG_HAS_FLOAT case SLANG_DOUBLE_TYPE: table->arg_type[argc] = SLANG_DOUBLE_TYPE; table->double_args[argc++] = atof(buf); #endif } break; } } /* call function */ status = (*cmd->cmdfun)(argc, table); error: if (table->string_args != NULL) for (i = 0; i < argc; i++) { if (NULL != table->string_args[i]) { SLfree (table->string_args[i]); table->string_args[i] = NULL; } } SLfree ((char *)table->string_args); table->string_args = NULL; SLfree ((char *)table->double_args); table->double_args = NULL; SLfree ((char *)table->int_args); table->int_args = NULL; SLfree ((char *)table->arg_type); table->arg_type = NULL; SLfree (buf); return status; }
/* * smtp_do_bounce() is caled by smtp_do_procmsg() to scan a set of delivery * instructions for "5" codes (permanent fatal errors) and produce/deliver * a "bounce" message (delivery status notification). */ void smtp_do_bounce(char *instr, StrBuf *OMsgTxt) { int i; int lines; int status; char buf[1024]; char key[1024]; char addr[1024]; char dsn[1024]; char bounceto[1024]; StrBuf *boundary; int num_bounces = 0; int bounce_this = 0; time_t submitted = 0L; struct CtdlMessage *bmsg = NULL; int give_up = 0; recptypes *valid; int successful_bounce = 0; static int seq = 0; StrBuf *BounceMB; long omsgid = (-1); syslog(LOG_DEBUG, "smtp_do_bounce() called\n"); strcpy(bounceto, ""); boundary = NewStrBufPlain(HKEY("=_Citadel_Multipart_")); StrBufAppendPrintf(boundary, "%s_%04x%04x", CtdlGetConfigStr("c_fqdn"), getpid(), ++seq); lines = num_tokens(instr, '\n'); /* See if it's time to give up on delivery of this message */ for (i=0; i<lines; ++i) { extract_token(buf, instr, i, '\n', sizeof buf); extract_token(key, buf, 0, '|', sizeof key); extract_token(addr, buf, 1, '|', sizeof addr); if (!strcasecmp(key, "submitted")) { submitted = atol(addr); } } if ( (time(NULL) - submitted) > SMTP_GIVE_UP ) { give_up = 1; } /* Start building our bounce message */ bmsg = (struct CtdlMessage *) malloc(sizeof(struct CtdlMessage)); if (bmsg == NULL) return; memset(bmsg, 0, sizeof(struct CtdlMessage)); BounceMB = NewStrBufPlain(NULL, 1024); bmsg->cm_magic = CTDLMESSAGE_MAGIC; bmsg->cm_anon_type = MES_NORMAL; bmsg->cm_format_type = FMT_RFC822; CM_SetField(bmsg, eAuthor, HKEY("Citadel")); CM_SetField(bmsg, eOriginalRoom, HKEY(MAILROOM)); CM_SetField(bmsg, eNodeName, CtdlGetConfigStr("c_nodename"), strlen(CtdlGetConfigStr("c_nodename"))); CM_SetField(bmsg, eMsgSubject, HKEY("Delivery Status Notification (Failure)")); StrBufAppendBufPlain(BounceMB, HKEY("Content-type: multipart/mixed; boundary=\""), 0); StrBufAppendBuf(BounceMB, boundary, 0); StrBufAppendBufPlain(BounceMB, HKEY("\"\r\n"), 0); StrBufAppendBufPlain(BounceMB, HKEY("MIME-Version: 1.0\r\n"), 0); StrBufAppendBufPlain(BounceMB, HKEY("X-Mailer: " CITADEL "\r\n"), 0); StrBufAppendBufPlain( BounceMB, HKEY("\r\nThis is a multipart message in MIME format." "\r\n\r\n"), 0); StrBufAppendBufPlain(BounceMB, HKEY("--"), 0); StrBufAppendBuf(BounceMB, boundary, 0); StrBufAppendBufPlain(BounceMB, HKEY("\r\n"), 0); StrBufAppendBufPlain(BounceMB, HKEY("Content-type: text/plain\r\n\r\n"), 0); if (give_up) { StrBufAppendBufPlain( BounceMB, HKEY("A message you sent could not be delivered " "to some or all of its recipients\ndue to " "prolonged unavailability of its destination(s).\n" "Giving up on the following addresses:\n\n"), 0); } else { StrBufAppendBufPlain( BounceMB, HKEY("A message you sent could not be delivered " "to some or all of its recipients.\n" "The following addresses were undeliverable:\n\n" ), 0); } /* * Now go through the instructions checking for stuff. */ for (i=0; i<lines; ++i) { long addrlen; long dsnlen; extract_token(buf, instr, i, '\n', sizeof buf); extract_token(key, buf, 0, '|', sizeof key); addrlen = extract_token(addr, buf, 1, '|', sizeof addr); status = extract_int(buf, 2); dsnlen = extract_token(dsn, buf, 3, '|', sizeof dsn); bounce_this = 0; syslog(LOG_DEBUG, "key=<%s> addr=<%s> status=%d dsn=<%s>\n", key, addr, status, dsn); if (!strcasecmp(key, "bounceto")) { strcpy(bounceto, addr); } if (!strcasecmp(key, "msgid")) { omsgid = atol(addr); } if (!strcasecmp(key, "remote")) { if (status == 5) bounce_this = 1; if (give_up) bounce_this = 1; } if (bounce_this) { ++num_bounces; StrBufAppendBufPlain(BounceMB, addr, addrlen, 0); StrBufAppendBufPlain(BounceMB, HKEY(": "), 0); StrBufAppendBufPlain(BounceMB, dsn, dsnlen, 0); StrBufAppendBufPlain(BounceMB, HKEY("\r\n"), 0); remove_token(instr, i, '\n'); --i; --lines; } } /* Attach the original message */ if (omsgid >= 0) { StrBufAppendBufPlain(BounceMB, HKEY("--"), 0); StrBufAppendBuf(BounceMB, boundary, 0); StrBufAppendBufPlain(BounceMB, HKEY("\r\n"), 0); StrBufAppendBufPlain( BounceMB, HKEY("Content-type: message/rfc822\r\n"), 0); StrBufAppendBufPlain( BounceMB, HKEY("Content-Transfer-Encoding: 7bit\r\n"), 0); StrBufAppendBufPlain( BounceMB, HKEY("Content-Disposition: inline\r\n"), 0); StrBufAppendBufPlain(BounceMB, HKEY("\r\n"), 0); if (OMsgTxt == NULL) { CC->redirect_buffer = NewStrBufPlain(NULL, SIZ); CtdlOutputMsg(omsgid, MT_RFC822, HEADERS_ALL, 0, 1, NULL, 0, NULL, NULL, NULL); StrBufAppendBuf(BounceMB, CC->redirect_buffer, 0); FreeStrBuf(&CC->redirect_buffer); } else { StrBufAppendBuf(BounceMB, OMsgTxt, 0); } } /* Close the multipart MIME scope */ StrBufAppendBufPlain(BounceMB, HKEY("--"), 0); StrBufAppendBuf(BounceMB, boundary, 0); StrBufAppendBufPlain(BounceMB, HKEY("--\r\n"), 0); CM_SetAsFieldSB(bmsg, eMesageText, &BounceMB); /* Deliver the bounce if there's anything worth mentioning */ syslog(LOG_DEBUG, "num_bounces = %d\n", num_bounces); if (num_bounces > 0) { /* First try the user who sent the message */ if (IsEmptyStr(bounceto)) syslog(LOG_ERR, "No bounce address specified\n"); else syslog(LOG_DEBUG, "bounce to user <%s>\n", bounceto); /* Can we deliver the bounce to the original sender? */ valid = validate_recipients(bounceto, smtp_get_Recipients (), 0); if (valid != NULL) { if (valid->num_error == 0) { CtdlSubmitMsg(bmsg, valid, "", QP_EADDR); successful_bounce = 1; } } /* If not, post it in the Aide> room */ if (successful_bounce == 0) { CtdlSubmitMsg(bmsg, NULL, CtdlGetConfigStr("c_aideroom"), QP_EADDR); } /* Free up the memory we used */ if (valid != NULL) { free_recipients(valid); } } FreeStrBuf(&boundary); CM_Free(bmsg); syslog(LOG_DEBUG, "Done processing bounces\n"); }
/* * Get or set global configuration options * * IF YOU ADD OR CHANGE FIELDS HERE, YOU *MUST* DOCUMENT YOUR CHANGES AT: * http://www.citadel.org/doku.php?id=documentation:applicationprotocol * */ void cmd_conf(char *argbuf) { char cmd[16]; char buf[256]; int a; char *confptr; char confname[128]; if (CtdlAccessCheck(ac_aide)) return; extract_token(cmd, argbuf, 0, '|', sizeof cmd); if (!strcasecmp(cmd, "GET")) { cprintf("%d Configuration...\n", LISTING_FOLLOWS); cprintf("%s\n", config.c_nodename); cprintf("%s\n", config.c_fqdn); cprintf("%s\n", config.c_humannode); cprintf("%s\n", config.c_phonenum); cprintf("%d\n", config.c_creataide); cprintf("%d\n", config.c_sleeping); cprintf("%d\n", config.c_initax); cprintf("%d\n", config.c_regiscall); cprintf("%d\n", config.c_twitdetect); cprintf("%s\n", config.c_twitroom); cprintf("%s\n", config.c_moreprompt); cprintf("%d\n", config.c_restrict); cprintf("%s\n", config.c_site_location); cprintf("%s\n", config.c_sysadm); cprintf("%d\n", config.c_maxsessions); cprintf("xxx\n"); /* placeholder -- field no longer in use */ cprintf("%d\n", config.c_userpurge); cprintf("%d\n", config.c_roompurge); cprintf("%s\n", config.c_logpages); cprintf("%d\n", config.c_createax); cprintf("%ld\n", config.c_maxmsglen); cprintf("%d\n", config.c_min_workers); cprintf("%d\n", config.c_max_workers); cprintf("%d\n", config.c_pop3_port); cprintf("%d\n", config.c_smtp_port); cprintf("%d\n", config.c_rfc822_strict_from); cprintf("%d\n", config.c_aide_zap); cprintf("%d\n", config.c_imap_port); cprintf("%ld\n", config.c_net_freq); cprintf("%d\n", config.c_disable_newu); cprintf("1\n"); /* niu */ cprintf("%d\n", config.c_purge_hour); #ifdef HAVE_LDAP cprintf("%s\n", config.c_ldap_host); cprintf("%d\n", config.c_ldap_port); cprintf("%s\n", config.c_ldap_base_dn); cprintf("%s\n", config.c_ldap_bind_dn); cprintf("%s\n", config.c_ldap_bind_pw); #else cprintf("\n"); cprintf("0\n"); cprintf("\n"); cprintf("\n"); cprintf("\n"); #endif cprintf("%s\n", config.c_ip_addr); cprintf("%d\n", config.c_msa_port); cprintf("%d\n", config.c_imaps_port); cprintf("%d\n", config.c_pop3s_port); cprintf("%d\n", config.c_smtps_port); cprintf("%d\n", config.c_enable_fulltext); cprintf("%d\n", config.c_auto_cull); cprintf("1\n"); cprintf("%d\n", config.c_allow_spoofing); cprintf("%d\n", config.c_journal_email); cprintf("%d\n", config.c_journal_pubmsgs); cprintf("%s\n", config.c_journal_dest); cprintf("%s\n", config.c_default_cal_zone); cprintf("%d\n", config.c_pftcpdict_port); cprintf("%d\n", config.c_managesieve_port); cprintf("%d\n", config.c_auth_mode); cprintf("%s\n", config.c_funambol_host); cprintf("%d\n", config.c_funambol_port); cprintf("%s\n", config.c_funambol_source); cprintf("%s\n", config.c_funambol_auth); cprintf("%d\n", config.c_rbl_at_greeting); cprintf("%s\n", config.c_master_user); cprintf("%s\n", config.c_master_pass); cprintf("%s\n", config.c_pager_program); cprintf("%d\n", config.c_imap_keep_from); cprintf("%d\n", config.c_xmpp_c2s_port); cprintf("%d\n", config.c_xmpp_s2s_port); cprintf("%ld\n", config.c_pop3_fetch); cprintf("%ld\n", config.c_pop3_fastest); cprintf("%d\n", config.c_spam_flag_only); cprintf("%d\n", config.c_guest_logins); cprintf("%d\n", config.c_port_number); cprintf("%d\n", config.c_ctdluid); cprintf("%d\n", config.c_nntp_port); cprintf("%d\n", config.c_nntps_port); cprintf("000\n"); } else if (!strcasecmp(cmd, "SET")) { unbuffer_output(); cprintf("%d Send configuration...\n", SEND_LISTING); a = 0; while (client_getln(buf, sizeof buf) >= 0 && strcmp(buf, "000")) { switch (a) { case 0: configlen.c_nodename = safestrncpy(config.c_nodename, buf, sizeof config.c_nodename); break; case 1: configlen.c_fqdn = safestrncpy(config.c_fqdn, buf, sizeof config.c_fqdn); break; case 2: configlen.c_humannode = safestrncpy(config.c_humannode, buf, sizeof config.c_humannode); break; case 3: configlen.c_phonenum = safestrncpy(config.c_phonenum, buf, sizeof config.c_phonenum); break; case 4: config.c_creataide = atoi(buf); break; case 5: config.c_sleeping = atoi(buf); break; case 6: config.c_initax = atoi(buf); if (config.c_initax < 1) config.c_initax = 1; if (config.c_initax > 6) config.c_initax = 6; break; case 7: config.c_regiscall = atoi(buf); if (config.c_regiscall != 0) config.c_regiscall = 1; break; case 8: config.c_twitdetect = atoi(buf); if (config.c_twitdetect != 0) config.c_twitdetect = 1; break; case 9: configlen.c_twitroom = safestrncpy(config.c_twitroom, buf, sizeof config.c_twitroom); break; case 10: configlen.c_moreprompt = safestrncpy(config.c_moreprompt, buf, sizeof config.c_moreprompt); break; case 11: config.c_restrict = atoi(buf); if (config.c_restrict != 0) config.c_restrict = 1; break; case 12: configlen.c_site_location = safestrncpy( config.c_site_location, buf, sizeof config.c_site_location); break; case 13: configlen.c_sysadm = safestrncpy(config.c_sysadm, buf, sizeof config.c_sysadm); break; case 14: config.c_maxsessions = atoi(buf); if (config.c_maxsessions < 0) config.c_maxsessions = 0; break; case 15: /* placeholder -- field no longer in use */ break; case 16: config.c_userpurge = atoi(buf); break; case 17: config.c_roompurge = atoi(buf); break; case 18: configlen.c_logpages = safestrncpy(config.c_logpages, buf, sizeof config.c_logpages); break; case 19: config.c_createax = atoi(buf); if (config.c_createax < 1) config.c_createax = 1; if (config.c_createax > 6) config.c_createax = 6; break; case 20: if (atoi(buf) >= 8192) config.c_maxmsglen = atoi(buf); break; case 21: if (atoi(buf) >= 2) config.c_min_workers = atoi(buf); case 22: if (atoi(buf) >= config.c_min_workers) config.c_max_workers = atoi(buf); case 23: config.c_pop3_port = atoi(buf); break; case 24: config.c_smtp_port = atoi(buf); break; case 25: config.c_rfc822_strict_from = atoi(buf); break; case 26: config.c_aide_zap = atoi(buf); if (config.c_aide_zap != 0) config.c_aide_zap = 1; break; case 27: config.c_imap_port = atoi(buf); break; case 28: config.c_net_freq = atol(buf); break; case 29: config.c_disable_newu = atoi(buf); if (config.c_disable_newu != 0) config.c_disable_newu = 1; break; case 30: /* niu */ break; case 31: if ((config.c_purge_hour >= 0) && (config.c_purge_hour <= 23)) { config.c_purge_hour = atoi(buf); } break; #ifdef HAVE_LDAP case 32: configlen.c_ldap_host = safestrncpy(config.c_ldap_host, buf, sizeof config.c_ldap_host); break; case 33: config.c_ldap_port = atoi(buf); break; case 34: configlen.c_ldap_base_dn = safestrncpy(config.c_ldap_base_dn, buf, sizeof config.c_ldap_base_dn); break; case 35: configlen.c_ldap_bind_dn = safestrncpy(config.c_ldap_bind_dn, buf, sizeof config.c_ldap_bind_dn); break; case 36: configlen.c_ldap_bind_pw = safestrncpy(config.c_ldap_bind_pw, buf, sizeof config.c_ldap_bind_pw); break; #endif case 37: configlen.c_ip_addr = safestrncpy(config.c_ip_addr, buf, sizeof config.c_ip_addr); case 38: config.c_msa_port = atoi(buf); break; case 39: config.c_imaps_port = atoi(buf); break; case 40: config.c_pop3s_port = atoi(buf); break; case 41: config.c_smtps_port = atoi(buf); break; case 42: config.c_enable_fulltext = atoi(buf); break; case 43: config.c_auto_cull = atoi(buf); break; case 44: /* niu */ break; case 45: config.c_allow_spoofing = atoi(buf); break; case 46: config.c_journal_email = atoi(buf); break; case 47: config.c_journal_pubmsgs = atoi(buf); break; case 48: configlen.c_journal_dest = safestrncpy(config.c_journal_dest, buf, sizeof config.c_journal_dest); case 49: configlen.c_default_cal_zone = safestrncpy( config.c_default_cal_zone, buf, sizeof config.c_default_cal_zone); break; case 50: config.c_pftcpdict_port = atoi(buf); break; case 51: config.c_managesieve_port = atoi(buf); break; case 52: config.c_auth_mode = atoi(buf); case 53: configlen.c_funambol_host = safestrncpy( config.c_funambol_host, buf, sizeof config.c_funambol_host); break; case 54: config.c_funambol_port = atoi(buf); break; case 55: configlen.c_funambol_source = safestrncpy( config.c_funambol_source, buf, sizeof config.c_funambol_source); break; case 56: configlen.c_funambol_auth = safestrncpy( config.c_funambol_auth, buf, sizeof config.c_funambol_auth); break; case 57: config.c_rbl_at_greeting = atoi(buf); break; case 58: configlen.c_master_user = safestrncpy( config.c_master_user, buf, sizeof config.c_master_user); break; case 59: configlen.c_master_pass = safestrncpy( config.c_master_pass, buf, sizeof config.c_master_pass); break; case 60: configlen.c_pager_program = safestrncpy( config.c_pager_program, buf, sizeof config.c_pager_program); break; case 61: config.c_imap_keep_from = atoi(buf); break; case 62: config.c_xmpp_c2s_port = atoi(buf); break; case 63: config.c_xmpp_s2s_port = atoi(buf); break; case 64: config.c_pop3_fetch = atol(buf); break; case 65: config.c_pop3_fastest = atol(buf); break; case 66: config.c_spam_flag_only = atoi(buf); break; case 67: config.c_guest_logins = atoi(buf); break; case 68: config.c_port_number = atoi(buf); break; case 69: config.c_ctdluid = atoi(buf); break; case 70: config.c_nntp_port = atoi(buf); break; case 71: config.c_nntps_port = atoi(buf); break; } ++a; } put_config(); snprintf(buf, sizeof buf, "The global system configuration has been edited by %s.\n", (CC->logged_in ? CC->curr_user : "******") ); CtdlAideMessage(buf,"Citadel Configuration Manager Message"); if (!IsEmptyStr(config.c_logpages)) CtdlCreateRoom(config.c_logpages, 3, "", 0, 1, 1, VIEW_BBS); /* If full text indexing has been disabled, invalidate the * index so it doesn't try to use it later. */ if (config.c_enable_fulltext == 0) { CitControl.fulltext_wordbreaker = 0; put_control(); } } else if (!strcasecmp(cmd, "GETSYS")) { extract_token(confname, argbuf, 1, '|', sizeof confname); confptr = CtdlGetSysConfig(confname); if (confptr != NULL) { long len; len = strlen(confptr); cprintf("%d %s\n", LISTING_FOLLOWS, confname); client_write(confptr, len); if ((len > 0) && (confptr[len - 1] != 10)) client_write("\n", 1); cprintf("000\n"); free(confptr); } else { cprintf("%d No such configuration.\n", ERROR + ILLEGAL_VALUE); } } else if (!strcasecmp(cmd, "PUTSYS")) { extract_token(confname, argbuf, 1, '|', sizeof confname); unbuffer_output(); cprintf("%d %s\n", SEND_LISTING, confname); confptr = CtdlReadMessageBody(HKEY("000"), config.c_maxmsglen, NULL, 0, 0); CtdlPutSysConfig(confname, confptr); free(confptr); } else { cprintf("%d Illegal option(s) specified.\n", ERROR + ILLEGAL_VALUE); } }
/* * Fetch a message from the server and extract a vNote from it */ struct vnote *vnote_new_from_msg(long msgnum,int unread) { StrBuf *Buf; StrBuf *Data = NULL; const char *bptr; int Done = 0; char uid_from_headers[256]; char mime_partnum[256]; char mime_filename[256]; char mime_content_type[256]; char mime_disposition[256]; char relevant_partnum[256]; int phase = 0; /* 0 = citadel headers, 1 = mime headers, 2 = body */ char msg4_content_type[256] = ""; char msg4_content_encoding[256] = ""; int msg4_content_length = 0; struct vnote *vnote_from_body = NULL; int vnote_inline = 0; /* 1 = MSG4 gave us a text/x-vnote top level */ relevant_partnum[0] = '\0'; serv_printf("MSG4 %ld", msgnum); /* we need the mime headers */ Buf = NewStrBuf(); StrBuf_ServGetln(Buf); if (GetServerStatus(Buf, NULL) != 1) { FreeStrBuf (&Buf); return NULL; } while ((StrBuf_ServGetln(Buf)>=0) && !Done) { if ( (StrLength(Buf)==3) && !strcmp(ChrPtr(Buf), "000")) { Done = 1; break; } bptr = ChrPtr(Buf); switch (phase) { case 0: if (!strncasecmp(bptr, "exti=", 5)) { safestrncpy(uid_from_headers, &(ChrPtr(Buf)[5]), sizeof uid_from_headers); } else if (!strncasecmp(bptr, "part=", 5)) { extract_token(mime_filename, &bptr[5], 1, '|', sizeof mime_filename); extract_token(mime_partnum, &bptr[5], 2, '|', sizeof mime_partnum); extract_token(mime_disposition, &bptr[5], 3, '|', sizeof mime_disposition); extract_token(mime_content_type, &bptr[5], 4, '|', sizeof mime_content_type); if (!strcasecmp(mime_content_type, "text/vnote")) { strcpy(relevant_partnum, mime_partnum); } } else if ((phase == 0) && (!strncasecmp(bptr, "text", 4))) { phase = 1; } break; case 1: if (!IsEmptyStr(bptr)) { if (!strncasecmp(bptr, "Content-type: ", 14)) { safestrncpy(msg4_content_type, &bptr[14], sizeof msg4_content_type); striplt(msg4_content_type); } else if (!strncasecmp(bptr, "Content-transfer-encoding: ", 27)) { safestrncpy(msg4_content_encoding, &bptr[27], sizeof msg4_content_encoding); striplt(msg4_content_type); } else if ((!strncasecmp(bptr, "Content-length: ", 16))) { msg4_content_length = atoi(&bptr[16]); } break; } else { phase++; if ((msg4_content_length > 0) && ( !strcasecmp(msg4_content_encoding, "7bit")) && (!strcasecmp(msg4_content_type, "text/vnote")) ) { vnote_inline = 1; } } case 2: if (vnote_inline) { Data = NewStrBufPlain(NULL, msg4_content_length * 2); if (msg4_content_length > 0) { StrBuf_ServGetBLOBBuffered(Data, msg4_content_length); phase ++; } else { StrBufAppendBuf(Data, Buf, 0); StrBufAppendBufPlain(Data, "\r\n", 1, 0); } } case 3: if (vnote_inline) { StrBufAppendBuf(Data, Buf, 0); } } } FreeStrBuf(&Buf); /* If MSG4 didn't give us the part we wanted, but we know that we can find it * as one of the other MIME parts, attempt to load it now. */ if ((!vnote_inline) && (!IsEmptyStr(relevant_partnum))) { Data = load_mimepart(msgnum, relevant_partnum); } if (StrLength(Data) > 0) { if (IsEmptyStr(uid_from_headers)) { /* Convert an old-style note to a vNote */ vnote_from_body = vnote_new(); vnote_from_body->uid = strdup(uid_from_headers); vnote_from_body->color_red = pastel_palette[3][0]; vnote_from_body->color_green = pastel_palette[3][1]; vnote_from_body->color_blue = pastel_palette[3][2]; vnote_from_body->body = malloc(StrLength(Data) + 1); vnote_from_body->body[0] = 0; memcpy(vnote_from_body->body, ChrPtr(Data), StrLength(Data) + 1); FreeStrBuf(&Data); return vnote_from_body; } else { char *Buf = SmashStrBuf(&Data); struct vnote *v = vnote_new_from_str(Buf); free(Buf); return(v); } } return NULL; }
// // The LAST and NEXT commands are so similar that they are handled by a single function. // void nntp_last_next(const char *cmd) { if (CtdlAccessCheck(ac_logged_in_or_guest)) return; citnntp *nntpstate = (citnntp *) CC->session_specific_data; char which_command[16]; int acmd = 0; // We're going to store one of these values in the variable 'acmd' so that // we can quickly check later which version of the output we want. enum { NNTP_LAST, NNTP_NEXT }; extract_token(which_command, cmd, 0, ' ', sizeof which_command); if (!strcasecmp(which_command, "last")) { acmd = NNTP_LAST; } else if (!strcasecmp(which_command, "next")) { acmd = NNTP_NEXT; } else { cprintf("500 I'm afraid I can't do that.\r\n"); return; } // ok, here we go ... fetch the msglist so we can figure out our place in the universe struct nntp_msglist nm; int i = 0; long selected_msgnum = 0; char *message_id = NULL; nm = nntp_fetch_msglist(&CC->room); if ((nm.num_msgs < 0) || (nm.msgnums == NULL)) { cprintf("500 something bad happened\r\n"); return; } if ( (acmd == NNTP_LAST) && (nm.num_msgs == 0) ) { cprintf("422 no previous article in this group\r\n"); // nothing here } else if ( (acmd == NNTP_LAST) && (nntpstate->current_article_number <= nm.msgnums[0]) ) { cprintf("422 no previous article in this group\r\n"); // already at the beginning } else if (acmd == NNTP_LAST) { for (i=0; ((i<nm.num_msgs)&&(selected_msgnum<=0)); ++i) { if ( (nm.msgnums[i] >= nntpstate->current_article_number) && (i > 0) ) { selected_msgnum = nm.msgnums[i-1]; } } if (selected_msgnum > 0) { nntpstate->current_article_number = selected_msgnum; message_id = message_id_from_msgnum(nntpstate->current_article_number); cprintf("223 %ld <%s>\r\n", nntpstate->current_article_number, message_id); if (message_id) free(message_id); } else { cprintf("422 no previous article in this group\r\n"); } } else if ( (acmd == NNTP_NEXT) && (nm.num_msgs == 0) ) { cprintf("421 no next article in this group\r\n"); // nothing here } else if ( (acmd == NNTP_NEXT) && (nntpstate->current_article_number >= nm.msgnums[nm.num_msgs-1]) ) { cprintf("421 no next article in this group\r\n"); // already at the end } else if (acmd == NNTP_NEXT) { for (i=0; ((i<nm.num_msgs)&&(selected_msgnum<=0)); ++i) { if (nm.msgnums[i] > nntpstate->current_article_number) { selected_msgnum = nm.msgnums[i]; } } if (selected_msgnum > 0) { nntpstate->current_article_number = selected_msgnum; message_id = message_id_from_msgnum(nntpstate->current_article_number); cprintf("223 %ld <%s>\r\n", nntpstate->current_article_number, message_id); if (message_id) free(message_id); } else { cprintf("421 no next article in this group\r\n"); } } // should never get here else { cprintf("500 internal error\r\n"); } if (nm.msgnums != NULL) { free(nm.msgnums); } }
/* * Called by JournalRunQueue() to send an individual message. */ void JournalRunQueueMsg(struct jnlq *jmsg) { struct CtdlMessage *journal_msg = NULL; recptypes *journal_recps = NULL; StrBuf *message_text = NULL; char mime_boundary[256]; long mblen; long rfc822len; char recipient[256]; char inetemail[256]; static int seq = 0; int i; if (jmsg == NULL) return; journal_recps = validate_recipients(config.c_journal_dest, NULL, 0); if (journal_recps != NULL) { if ( (journal_recps->num_local > 0) || (journal_recps->num_internet > 0) || (journal_recps->num_ignet > 0) || (journal_recps->num_room > 0) ) { /* * Construct journal message. * Note that we are transferring ownership of some of the memory here. */ journal_msg = malloc(sizeof(struct CtdlMessage)); memset(journal_msg, 0, sizeof(struct CtdlMessage)); journal_msg->cm_magic = CTDLMESSAGE_MAGIC; journal_msg->cm_anon_type = MES_NORMAL; journal_msg->cm_format_type = FMT_RFC822; CM_SetField(journal_msg, eJournal, HKEY("is journal")); CM_SetField(journal_msg, eAuthor, jmsg->from, strlen(jmsg->from)); CM_SetField(journal_msg, eNodeName, jmsg->node, strlen(jmsg->node)); CM_SetField(journal_msg, erFc822Addr, jmsg->rfca, strlen(jmsg->rfca)); CM_SetField(journal_msg, eMsgSubject, jmsg->subj, strlen(jmsg->subj)); mblen = snprintf(mime_boundary, sizeof(mime_boundary), "--Citadel-Journal-%08lx-%04x--", time(NULL), ++seq); rfc822len = strlen(jmsg->rfc822); message_text = NewStrBufPlain(NULL, rfc822len + sizeof(recptypes) + 1024); /* * Here is where we begin to compose the journalized message. * NOTE: the superfluous "Content-Identifer: ExJournalReport" header was * requested by a paying customer, and yes, it is intentionally * spelled wrong. Do NOT remove or change it. */ StrBufAppendBufPlain( message_text, HKEY("Content-type: multipart/mixed; boundary=\""), 0); StrBufAppendBufPlain(message_text, mime_boundary, mblen, 0); StrBufAppendBufPlain( message_text, HKEY("\"\r\n" "Content-Identifer: ExJournalReport\r\n" "MIME-Version: 1.0\r\n" "\n" "--"), 0); StrBufAppendBufPlain(message_text, mime_boundary, mblen, 0); StrBufAppendBufPlain( message_text, HKEY("\r\n" "Content-type: text/plain\r\n" "\r\n" "Sender: "), 0); if (CM_IsEmpty(journal_msg, eAuthor)) StrBufAppendBufPlain( message_text, journal_msg->cm_fields[eAuthor], -1, 0); else StrBufAppendBufPlain( message_text, HKEY("(null)"), 0); if (!CM_IsEmpty(journal_msg, erFc822Addr)) { StrBufAppendPrintf(message_text, " <%s>", journal_msg->cm_fields[erFc822Addr]); } else if (!CM_IsEmpty(journal_msg, eNodeName)) { StrBufAppendPrintf(message_text, " @ %s", journal_msg->cm_fields[eNodeName]); } else StrBufAppendBufPlain( message_text, HKEY(" "), 0); StrBufAppendBufPlain( message_text, HKEY("\r\n" "Message-ID: <"), 0); StrBufAppendBufPlain(message_text, jmsg->msgn, -1, 0); StrBufAppendBufPlain( message_text, HKEY(">\r\n" "Recipients:\r\n"), 0); if (jmsg->recps.num_local > 0) { for (i=0; i<jmsg->recps.num_local; ++i) { extract_token(recipient, jmsg->recps.recp_local, i, '|', sizeof recipient); local_to_inetemail(inetemail, recipient, sizeof inetemail); StrBufAppendPrintf(message_text, " %s <%s>\r\n", recipient, inetemail); } } if (jmsg->recps.num_ignet > 0) { for (i=0; i<jmsg->recps.num_ignet; ++i) { extract_token(recipient, jmsg->recps.recp_ignet, i, '|', sizeof recipient); StrBufAppendPrintf(message_text, " %s\r\n", recipient); } } if (jmsg->recps.num_internet > 0) { for (i=0; i<jmsg->recps.num_internet; ++i) { extract_token(recipient, jmsg->recps.recp_internet, i, '|', sizeof recipient); StrBufAppendPrintf(message_text, " %s\r\n", recipient); } } StrBufAppendBufPlain( message_text, HKEY("\r\n" "--"), 0); StrBufAppendBufPlain(message_text, mime_boundary, mblen, 0); StrBufAppendBufPlain( message_text, HKEY("\r\n" "Content-type: message/rfc822\r\n" "\r\n"), 0); StrBufAppendBufPlain(message_text, jmsg->rfc822, rfc822len, 0); StrBufAppendBufPlain( message_text, HKEY("--"), 0); StrBufAppendBufPlain(message_text, mime_boundary, mblen, 0); StrBufAppendBufPlain( message_text, HKEY("--\r\n"), 0); CM_SetAsFieldSB(journal_msg, eMesageText, &message_text); free(jmsg->rfc822); free(jmsg->msgn); jmsg->rfc822 = NULL; jmsg->msgn = NULL; /* Submit journal message */ CtdlSubmitMsg(journal_msg, journal_recps, "", 0); CM_Free(journal_msg); } free_recipients(journal_recps); } /* We are responsible for freeing this memory. */ free(jmsg); }
/* * The pathname is always going to be /groupdav/room_name/euid */ void dav_delete(void) { wcsession *WCC = WC; char dav_uid[SIZ]; long dav_msgnum = (-1); char buf[SIZ]; int n = 0; StrBuf *dav_roomname = NewStrBuf(); /* Now extract the message euid */ n = StrBufNum_tokens(WCC->Hdr->HR.ReqLine, '/'); extract_token(dav_uid, ChrPtr(WCC->Hdr->HR.ReqLine), n-1, '/', sizeof dav_uid); StrBufExtract_token(dav_roomname, WCC->Hdr->HR.ReqLine, 0, '/'); ///* What's left is the room name. Remove trailing slashes. */ //len = StrLength(WCC->Hdr->HR.ReqLine); //if ((len > 0) && (ChrPtr(WCC->Hdr->HR.ReqLinee)[len-1] == '/')) { // StrBufCutRight(WCC->Hdr->HR.ReqLine, 1); //} //StrBufCutLeft(WCC->Hdr->HR.ReqLine, 1); /* Go to the correct room. */ if (strcasecmp(ChrPtr(WC->CurRoom.name), ChrPtr(dav_roomname))) { gotoroom(dav_roomname); } if (strcasecmp(ChrPtr(WC->CurRoom.name), ChrPtr(dav_roomname))) { hprintf("HTTP/1.1 404 not found\r\n"); dav_common_headers(); hprintf("Content-Length: 0\r\n\r\n"); begin_burst(); end_burst(); FreeStrBuf(&dav_roomname); return; } dav_msgnum = locate_message_by_uid(dav_uid); /* * If no item exists with the requested uid ... simple error. */ if (dav_msgnum < 0L) { hprintf("HTTP/1.1 404 Not Found\r\n"); dav_common_headers(); hprintf("Content-Length: 0\r\n\r\n"); begin_burst(); end_burst(); FreeStrBuf(&dav_roomname); return; } /* * It's there ... check the ETag and make sure it matches * the message number. */ if (StrLength(WCC->Hdr->HR.dav_ifmatch) > 0) { if (StrTol(WCC->Hdr->HR.dav_ifmatch) != dav_msgnum) { hprintf("HTTP/1.1 412 Precondition Failed\r\n"); dav_common_headers(); hprintf("Content-Length: 0\r\n\r\n"); begin_burst(); end_burst(); FreeStrBuf(&dav_roomname); return; } } /* * Ok, attempt to delete the item. */ serv_printf("DELE %ld", dav_msgnum); serv_getln(buf, sizeof buf); if (buf[0] == '2') { hprintf("HTTP/1.1 204 No Content\r\n"); /* success */ dav_common_headers(); hprintf("Content-Length: 0\r\n\r\n"); begin_burst(); end_burst(); } else { hprintf("HTTP/1.1 403 Forbidden\r\n"); /* access denied */ dav_common_headers(); hprintf("Content-Length: 0\r\n\r\n"); begin_burst(); end_burst(); } FreeStrBuf(&dav_roomname); return; }
/* Converts a PEM encoded file into its binary form * * RFC 1421 Privacy Enhancement for Electronic Mail, February 1993 * RFC 934 Message Encapsulation, January 1985 */ err_t pem_to_bin(chunk_t *blob, chunk_t *passphrase, bool *pgp) { typedef enum { PEM_PRE = 0, PEM_MSG = 1, PEM_HEADER = 2, PEM_BODY = 3, PEM_POST = 4, PEM_ABORT = 5 } state_t; encryption_algorithm_t alg = ENCR_UNDEFINED; size_t key_size = 0; bool encrypted = FALSE; state_t state = PEM_PRE; chunk_t src = *blob; chunk_t dst = *blob; chunk_t line = CHUNK_INITIALIZER; chunk_t iv = CHUNK_INITIALIZER; u_char iv_buf[16]; /* MD5 digest size */ /* zero size of converted blob */ dst.len = 0; /* zero size of IV */ iv.ptr = iv_buf; iv.len = 0; pem_init_logger(); while (fetchline(&src, &line)) { if (state == PEM_PRE) { if (find_boundary("BEGIN", &line)) { state = PEM_MSG; } continue; } else { if (find_boundary("END", &line)) { state = PEM_POST; break; } if (state == PEM_MSG) { state = (memchr(line.ptr, ':', line.len) == NULL) ? PEM_BODY : PEM_HEADER; } if (state == PEM_HEADER) { err_t ugh = NULL; chunk_t name = CHUNK_INITIALIZER; chunk_t value = CHUNK_INITIALIZER; /* an empty line separates HEADER and BODY */ if (line.len == 0) { state = PEM_BODY; continue; } /* we are looking for a parameter: value pair */ logger->log(logger, CONTROL|LEVEL2, " %.*s", (int)line.len, line.ptr); ugh = extract_parameter_value(&name, &value, &line); if (ugh != NULL) continue; if (match("Proc-Type", &name) && *value.ptr == '4') encrypted = TRUE; else if (match("DEK-Info", &name)) { size_t len = 0; chunk_t dek; if (!extract_token(&dek, ',', &value)) dek = value; /* we support DES-EDE3-CBC encrypted files, only */ if (match("DES-EDE3-CBC", &dek)) { alg = ENCR_3DES; key_size = 24; } else if (match("AES-128-CBC", &dek)) { alg = ENCR_AES_CBC; key_size = 16; } else if (match("AES-192-CBC", &dek)) { alg = ENCR_AES_CBC; key_size = 24; } else if (match("AES-256-CBC", &dek)) { alg = ENCR_AES_CBC; key_size = 32; } else { return "encryption algorithm not supported"; } eat_whitespace(&value); ugh = ttodata(value.ptr, value.len, 16, iv.ptr, 16, &len); if (ugh) return "error in IV"; iv.len = len; } } else /* state is PEM_BODY */ { const char *ugh = NULL; size_t len = 0; chunk_t data; /* remove any trailing whitespace */ if (!extract_token(&data ,' ', &line)) { data = line; } /* check for PGP armor checksum */ if (*data.ptr == '=') { *pgp = TRUE; data.ptr++; data.len--; logger->log(logger, CONTROL|LEVEL2, " Armor checksum: %.*s", (int)data.len, data.ptr); continue; } ugh = ttodata(data.ptr, data.len, 64, dst.ptr, blob->len - dst.len, &len); if (ugh) { state = PEM_ABORT; break; } else { dst.ptr += len; dst.len += len; } } } } /* set length to size of binary blob */ blob->len = dst.len; if (state != PEM_POST) return "file coded in unknown format, discarded"; return (encrypted)? pem_decrypt(blob, alg, key_size, &iv, passphrase) : NULL; }
void network_process_ignetpush(SpoolControl *sc, struct CtdlMessage *omsg, long *delete_after_send) { StrBuf *Recipient; StrBuf *RemoteRoom; const char *Pos = NULL; struct CtdlMessage *msg = NULL; struct CitContext *CCC = CC; struct ser_ret sermsg; char buf[SIZ]; char filename[PATH_MAX]; FILE *fp; StrBuf *Buf = NULL; int i; int bang = 0; int send = 1; if (sc->Users[ignet_push_share] == NULL) return; /* * Process IGnet push shares */ msg = CM_Duplicate(omsg); /* Prepend our node name to the Path field whenever * sending a message to another IGnet node */ Netmap_AddMe(msg, HKEY("username")); /* * Determine if this message is set to be deleted * after sending out on the network */ if (!CM_IsEmpty(msg, eSpecialField)) { if (!strcasecmp(msg->cm_fields[eSpecialField], "CANCEL")) { *delete_after_send = 1; } } /* Now send it to every node */ Recipient = NewStrBufPlain(NULL, StrLength(sc->Users[ignet_push_share])); RemoteRoom = NewStrBufPlain(NULL, StrLength(sc->Users[ignet_push_share])); while ((Pos != StrBufNOTNULL) && StrBufExtract_NextToken(Recipient, sc->Users[ignet_push_share], &Pos, ',')) { StrBufExtract_NextToken(RemoteRoom, sc->Users[ignet_push_share], &Pos, ','); send = 1; NewStrBufDupAppendFlush(&Buf, Recipient, NULL, 1); /* Check for valid node name */ if (CtdlIsValidNode(NULL, NULL, Buf, sc->working_ignetcfg, sc->the_netmap) != 0) { QN_syslog(LOG_ERR, "Invalid node <%s>\n", ChrPtr(Recipient)); send = 0; } /* Check for split horizon */ QN_syslog(LOG_DEBUG, "Path is %s\n", msg->cm_fields[eMessagePath]); bang = num_tokens(msg->cm_fields[eMessagePath], '!'); if (bang > 1) { for (i=0; i<(bang-1); ++i) { extract_token(buf, msg->cm_fields[eMessagePath], i, '!', sizeof buf); QN_syslog(LOG_DEBUG, "Compare <%s> to <%s>\n", buf, ChrPtr(Recipient)) ; if (!strcasecmp(buf, ChrPtr(Recipient))) { send = 0; break; } } QN_syslog(LOG_INFO, " %sSending to %s\n", (send)?"":"Not ", ChrPtr(Recipient)); } /* Send the message */ if (send == 1) { /* * Force the message to appear in the correct * room on the far end by setting the C field * correctly */ if (StrLength(RemoteRoom) > 0) { CM_SetField(msg, eRemoteRoom, SKEY(RemoteRoom)); } else { CM_SetField(msg, eRemoteRoom, CCC->room.QRname, strlen(CCC->room.QRname)); } /* serialize it for transmission */ CtdlSerializeMessage(&sermsg, msg); if (sermsg.len > 0) { /* write it to a spool file */ snprintf(filename, sizeof(filename), "%s/%s@%lx%x", ctdl_netout_dir, ChrPtr(Recipient), time(NULL), rand() ); QN_syslog(LOG_DEBUG, "Appending to %s\n", filename); fp = fopen(filename, "ab"); if (fp != NULL) { fwrite(sermsg.ser, sermsg.len, 1, fp); fclose(fp); } else { QN_syslog(LOG_ERR, "%s: %s\n", filename, strerror(errno)); } /* free the serialized version */ free(sermsg.ser); } } } FreeStrBuf(&Buf); FreeStrBuf(&Recipient); FreeStrBuf(&RemoteRoom); CM_Free(msg); }
/* Creates and adds Media-Sub-Components to AVP_LIST * @param list - pointer to the AVP_LIST * @param sdpA - the SDP body of the INVITE * @param sdpB - the SDP body of the 200 OK answer for the INVITE * @param number - the number of the media component to use (which m= line?) * @param media_sub_component - array of Gq_Media_Sub_Components elements of type *AAA_AVP that were added * @param tag - 0 originating side 1 terminating side * returns the number of media_sub_components added on success -1 on error * the media_sub_component is given in order to free the AVPS after grouping them! */ inline int Gq_create_add_media_subcomponents(AAA_AVP_LIST *list,str sdpA,str sdpB,int number,AAA_AVP **media_sub_component,int tag) { char *mlineA,*mlineB,*clineA,*clineB; char portA[Gq_MAX_Char],portB[Gq_MAX_Char]; int intportA,intportB; char addressA[Gq_MAX_Char]; char addressB[Gq_MAX_Char]; int i=0,flows=0; int atributes=0; /* a= lines present?*/ char *newline,*rtp; int ports=1; /*how many ports does this m line define?*/ if (!extract_mclines(sdpA,sdpB,&mlineA,&clineA,&mlineB,&clineB,number)) { return -1; } /*a= lines are also needed*/ if (tag==0) { atributes=check_atributes(sdpA,mlineA); } else { atributes=check_atributes(sdpB,mlineB); } /*1 means sendonly*/ /*2 means recvonly*/ /*0 is no a= line or sendrecv or recvonly*/ if (!extract_token(mlineA,portA,Gq_MAX_Char,2)) { return -1; /*problem extracting port*/ } if (!extract_token(mlineB,portB,Gq_MAX_Char,2)) { return -1; /* either no ' ' or Gq_MAX_Char too small*/ } /*check if this are ports or multiports!*/ if(!is_a_port(portA) || !is_a_port(portB)) { return -1; /* there was a word there but it isn't a port*/ } if (strncmp(portA,"0",1)!=0 && strncmp(portB,"0",1)==0) { /*this means answerer rejected the offer*/ return 0; /*this is more logical*/ } /*the next lines have nothing to do with rtp * i just reused the pointer*/ rtp=index(portA,'/'); if (rtp!=NULL) { sscanf(portA,"%*i/%i%*s",&ports); *rtp='\0'; } if(!extract_token(clineA,addressA,Gq_MAX_Char,3)) { return -1; } if(!extract_token(clineB,addressB,Gq_MAX_Char,3)) { return -1; } /* i is the flow number */ /*flows is the number of data flows .. for each port 1 data flow*/ while(flows<ports && i+2<Gq_Media_Sub_Components) { i++; if (tag!=1) { media_sub_component[i-1]=Gq_create_media_subcomponent(i,"ip",addressA,portA,addressB,portB,"",atributes); AAAAddAVPToAVPList(list,media_sub_component[i-1]); } else { media_sub_component[i-1]=Gq_create_media_subcomponent(i,"ip",addressB,portB,addressA,portA,"",atributes); AAAAddAVPToAVPList(list,media_sub_component[i-1]); } flows++; if (1) { rtp=strstr(mlineA,"RTP"); newline=index(mlineA,'\n'); if (rtp!=NULL && rtp < newline) { i++; /*please optimize here!*/ sscanf(portA,"%i",&intportA); sscanf(portB,"%i",&intportB); intportA++; intportB++; sprintf(portA,"%i",intportA); sprintf(portB,"%i",intportB); if (tag!=1) { media_sub_component[i-1]=Gq_create_media_subcomponent(i,"ip",addressA,portA,addressB,portB,"",3); AAAAddAVPToAVPList(list,media_sub_component[i-1]); } else { media_sub_component[i-1]=Gq_create_media_subcomponent(i,"ip",addressB,portB,addressA,portA,"",3); AAAAddAVPToAVPList(list,media_sub_component[i-1]); } } sscanf(portA,"%i",&intportA); sscanf(portB,"%i",&intportB); intportA++; intportB++; sprintf(portA,"%i",intportA); sprintf(portB,"%i",intportB); /*if its not an RTP flow and it has multiports then the odd ports * are used for the next component .. if it is RTP and multiports than * the even ports are for the next component because the odd are used for * RTCP flows*/ } } return (i); }
/** * load IMCs from a configuration file */ static bool load_imcs(char *filename) { int fd, line_nr = 0; chunk_t src, line; struct stat sb; void *addr; DBG1(DBG_TNC, "loading IMCs from '%s'", filename); fd = open(filename, O_RDONLY); if (fd == -1) { DBG1(DBG_TNC, "opening configuration file '%s' failed: %s", filename, strerror(errno)); return FALSE; } if (fstat(fd, &sb) == -1) { DBG1(DBG_LIB, "getting file size of '%s' failed: %s", filename, strerror(errno)); close(fd); return FALSE; } addr = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); if (addr == MAP_FAILED) { DBG1(DBG_LIB, "mapping '%s' failed: %s", filename, strerror(errno)); close(fd); return FALSE; } src = chunk_create(addr, sb.st_size); while (fetchline(&src, &line)) { char *name, *path; chunk_t token; imc_t *imc; line_nr++; /* skip comments or empty lines */ if (*line.ptr == '#' || !eat_whitespace(&line)) { continue; } /* determine keyword */ if (!extract_token(&token, ' ', &line)) { DBG1(DBG_TNC, "line %d: keyword must be followed by a space", line_nr); return FALSE; } /* only interested in IMCs */ if (!match("IMC", &token)) { continue; } /* advance to the IMC name and extract it */ if (!extract_token(&token, '"', &line) || !extract_token(&token, '"', &line)) { DBG1(DBG_TNC, "line %d: IMC name must be set in double quotes", line_nr); return FALSE; } /* copy the IMC name */ name = malloc(token.len + 1); memcpy(name, token.ptr, token.len); name[token.len] = '\0'; /* advance to the IMC path and extract it */ if (!eat_whitespace(&line)) { DBG1(DBG_TNC, "line %d: IMC path is missing", line_nr); free(name); return FALSE; } if (!extract_token(&token, ' ', &line)) { token = line; } /* copy the IMC path */ path = malloc(token.len + 1); memcpy(path, token.ptr, token.len); path[token.len] = '\0'; /* load and register IMC instance */ imc = tnc_imc_create(name, path); if (!imc) { free(name); free(path); return FALSE; } if (!charon->imcs->add(charon->imcs, imc)) { if (imc->terminate && imc->terminate(imc->get_id(imc)) != TNC_RESULT_SUCCESS) { DBG1(DBG_TNC, "IMC \"%s\" not terminated successfully", imc->get_name(imc)); } imc->destroy(imc); return FALSE; } DBG1(DBG_TNC, "IMC %u \"%s\" loaded from '%s'", imc->get_id(imc), name, path); } munmap(addr, sb.st_size); close(fd); return TRUE; }
// ---------------------------------------------------------------------------- // std::vector<CString> SimpleJsonParser::tokenize( LPCSTR value, LPCSTR break_chars, bool store_breaks ) { std::vector<CString> tokens; LPCSTR start; LPCSTR head; CString token; bool in_quotes = false; bool in_token = false; bool must_break = false; char last_char = '\0'; for ( head=start=value; *head; head++ ) { if ( in_quotes ) { if ( *head == '"' && last_char != '\\' ) { in_quotes = false; must_break = true; token = extract_token( start, head ); } } else if ( iswspace(*head) ) { if ( in_token && !must_break ) { token = extract_token( start, head-1 ); must_break = true; } else if ( !in_token ) start = head+1; else ; // Ignore WS between tokens and breaks } else if ( strchr( break_chars, *head ) != NULL ) { if ( in_token && !must_break ) // Non-quoted literal token = extract_token( start, head-1 ); if ( in_token ) tokens.push_back( token ); if ( store_breaks ) tokens.push_back( extract_token( head, head ) ); start = head+1; in_token = must_break = false; } else if ( must_break ) throw std::exception( "Parse error" ); else { in_token = true; if ( *head == '"' && last_char != '\\' ) in_quotes = true; } last_char = *head; } if ( in_token ) { if ( in_quotes ) throw std::exception( "Unterminate quotes" ); if ( !must_break ) // Non-quoted literal token = extract_token( start, head-1 ); tokens.push_back( token ); } return tokens; }
// ---------------------------------------------------------------------------- // void SimpleJsonTokenizer::advanceToken() { bool in_quotes = false; while ( !m_token_available && !m_break_available && *m_head ) { if ( in_quotes ) { if ( *m_head == '"' && m_last_char != '\\' ) { in_quotes = false; m_must_break = true; extract_token( m_start, m_head ); } } else if ( iswspace(*m_head) ) { if ( m_in_token && !m_must_break ) { extract_token( m_start, m_head-1 ); m_must_break = true; } else if ( !m_in_token ) m_start = m_head+1; else ; // Ignore WS between tokens and breaks } else if ( strchr( m_break_chars, *m_head ) != NULL ) { if ( m_in_token && !m_must_break ) // Non-quoted literal extract_token( m_start, m_head-1 ); if ( m_in_token ) m_token_available = true; if ( m_store_breaks ) { m_break_char = *m_head; m_break_available = true; } m_start = m_head+1; m_in_token = m_must_break = false; } else if ( m_must_break ) throw std::exception( "Parse error" ); else { m_in_token = true; if ( *m_head == '"' && m_last_char != '\\' ) in_quotes = true; } m_last_char = *m_head; m_head++; } if ( m_token_available || m_break_available ) return; if ( m_in_token ) { if ( in_quotes ) throw std::exception( "Unterminate quotes" ); if ( !m_must_break ) // Non-quoted literal extract_token( m_start, m_head-1 ); m_token_available = true; m_in_token = false; } }