static void cmd_user_mail_input_field(const char *key, const char *value, const char *show_field) { string_t *jvalue = t_str_new(128); if (show_field != NULL && strcmp(show_field, key) != 0) return; json_append_escaped(jvalue, key); o_stream_nsend_str(doveadm_print_ostream, "\""); o_stream_nsend_str(doveadm_print_ostream, str_c(jvalue)); o_stream_nsend_str(doveadm_print_ostream, "\":\""); str_truncate(jvalue, 0); json_append_escaped(jvalue, value); o_stream_nsend_str(doveadm_print_ostream, str_c(jvalue)); o_stream_nsend_str(doveadm_print_ostream, "\""); }
static void test_json_append_escaped(void) { string_t *str = t_str_new(32); test_begin("json_append_escaped()"); json_append_escaped(str, "\b\f\r\n\t\"\\\001\002-\xC3\xA4"); test_assert(strcmp(str_c(str), "\\b\\f\\r\\n\\t\\\"\\\\\\u0001\\u0002-\xC3\xA4") == 0); test_end(); }
static int xaps_register(const char *aps_account_id, const char *aps_device_token, const char *aps_subtopic, const char *dovecot_username, const struct imap_arg *dovecot_mailboxes) { /* * Construct our request. */ string_t *req = t_str_new(2048); str_append(req, "XAPS REGISTER "); str_append(req, "{\"aps-account-id\":\""); json_append_escaped(req, aps_account_id); str_append(req, "\",\"aps-device-token\":\""); json_append_escaped(req, aps_device_token); str_append(req, "\",\"aps-subtopic\":\""); json_append_escaped(req, aps_subtopic); str_append(req, "\",\"dovecot-username\":\""); json_append_escaped(req, dovecot_username); str_append(req, "\","); if (dovecot_mailboxes == NULL) { str_append(req, "\"dovecot-mailboxes\":[\"INBOX\"]"); } else { str_append(req, "\"dovecot-mailboxes\":["); int next = 0; for (; !IMAP_ARG_IS_EOL(dovecot_mailboxes); dovecot_mailboxes++) { const char *mailbox; if (!imap_arg_get_astring(&dovecot_mailboxes[0], &mailbox)) { return -1; } if (next) { str_append(req, ","); } str_append(req, "\""); json_append_escaped(req, mailbox); str_append(req, "\""); next = 1; } str_append(req, "]"); } str_append(req, "}"); i_info(str_c(req)); return 0; }
static int cmd_user_input(struct auth_master_connection *conn, const struct authtest_input *input, const char *show_field, bool userdb) { const char *lookup_name = userdb ? "userdb lookup" : "passdb lookup"; pool_t pool; const char *updated_username = NULL, *const *fields, *p; int ret; pool = pool_alloconly_create("auth master lookup", 1024); if (userdb) { ret = auth_master_user_lookup(conn, input->username, &input->info, pool, &updated_username, &fields); } else { ret = auth_master_pass_lookup(conn, input->username, &input->info, pool, &fields); } if (ret < 0) { const char *msg; if (fields[0] == NULL) { msg = t_strdup_printf("\"error\":\"%s failed\"", lookup_name); } else { msg = t_strdup_printf("\"error\":\"%s failed: %s\"", lookup_name, fields[0]); } o_stream_nsend_str(doveadm_print_ostream, msg); ret = -1; } else if (ret == 0) { o_stream_nsend_str(doveadm_print_ostream, t_strdup_printf("\"error\":\"%s: user doesn't exist\"", lookup_name)); } else if (show_field != NULL) { unsigned int show_field_len = strlen(show_field); string_t *json_field = t_str_new(show_field_len+1); json_append_escaped(json_field, show_field); o_stream_nsend_str(doveadm_print_ostream, t_strdup_printf("\"%s\":", str_c(json_field))); for (; *fields != NULL; fields++) { if (strncmp(*fields, show_field, show_field_len) == 0 && (*fields)[show_field_len] == '=') { string_t *jsonval = t_str_new(32); json_append_escaped(jsonval, *fields + show_field_len + 1); o_stream_nsend_str(doveadm_print_ostream, "\""); o_stream_nsend_str(doveadm_print_ostream, str_c(jsonval)); o_stream_nsend_str(doveadm_print_ostream, "\""); } } } else { string_t *jsonval = t_str_new(64); o_stream_nsend_str(doveadm_print_ostream, "\"source\":\""); o_stream_nsend_str(doveadm_print_ostream, userdb ? "userdb\"" : "passdb\""); if (updated_username != NULL) { o_stream_nsend_str(doveadm_print_ostream, ",\"updated_username\":\""); str_truncate(jsonval, 0); json_append_escaped(jsonval, updated_username); o_stream_nsend_str(doveadm_print_ostream, str_c(jsonval)); o_stream_nsend_str(doveadm_print_ostream, "\""); } for (; *fields != NULL; fields++) { const char *field = *fields; if (*field == '\0') continue; p = strchr(*fields, '='); str_truncate(jsonval, 0); if (p != NULL) { field = t_strcut(*fields, '='); } str_truncate(jsonval, 0); json_append_escaped(jsonval, field); o_stream_nsend_str(doveadm_print_ostream, ",\""); o_stream_nsend_str(doveadm_print_ostream, str_c(jsonval)); o_stream_nsend_str(doveadm_print_ostream, "\":"); if (p != NULL) { str_truncate(jsonval, 0); json_append_escaped(jsonval, p+1); o_stream_nsend_str(doveadm_print_ostream, "\""); o_stream_nsend_str(doveadm_print_ostream, str_c(jsonval)); o_stream_nsend_str(doveadm_print_ostream, "\""); } else { o_stream_nsend_str(doveadm_print_ostream, "true"); } } } return ret; }
static void cmd_user_ver2(struct doveadm_cmd_context *cctx) { const char * const *optval; const char *auth_socket_path = NULL; struct auth_master_connection *conn; struct authtest_input input; const char *show_field = NULL, *expand_field = NULL; struct mail_storage_service_ctx *storage_service = NULL; bool have_wildcards, userdb_only = FALSE, first = TRUE; int ret; if (!doveadm_cmd_param_str(cctx, "socket-path", &auth_socket_path)) auth_socket_path = doveadm_settings->auth_socket_path; (void)doveadm_cmd_param_str(cctx, "expand-field", &expand_field); (void)doveadm_cmd_param_str(cctx, "field", &show_field); (void)doveadm_cmd_param_bool(cctx, "userdb-only", &userdb_only); memset(&input, 0, sizeof(input)); if (doveadm_cmd_param_array(cctx, "auth-info", &optval)) for(; *optval != NULL; optval++) auth_user_info_parse(&input.info, *optval); if (!doveadm_cmd_param_array(cctx, "user-mask", &optval)) { doveadm_exit_code = EX_USAGE; i_error("No user(s) specified"); return; } if (expand_field != NULL && userdb_only) { i_error("-e can't be used with -u"); doveadm_exit_code = EX_USAGE; return; } if (expand_field != NULL && show_field != NULL) { i_error("-e can't be used with -f"); doveadm_exit_code = EX_USAGE; return; } conn = doveadm_get_auth_master_conn(auth_socket_path); have_wildcards = FALSE; for(const char *const *val = optval; *val != NULL; val++) { if (strchr(*val, '*') != NULL || strchr(*val, '?') != NULL) { have_wildcards = TRUE; break; } } if (have_wildcards) { cmd_user_list(conn, &input, (char*const*)optval); auth_master_deinit(&conn); return; } if (!userdb_only) { storage_service = mail_storage_service_init(master_service, NULL, MAIL_STORAGE_SERVICE_FLAG_USERDB_LOOKUP | MAIL_STORAGE_SERVICE_FLAG_NO_CHDIR | MAIL_STORAGE_SERVICE_FLAG_NO_LOG_INIT | MAIL_STORAGE_SERVICE_FLAG_NO_PLUGINS | MAIL_STORAGE_SERVICE_FLAG_NO_NAMESPACES | MAIL_STORAGE_SERVICE_FLAG_NO_RESTRICT_ACCESS); mail_storage_service_set_auth_conn(storage_service, conn); conn = NULL; } string_t *json = t_str_new(64); o_stream_nsend_str(doveadm_print_ostream, "{"); input.info.local_ip = cctx->local_ip; input.info.local_port = cctx->local_port; input.info.remote_ip = cctx->remote_ip; input.info.remote_port = cctx->remote_port; for(const char *const *val = optval; *val != NULL; val++) { str_truncate(json, 0); json_append_escaped(json, *val); input.username = *val; if (first) first = FALSE; else o_stream_nsend_str(doveadm_print_ostream, ","); o_stream_nsend_str(doveadm_print_ostream, "\""); o_stream_nsend_str(doveadm_print_ostream, str_c(json)); o_stream_nsend_str(doveadm_print_ostream, "\""); o_stream_nsend_str(doveadm_print_ostream, ":{"); ret = !userdb_only ? cmd_user_mail_input(storage_service, &input, show_field, expand_field) : cmd_user_input(conn, &input, show_field, TRUE); o_stream_nsend_str(doveadm_print_ostream, "}"); switch (ret) { case -1: doveadm_exit_code = EX_TEMPFAIL; break; case 0: doveadm_exit_code = EX_NOUSER; break; } } o_stream_nsend_str(doveadm_print_ostream,"}"); if (storage_service != NULL) mail_storage_service_deinit(&storage_service); if (conn != NULL) auth_master_deinit(&conn); }
static int cmd_user_mail_input(struct mail_storage_service_ctx *storage_service, const struct authtest_input *input, const char *show_field, const char *expand_field) { struct mail_storage_service_input service_input; struct mail_storage_service_user *service_user; struct mail_user *user; const char *error, *const *userdb_fields; pool_t pool; int ret; memset(&service_input, 0, sizeof(service_input)); service_input.module = "mail"; service_input.service = input->info.service; service_input.username = input->username; service_input.local_ip = input->info.local_ip; service_input.local_port = input->info.local_port; service_input.remote_ip = input->info.remote_ip; service_input.remote_port = input->info.remote_port; service_input.debug = input->info.debug; pool = pool_alloconly_create("userdb fields", 1024); mail_storage_service_save_userdb_fields(storage_service, pool, &userdb_fields); if ((ret = mail_storage_service_lookup_next(storage_service, &service_input, &service_user, &user, &error)) <= 0) { pool_unref(&pool); if (ret < 0) return -1; string_t *username = t_str_new(32); json_append_escaped(username, input->username); o_stream_nsend_str(doveadm_print_ostream, t_strdup_printf("\"error\":\"userdb lookup: user %s doesn't exist\"", str_c(username)) ); return 0; } if (expand_field == NULL) cmd_user_mail_print_fields(input, user, userdb_fields, show_field); else { string_t *str = t_str_new(128); if (var_expand_with_funcs(str, expand_field, mail_user_var_expand_table(user), mail_user_var_expand_func_table, user, &error) <= 0) { string_t *str = t_str_new(128); str_printfa(str, "\"error\":\"Failed to expand field: "); json_append_escaped(str, error); str_append_c(str, '"'); o_stream_nsend(doveadm_print_ostream, str_data(str), str_len(str)); } else { string_t *value = t_str_new(128); json_append_escaped(value, expand_field); o_stream_nsend_str(doveadm_print_ostream, "\""); o_stream_nsend_str(doveadm_print_ostream, str_c(value)); o_stream_nsend_str(doveadm_print_ostream, "\":\""); str_truncate(value, 0); json_append_escaped(value, str_c(str)); o_stream_nsend_str(doveadm_print_ostream, str_c(value)); o_stream_nsend_str(doveadm_print_ostream, "\""); } } mail_user_unref(&user); mail_storage_service_user_free(&service_user); pool_unref(&pool); return 1; }