int MailboxState_getAcl(T M, uint64_t userid, struct ACLMap *map) { int i; volatile int t = DM_SUCCESS; gboolean gotrow = FALSE; uint64_t anyone; Connection_T c; ResultSet_T r; PreparedStatement_T s; g_return_val_if_fail(MailboxState_getId(M),DM_EGENERAL); if (! (auth_user_exists(DBMAIL_ACL_ANYONE_USER, &anyone))) return DM_EQUERY; c = db_con_get(); TRY s = db_stmt_prepare(c, "SELECT lookup_flag,read_flag,seen_flag," "write_flag,insert_flag,post_flag," "create_flag,delete_flag,deleted_flag,expunge_flag,administer_flag " "FROM %sacl " "WHERE mailbox_id = ? AND user_id = ?",DBPFX); db_stmt_set_u64(s, 1, MailboxState_getId(M)); db_stmt_set_u64(s, 2, userid); r = db_stmt_query(s); if (! db_result_next(r)) { /* else check the 'anyone' user */ db_stmt_set_u64(s, 2, anyone); r = db_stmt_query(s); if (db_result_next(r)) gotrow = TRUE; } else { gotrow = TRUE; } if (gotrow) { i = 0; map->lookup_flag = db_result_get_bool(r,i++); map->read_flag = db_result_get_bool(r,i++); map->seen_flag = db_result_get_bool(r,i++); map->write_flag = db_result_get_bool(r,i++); map->insert_flag = db_result_get_bool(r,i++); map->post_flag = db_result_get_bool(r,i++); map->create_flag = db_result_get_bool(r,i++); map->delete_flag = db_result_get_bool(r,i++); map->deleted_flag = db_result_get_bool(r,i++); map->expunge_flag = db_result_get_bool(r,i++); map->administer_flag = db_result_get_bool(r,i++); } CATCH(SQLException) LOG_SQLERROR; t = DM_EQUERY; FINALLY db_con_close(c); END_TRY; return t; }
int MailboxState_flush_recent(T M) { GList *recent; if ((!M) || (M && MailboxState_getPermission(M) != IMAPPERM_READWRITE)) return DM_SUCCESS; if (! g_tree_nnodes(M->recent_queue)) return DM_SUCCESS; TRACE(TRACE_DEBUG,"flush [%d] recent messages", g_tree_nnodes(M->recent_queue)); recent = g_tree_keys(M->recent_queue); if (recent) { long long int changed = 0; uint64_t seq = MailboxState_getSeq(M); changed = _update_recent(g_list_slices_u64(recent,100), seq+1); if (changed) db_mailbox_seq_update(MailboxState_getId(M), 0); } g_list_free(g_list_first(recent)); g_tree_foreach(M->recent_queue, (GTraverseFunc)_free_recent_queue, M); g_tree_destroy(M->recent_queue); M->recent_queue = g_tree_new((GCompareFunc)ucmp); return 0; }
//--------------------------------------------------------------------------------------// void Http_getUsers(T R) { struct evbuffer *buf; char *username = NULL; uint64_t id = 0; if (Request_getId(R)) { /* * id can be specified both by name and number * * C < /users/testuser1 * C < /users/123 * */ if ((id = strtoull(Request_getId(R), NULL, 10))) username = auth_get_userid(id); else if (auth_user_exists(Request_getId(R), &id)) username = g_strdup(Request_getId(R)); if (! (username && id)) Request_error(R, HTTP_NOTFOUND, "User not found"); } buf = evbuffer_new(); if (Request_getMethod(R) == NULL) { GList *users = NULL; if (username) { MailboxState_T M; const char *mailbox; uint64_t mboxid; /* * retrieve user meta-data * C < /users/testuser1 * create/delete mailbox for user * POST C < /users/testuser1 */ if ((mailbox = evhttp_find_header(Request_getPOST(R),"create"))) { const char *message; if (db_mailbox_create_with_parents(mailbox, BOX_COMMANDLINE, id, &mboxid, &message)) { Request_error(R, HTTP_BADREQUEST, message); evbuffer_free(buf); return; } } if ((mailbox = evhttp_find_header(Request_getPOST(R),"delete"))) { int access; /* check if there is an attempt to delete inbox */ if (MATCH(mailbox, "INBOX")) { Request_error(R, HTTP_BADREQUEST, "NO cannot delete special mailbox INBOX"); evbuffer_free(buf); return; } if (! (db_findmailbox(mailbox, id, &mboxid)) ) { Request_error(R, HTTP_NOTFOUND, "NO mailbox doesn't exists"); evbuffer_free(buf); return; } /* Check if the user has ACL delete rights to this mailbox */ M = MailboxState_new(mboxid); access = acl_has_right(M, id, ACL_RIGHT_DELETE); if (access != 1) { Request_error(R, HTTP_BADREQUEST, "NO permission denied"); evbuffer_free(buf); return; } /* ok remove mailbox */ if (db_delete_mailbox(mboxid, 0, 1)) { Request_error(R, HTTP_SERVUNAVAIL, "NO delete failed"); evbuffer_free(buf); return; } } users = g_list_append_printf(users, "%s", username); } else { /* * list all users * C < /users/ * * create,edit,delete user * POST C < /users/ */ const char *user = NULL; if ((user = evhttp_find_header(Request_getPOST(R),"create"))) { const char *password, *encoding, *quota; password = evhttp_find_header(Request_getPOST(R), "password"); encoding = evhttp_find_header(Request_getPOST(R), "encoding"); quota = evhttp_find_header(Request_getPOST(R), "quota"); TRACE(TRACE_DEBUG, "create user: [%s] password: [%s] encoding [%s] quota [%s]", user, password, encoding, quota); } else if ((user = evhttp_find_header(Request_getPOST(R),"edit"))) { TRACE(TRACE_DEBUG, "edit user: [%s]", user); } else if ((user = evhttp_find_header(Request_getPOST(R),"delete"))) { TRACE(TRACE_DEBUG, "delete user: [%s]", user); } users = auth_get_known_users(); } Request_setContentType(R,"application/json; charset=utf-8"); evbuffer_add_printf(buf, "{\"users\": {\n"); while(users->data) { uint64_t id; if (auth_user_exists((char *)users->data, &id)) evbuffer_add_printf(buf, " \"%lu\":{\"name\":\"%s\"}", id, (char *)users->data); if (! g_list_next(users)) break; users = g_list_next(users); evbuffer_add_printf(buf,",\n"); } evbuffer_add_printf(buf, "\n}}\n"); g_list_destroy(users); } else if (MATCH(Request_getMethod(R),"mailboxes")) { GList *mailboxes = NULL; if (! username) { Request_error(R, HTTP_NOTFOUND, "User not found"); evbuffer_free(buf); return; } /* * list mailboxes for user * GET C < /users/testuser1/mailboxes * */ db_findmailbox_by_regex(id, "*", &mailboxes, FALSE); Request_setContentType(R,"application/json; charset=utf-8"); evbuffer_add_printf(buf, "{\"mailboxes\": {\n"); while (mailboxes->data) { MailboxState_T b = MailboxState_new(*((uint64_t *)mailboxes->data)); MailboxState_setOwner(b, id); //if (MailboxState_reload(b) == DM_SUCCESS) evbuffer_add_printf(buf, " \"%lu\":{\"name\":\"%s\",\"exists\":%u}", MailboxState_getId(b), MailboxState_getName(b), MailboxState_getExists(b)); MailboxState_free(&b); if (! g_list_next(mailboxes)) break; mailboxes = g_list_next(mailboxes); evbuffer_add_printf(buf,",\n"); } evbuffer_add_printf(buf, "\n}}\n"); } if (EVBUFFER_LENGTH(buf)) Request_send(R, HTTP_OK, "OK", buf); else Request_error(R, HTTP_SERVUNAVAIL, "Server error"); if (username) g_free(username); evbuffer_free(buf); }
//--------------------------------------------------------------------------------------// void Http_getMailboxes(T R) { const char *mailbox = Request_getId(R); TRACE(TRACE_DEBUG,"mailbox [%s]", mailbox); char *endptr = NULL; struct evbuffer *buf; uint64_t id = 0; if (! mailbox) { Request_error(R, HTTP_SERVUNAVAIL, "Server error"); return; } if (! (id = strtoull(mailbox, &endptr, 10))) { Request_error(R, HTTP_NOTFOUND, "Not found"); return; } TRACE(TRACE_DEBUG,"mailbox id [%lu]", id); buf = evbuffer_new(); Request_setContentType(R,"application/json; charset=utf-8"); if (Request_getMethod(R) == NULL) { /* * retrieve mailbox meta-data * C < GET /mailboxes/876 * * or * * append a new message * C < POST /mailboxes/876 */ const char *msg; uint64_t msg_id = 0; MailboxState_T b = MailboxState_new(id); unsigned exists = MailboxState_getExists(b); if ((msg = evhttp_find_header(Request_getPOST(R),"message"))) { if (! db_append_msg(msg, MailboxState_getId(b), MailboxState_getOwner(b), NULL, &msg_id, TRUE)) exists++; } evbuffer_add_printf(buf, "{\"mailboxes\": {\n"); evbuffer_add_printf(buf, " \"%lu\":{\"name\":\"%s\",\"exists\":%d}", MailboxState_getId(b), MailboxState_getName(b), exists); evbuffer_add_printf(buf, "\n}}\n"); MailboxState_free(&b); } else if (MATCH(Request_getMethod(R),"messages")) { /* * list messages in mailbox * C < GET /mailboxes/876/messages */ MailboxState_T b = MailboxState_new(id); GTree *msns = MailboxState_getMsn(b); GList *ids = g_tree_keys(msns); GTree *msginfo = MailboxState_getMsginfo(b); evbuffer_add_printf(buf, "{\"messages\": {\n"); while (ids && ids->data) { uint64_t *msn = (uint64_t *)ids->data; uint64_t *uid = (uint64_t *)g_tree_lookup(msns, msn); MessageInfo *info = (MessageInfo *)g_tree_lookup(msginfo, uid); evbuffer_add_printf(buf, " \"%lu\":{\"size\":%lu}", *uid, info->rfcsize); if (! g_list_next(ids)) break; ids = g_list_next(ids); evbuffer_add_printf(buf,",\n"); } evbuffer_add_printf(buf, "\n}}\n"); if (ids) g_list_free(g_list_first(ids)); MailboxState_free(&b); } if (EVBUFFER_LENGTH(buf)) Request_send(R, HTTP_OK, "OK", buf); else Request_error(R, HTTP_SERVUNAVAIL, "Server error"); evbuffer_free(buf); }
int MailboxState_hasPermission(T M, uint64_t userid, const char *right_flag) { PreparedStatement_T stmt; Connection_T c; ResultSet_T r; volatile int result = FALSE; volatile bool owner_acl = false; uint64_t owner_id, mboxid; mboxid = MailboxState_getId(M); TRACE(TRACE_DEBUG, "checking ACL [%s] for user [%" PRIu64 "] on mailbox [%" PRIu64 "]", right_flag, userid, mboxid); /* If we don't know who owns the mailbox, look it up. */ owner_id = MailboxState_getOwner(M); if (! owner_id) { result = db_get_mailbox_owner(mboxid, &owner_id); MailboxState_setOwner(M, owner_id); if (! (result > 0)) return result; } if (owner_id == userid) { c = db_con_get(); TRY stmt = db_stmt_prepare(c, "SELECT * FROM %sacl WHERE " "user_id = ? AND mailbox_id = ?", DBPFX); db_stmt_set_u64(stmt, 1, userid); db_stmt_set_u64(stmt, 2, mboxid); r = db_stmt_query(stmt); if (db_result_next(r)) owner_acl = true; CATCH(SQLException) LOG_SQLERROR; result = DM_EQUERY; FINALLY db_con_close(c); END_TRY; if (! owner_acl) { TRACE(TRACE_DEBUG, "mailbox [%" PRIu64 "] is owned by user [%" PRIu64 "]" "and no ACL in place. Giving all rights", mboxid, userid); return 1; } else { TRACE(TRACE_DEBUG, "mailbox [%" PRIu64 "] is owned by user [%" PRIu64 "]" "but ACL in place. Restricted access for owner.", mboxid, userid); } } result = FALSE; c = db_con_get(); TRY stmt = db_stmt_prepare(c, "SELECT * FROM %sacl WHERE " "user_id = ? AND mailbox_id = ? AND %s = 1", DBPFX, right_flag); db_stmt_set_u64(stmt, 1, userid); db_stmt_set_u64(stmt, 2, mboxid); r = db_stmt_query(stmt); if (db_result_next(r)) result = TRUE; CATCH(SQLException) LOG_SQLERROR; result = DM_EQUERY; FINALLY db_con_close(c); END_TRY; return result; }