Adds a new entry in the ACL log, making sure to delete the old entry * if we reach the maximum length allowed for the log. This function attempts * to find similar entries in the current log in order to bump the counter of * the log entry instead of creating many entries for very similar ACL * rules issues. * * The argpos argument is used when the reason is ACL_DENIED_KEY or * ACL_DENIED_C
| 1801 | * reason. Otherwise it will just be NULL. |
| 1802 | */ |
| 1803 | void addACLLogEntry(client *c, int reason, int argpos, sds username) { |
| 1804 | /* Create a new entry. */ |
| 1805 | struct ACLLogEntry *le = zmalloc(sizeof(*le)); |
| 1806 | le->count = 1; |
| 1807 | le->reason = reason; |
| 1808 | le->username = sdsdup(reason == ACL_DENIED_AUTH ? username : c->user->name); |
| 1809 | le->ctime = mstime(); |
| 1810 | |
| 1811 | switch(reason) { |
| 1812 | case ACL_DENIED_CMD: le->object = sdsnew(c->cmd->name); break; |
| 1813 | case ACL_DENIED_KEY: le->object = sdsdup(c->argv[argpos]->ptr); break; |
| 1814 | case ACL_DENIED_CHANNEL: le->object = sdsdup(c->argv[argpos]->ptr); break; |
| 1815 | case ACL_DENIED_AUTH: le->object = sdsdup(c->argv[0]->ptr); break; |
| 1816 | default: le->object = sdsempty(); |
| 1817 | } |
| 1818 | |
| 1819 | client *realclient = c; |
| 1820 | if (realclient->flags & CLIENT_LUA) realclient = server.lua_caller; |
| 1821 | |
| 1822 | le->cinfo = catClientInfoString(sdsempty(),realclient); |
| 1823 | if (c->flags & CLIENT_MULTI) { |
| 1824 | le->context = ACL_LOG_CTX_MULTI; |
| 1825 | } else if (c->flags & CLIENT_LUA) { |
| 1826 | le->context = ACL_LOG_CTX_LUA; |
| 1827 | } else { |
| 1828 | le->context = ACL_LOG_CTX_TOPLEVEL; |
| 1829 | } |
| 1830 | |
| 1831 | /* Try to match this entry with past ones, to see if we can just |
| 1832 | * update an existing entry instead of creating a new one. */ |
| 1833 | long toscan = 10; /* Do a limited work trying to find duplicated. */ |
| 1834 | listIter li; |
| 1835 | listNode *ln; |
| 1836 | listRewind(ACLLog,&li); |
| 1837 | ACLLogEntry *match = NULL; |
| 1838 | while (toscan-- && (ln = listNext(&li)) != NULL) { |
| 1839 | ACLLogEntry *current = listNodeValue(ln); |
| 1840 | if (ACLLogMatchEntry(current,le)) { |
| 1841 | match = current; |
| 1842 | listDelNode(ACLLog,ln); |
| 1843 | listAddNodeHead(ACLLog,current); |
| 1844 | break; |
| 1845 | } |
| 1846 | } |
| 1847 | |
| 1848 | /* If there is a match update the entry, otherwise add it as a |
| 1849 | * new one. */ |
| 1850 | if (match) { |
| 1851 | /* We update a few fields of the existing entry and bump the |
| 1852 | * counter of events for this entry. */ |
| 1853 | sdsfree(match->cinfo); |
| 1854 | match->cinfo = le->cinfo; |
| 1855 | match->ctime = le->ctime; |
| 1856 | match->count++; |
| 1857 | |
| 1858 | /* Release the old entry. */ |
| 1859 | le->cinfo = NULL; |
| 1860 | ACLFreeLogEntry(le); |
no test coverage detected