static char *builtin_function_checkmd5(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len) { int argc; char *argv[2]; char *args; char newmd5[33]; if (!data || ast_strlen_zero(data)) { ast_log(LOG_WARNING, "Syntax: CHECK_MD5(<digest>,<data>) - missing argument!\n"); return NULL; } args = ast_strdupa(data); argc = ast_app_separate_args(args, '|', argv, sizeof(argv) / sizeof(argv[0])); if (argc < 2) { ast_log(LOG_WARNING, "Syntax: CHECK_MD5(<digest>,<data>) - missing argument!\n"); return NULL; } ast_md5_hash(newmd5, argv[1]); if (!strcasecmp(newmd5, argv[0])) /* they match */ ast_copy_string(buf, "1", len); else ast_copy_string(buf, "0", len); return buf; }
int ast_sip_location_add_contact_nolock(struct ast_sip_aor *aor, const char *uri, struct timeval expiration_time, const char *path_info, const char *user_agent, const char *via_addr, int via_port, const char *call_id, struct ast_sip_endpoint *endpoint) { struct ast_sip_contact *contact; int res; char name[MAX_OBJECT_FIELD * 2 + 3]; char hash[33]; ast_md5_hash(hash, uri); snprintf(name, sizeof(name), "%s;@%s", ast_sorcery_object_get_id(aor), hash); contact = ast_sorcery_alloc(ast_sip_get_sorcery(), "contact", name); if (!contact) { return -1; } ast_string_field_set(contact, uri, uri); contact->expiration_time = expiration_time; contact->qualify_frequency = aor->qualify_frequency; contact->qualify_timeout = aor->qualify_timeout; contact->authenticate_qualify = aor->authenticate_qualify; if (path_info && aor->support_path) { ast_string_field_set(contact, path, path_info); } if (!ast_strlen_zero(aor->outbound_proxy)) { ast_string_field_set(contact, outbound_proxy, aor->outbound_proxy); } if (!ast_strlen_zero(user_agent)) { ast_string_field_set(contact, user_agent, user_agent); } if (!ast_strlen_zero(ast_config_AST_SYSTEM_NAME)) { ast_string_field_set(contact, reg_server, ast_config_AST_SYSTEM_NAME); } if (!ast_strlen_zero(via_addr)) { ast_string_field_set(contact, via_addr, via_addr); } contact->via_port = via_port; if (!ast_strlen_zero(call_id)) { ast_string_field_set(contact, call_id, call_id); } contact->endpoint = ao2_bump(endpoint); if (endpoint) { ast_string_field_set(contact, endpoint_name, ast_sorcery_object_get_id(endpoint)); } res = ast_sorcery_create(ast_sip_get_sorcery(), contact); ao2_ref(contact, -1); return res; }
/*! \brief Custom handler for permanent URIs */ static int permanent_uri_handler(const struct aco_option *opt, struct ast_variable *var, void *obj) { struct ast_sip_aor *aor = obj; const char *aor_id = ast_sorcery_object_get_id(aor); char *contacts; char *contact_uri; if (ast_strlen_zero(var->value)) { return 0; } contacts = ast_strdupa(var->value); while ((contact_uri = ast_strip(strsep(&contacts, ",")))) { struct ast_sip_contact *contact; struct ast_sip_contact_status *status; char hash[33]; char contact_id[strlen(aor_id) + sizeof(hash) + 2]; if (ast_strlen_zero(contact_uri)) { continue; } if (ast_sip_validate_uri_length(contact_uri)) { ast_log(LOG_ERROR, "Contact uri or hostname length exceeds pjproject limit: %s\n", contact_uri); return -1; } if (!aor->permanent_contacts) { aor->permanent_contacts = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK, AO2_CONTAINER_ALLOC_OPT_DUPS_REJECT, permanent_uri_sort_fn, NULL); if (!aor->permanent_contacts) { return -1; } } ast_md5_hash(hash, contact_uri); snprintf(contact_id, sizeof(contact_id), "%s@@%s", aor_id, hash); contact = ast_sorcery_alloc(ast_sip_get_sorcery(), "contact", contact_id); if (!contact) { return -1; } ast_string_field_set(contact, uri, contact_uri); status = ast_res_pjsip_find_or_create_contact_status(contact); if (!status) { ao2_ref(contact, -1); return -1; } ao2_ref(status, -1); ao2_link(aor->permanent_contacts, contact); ao2_ref(contact, -1); } return 0; }
static int md5(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len) { if (ast_strlen_zero(data)) { ast_log(LOG_WARNING, "Syntax: MD5(<data>) - missing argument!\n"); return -1; } ast_md5_hash(buf, data); buf[32] = '\0'; return 0; }
static char *builtin_function_md5(struct ast_channel *chan, char *cmd, char *data, char *buf, size_t len) { char md5[33]; if (ast_strlen_zero(data)) { ast_log(LOG_WARNING, "Syntax: MD5(<data>) - missing argument!\n"); return NULL; } ast_md5_hash(md5, data); ast_copy_string(buf, md5, len); return buf; }
/*! * \brief Calculate a nonce * * We use this in order to create authentication challenges. We also use this in order * to verify that an incoming request with credentials could be in response to one * of our challenges. * * The nonce is calculated from a timestamp, the source IP address, the source port, a * unique ID for us, and the realm. This helps to ensure that the incoming request * is from the same source that the nonce was calculated for. Including the realm * ensures that multiple challenges to the same request have different nonces. * * \param A UNIX timestamp expressed as a string * \param rdata The incoming request * \param realm The realm for which authentication should occur */ static int build_nonce(struct ast_str **nonce, const char *timestamp, const pjsip_rx_data *rdata, const char *realm) { struct ast_str *str = ast_str_alloca(256); RAII_VAR(char *, eid, ao2_global_obj_ref(entity_id), ao2_cleanup); char hash[32]; ast_str_append(&str, 0, "%s", timestamp); ast_str_append(&str, 0, ":%s", rdata->pkt_info.src_name); ast_str_append(&str, 0, ":%d", rdata->pkt_info.src_port); ast_str_append(&str, 0, ":%s", eid); ast_str_append(&str, 0, ":%s", realm); ast_md5_hash(hash, ast_str_buffer(str)); ast_str_append(nonce, 0, "%s/%s", timestamp, hash); return 0; }
int ast_sip_location_add_contact(struct ast_sip_aor *aor, const char *uri, struct timeval expiration_time, const char *path_info, const char *user_agent, struct ast_sip_endpoint *endpoint) { char name[MAX_OBJECT_FIELD * 2 + 3]; RAII_VAR(struct ast_sip_contact *, contact, NULL, ao2_cleanup); char hash[33]; ast_md5_hash(hash, uri); snprintf(name, sizeof(name), "%s;@%s", ast_sorcery_object_get_id(aor), hash); if (!(contact = ast_sorcery_alloc(ast_sip_get_sorcery(), "contact", name))) { return -1; } ast_string_field_set(contact, uri, uri); contact->expiration_time = expiration_time; contact->qualify_frequency = aor->qualify_frequency; contact->qualify_timeout = aor->qualify_timeout; contact->authenticate_qualify = aor->authenticate_qualify; if (path_info && aor->support_path) { ast_string_field_set(contact, path, path_info); } if (!ast_strlen_zero(aor->outbound_proxy)) { ast_string_field_set(contact, outbound_proxy, aor->outbound_proxy); } if (!ast_strlen_zero(user_agent)) { ast_string_field_set(contact, user_agent, user_agent); } contact->endpoint = ao2_bump(endpoint); return ast_sorcery_create(ast_sip_get_sorcery(), contact); }
static int auth_exec(struct ast_channel *chan, void *data) { int res=0; int jump = 0; int retries; struct localuser *u; char password[256]=""; char passwd[256]; char *opts; char *prompt; if (ast_strlen_zero(data)) { ast_log(LOG_WARNING, "Authenticate requires an argument(password)\n"); return -1; } LOCAL_USER_ADD(u); if (chan->_state != AST_STATE_UP) { res = ast_answer(chan); if (res) { LOCAL_USER_REMOVE(u); return -1; } } strncpy(password, data, sizeof(password) - 1); opts=strchr(password, '|'); if (opts) { *opts = 0; opts++; } else opts = ""; if (strchr(opts, 'j')) jump = 1; /* Start asking for password */ prompt = "agent-pass"; for (retries = 0; retries < 3; retries++) { res = ast_app_getdata(chan, prompt, passwd, sizeof(passwd) - 2, 0); if (res < 0) break; res = 0; if (password[0] == '/') { if (strchr(opts, 'd')) { char tmp[256]; /* Compare against a database key */ if (!ast_db_get(password + 1, passwd, tmp, sizeof(tmp))) { /* It's a good password */ if (strchr(opts, 'r')) { ast_db_del(password + 1, passwd); } break; } } else { /* Compare against a file */ FILE *f; f = fopen(password, "r"); if (f) { char buf[256] = ""; char md5passwd[33] = ""; char *md5secret = NULL; while (!feof(f)) { fgets(buf, sizeof(buf), f); if (!feof(f) && !ast_strlen_zero(buf)) { buf[strlen(buf) - 1] = '\0'; if (strchr(opts, 'm')) { md5secret = strchr(buf, ':'); if (md5secret == NULL) continue; *md5secret = '\0'; md5secret++; ast_md5_hash(md5passwd, passwd); if (!strcmp(md5passwd, md5secret)) { if (strchr(opts, 'a')) ast_cdr_setaccount(chan, buf); break; } } else { if (!strcmp(passwd, buf)) { if (strchr(opts, 'a')) ast_cdr_setaccount(chan, buf); break; } } } } fclose(f); if (!ast_strlen_zero(buf)) { if (strchr(opts, 'm')) { if (md5secret && !strcmp(md5passwd, md5secret)) break; } else { if (!strcmp(passwd, buf)) break; } } } else ast_log(LOG_WARNING, "Unable to open file '%s' for authentication: %s\n", password, strerror(errno)); } } else { /* Compare against a fixed password */ if (!strcmp(passwd, password)) break; } prompt="auth-incorrect"; } if ((retries < 3) && !res) { if (strchr(opts, 'a') && !strchr(opts, 'm')) ast_cdr_setaccount(chan, passwd); res = ast_streamfile(chan, "auth-thankyou", chan->language); if (!res) res = ast_waitstream(chan, ""); } else { if (jump && ast_goto_if_exists(chan, chan->context, chan->exten, chan->priority + 101) == 0) { res = 0; } else { if (!ast_streamfile(chan, "vm-goodbye", chan->language)) res = ast_waitstream(chan, ""); res = -1; } } LOCAL_USER_REMOVE(u); return res; }