auth-policy.c revision e1d4f6f6ab3cedc30c7477820c394fbd3769964c
7cb128dc4cae2a03a742f63ba7afee23c78e3af0Phil Carmody#include "lib.h"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include "net.h"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include "str.h"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include "istream.h"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include "ioloop.h"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include "base64.h"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include "hex-binary.h"
a991cfe2157e58ee43bc580f517ce9ef0dfb7acfStephan Bosch#include "hash-method.h"
de0181258ab66b527ad8dc7e51a8efa76b4658d0Stephan Bosch#include "http-url.h"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include "http-client.h"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include "json-parser.h"
0d5c9a80e91a4073d5fd6820e9ddce2755221f64Stephan Bosch#include "auth-request.h"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch#include "auth-penalty.h"
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch#include "auth-settings.h"
30f35cf5d1e1374d7fab4231e86144fc106a8e79Stephan Bosch#include "auth-policy.h"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen#define AUTH_POLICY_DNS_SOCKET_PATH "dns-client"
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic struct http_client_settings http_client_set = {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch .dns_client_socket_path = AUTH_POLICY_DNS_SOCKET_PATH,
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen .max_connect_attempts = 1,
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen .max_idle_time_msecs = 10000,
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen .max_parallel_connections = 100,
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen .debug = 0,
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen .user_agent = "dovecot/auth-policy-client"
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen};
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainenstatic char *auth_policy_json_template;
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainenstatic struct http_client *http_client;
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstruct policy_lookup_ctx {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch pool_t pool;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch string_t *json;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch struct auth_request *request;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch struct http_client_request *http_request;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch struct json_parser *parser;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch const struct auth_settings *set;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch const char *url;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch bool expect_result;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch int result;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch const char *message;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch auth_policy_callback_t callback;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch void *callback_context;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch struct istream *payload;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch struct io *io;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch enum {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch POLICY_RESULT = 0,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch POLICY_RESULT_VALUE_STATUS,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch POLICY_RESULT_VALUE_MESSAGE
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch } parse_state;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch bool parse_error;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch};
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
9145c8b5eda526d05bd4a7ced20f6f6f2ff8df03Stephan Boschstruct policy_template_keyvalue {
9145c8b5eda526d05bd4a7ced20f6f6f2ff8df03Stephan Bosch const char *key;
9145c8b5eda526d05bd4a7ced20f6f6f2ff8df03Stephan Bosch const char *value;
9145c8b5eda526d05bd4a7ced20f6f6f2ff8df03Stephan Bosch};
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Boschstatic
7384b4e78eaab44693c985192276e31322155e32Stephan Boschint auth_policy_attribute_comparator(const struct policy_template_keyvalue *a,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch const struct policy_template_keyvalue *b)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch{
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch return strcmp(a->key, b->key);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch}
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic
7384b4e78eaab44693c985192276e31322155e32Stephan Boschint auth_policy_strptrcmp(const char *a0, const char *a1,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch const char *b0, const char *b1)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch{
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch i_assert(a0 <= a1 && b0 <= b1);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch return memcmp(a0, b0, I_MIN((a1-a0),(b1-b0)));
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch}
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic
7384b4e78eaab44693c985192276e31322155e32Stephan Boschvoid auth_policy_open_key(const char *key, string_t *template)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch{
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch const char *ptr;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch while((ptr = strchr(key, '/')) != NULL) {
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch str_append_c(template,'"');
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch json_append_escaped(template, t_strndup(key, (ptr-key)));
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch str_append_c(template,'"');
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch str_append_c(template,':');
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch str_append_c(template,'{');
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch key = ptr+1;
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch }
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch}
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Boschstatic
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Boschvoid auth_policy_close_key(const char *key, string_t *template)
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch{
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch while((key = strchr(key, '/')) != NULL) { str_append_c(template,'}'); key++; }
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch}
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Boschstatic
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Boschvoid auth_policy_open_and_close_to_key(const char *fromkey, const char *tokey, string_t *template)
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch{
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch const char *fptr,*tptr,*fdash,*tdash;
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch fptr = strrchr(fromkey, '/');
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch tptr = strrchr(tokey, '/');
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch if (fptr == NULL && tptr == NULL) return; /* nothing to do */
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch
30f35cf5d1e1374d7fab4231e86144fc106a8e79Stephan Bosch if (fptr == NULL && tptr != NULL) {
30f35cf5d1e1374d7fab4231e86144fc106a8e79Stephan Bosch auth_policy_open_key(tokey, template);
30f35cf5d1e1374d7fab4231e86144fc106a8e79Stephan Bosch return;
30f35cf5d1e1374d7fab4231e86144fc106a8e79Stephan Bosch }
30f35cf5d1e1374d7fab4231e86144fc106a8e79Stephan Bosch
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch if (fptr != NULL && tptr == NULL) {
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch str_truncate(template, str_len(template)-1);
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch auth_policy_close_key(fromkey, template);
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch str_append_c(template, ',');
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch return;
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch }
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch if (auth_policy_strptrcmp(fromkey, fptr, tokey, tptr) == 0) {
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch /* nothing to do, again */
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch return;
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch }
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch fptr = fromkey;
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch tptr = tokey;
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch while (fptr != NULL && tptr != NULL) {
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch fdash = strchr(fptr, '/');
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch tdash = strchr(tptr, '/');
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch if (fdash == NULL) {
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch auth_policy_open_key(tptr, template);
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch break;
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch }
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch if (tdash == NULL) {
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch str_truncate(template, str_len(template)-1);
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch auth_policy_close_key(fptr, template);
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch str_append_c(template, ',');
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch break;
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch }
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch if (auth_policy_strptrcmp(fptr, fdash, tptr, tdash) != 0) {
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch str_truncate(template, str_len(template)-1);
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch auth_policy_close_key(fptr, template);
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch str_append_c(template, ',');
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch auth_policy_open_key(tptr, template);
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch break;
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch }
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch fptr = fdash+1;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch tptr = tdash+1;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch }
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch}
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Boschvoid auth_policy_init(void)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch{
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch http_client_set.request_absolute_timeout_msecs = global_auth_settings->policy_server_timeout_msecs;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (global_auth_settings->debug)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch http_client_set.debug = 1;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch http_client = http_client_init(&http_client_set);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch /* prepare template */
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch ARRAY(struct policy_template_keyvalue) attribute_pairs;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch const struct policy_template_keyvalue *kvptr;
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch string_t *template = t_str_new(64);
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch const char **ptr;
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch const char *key = NULL;
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch const char **list = t_strsplit_spaces(global_auth_settings->policy_request_attributes, "= ");
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch t_array_init(&attribute_pairs, 8);
fe681e6db72f30bd754b622005bbe298e5ca775aTimo Sirainen for(ptr = list; *ptr != NULL; ptr++) {
fe681e6db72f30bd754b622005bbe298e5ca775aTimo Sirainen struct policy_template_keyvalue pair;
fe681e6db72f30bd754b622005bbe298e5ca775aTimo Sirainen if (key == NULL) {
fe681e6db72f30bd754b622005bbe298e5ca775aTimo Sirainen key = *ptr;
fe681e6db72f30bd754b622005bbe298e5ca775aTimo Sirainen } else {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch pair.key = key;
a991cfe2157e58ee43bc580f517ce9ef0dfb7acfStephan Bosch pair.value = *ptr;
a991cfe2157e58ee43bc580f517ce9ef0dfb7acfStephan Bosch key = NULL;
a991cfe2157e58ee43bc580f517ce9ef0dfb7acfStephan Bosch array_append(&attribute_pairs, &pair, 1);
a991cfe2157e58ee43bc580f517ce9ef0dfb7acfStephan Bosch }
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch }
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (key != NULL) {
a991cfe2157e58ee43bc580f517ce9ef0dfb7acfStephan Bosch i_fatal("auth_policy_request_attributes contains invalid value");
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch }
16eb9a737d42017fc875ef7b68afc25c3c9f8979Stephan Bosch
16eb9a737d42017fc875ef7b68afc25c3c9f8979Stephan Bosch /* then we sort it */
16eb9a737d42017fc875ef7b68afc25c3c9f8979Stephan Bosch array_sort(&attribute_pairs, auth_policy_attribute_comparator);
a991cfe2157e58ee43bc580f517ce9ef0dfb7acfStephan Bosch
fb1be3de0159d6a10e916ad992e2bc53be64c6d5Timo Sirainen /* and build a template string */
fb1be3de0159d6a10e916ad992e2bc53be64c6d5Timo Sirainen const char *prevkey = "";
129596c93692b21d6c6b1313b389774af24c2983Stephan Bosch
fca68889b287d8eed4babe72a231bd6079da012dStephan Bosch array_foreach(&attribute_pairs, kvptr) {
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen const char *kptr = strchr(kvptr->key, '/');
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen auth_policy_open_and_close_to_key(prevkey, kvptr->key, template);
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen str_append_c(template,'"');
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen json_append_escaped(template, (kptr != NULL?kptr+1:kvptr->key));
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch str_append_c(template,'"');
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch str_append_c(template,':');
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch str_append_c(template,'"');
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch str_append(template,kvptr->value);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch str_append_c(template,'"');
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch str_append_c(template,',');
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch prevkey = kvptr->key;
fc94140acba51adafedafbc8491a3223a51db7a8Stephan Bosch }
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch auth_policy_open_and_close_to_key(prevkey, "", template);
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch str_truncate(template, str_len(template)-1);
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch auth_policy_json_template = i_strdup(str_c(template));
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch}
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Boschvoid auth_policy_deinit(void)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch{
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (http_client != NULL)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch http_client_deinit(&http_client);
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch i_free(auth_policy_json_template);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch}
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Boschstatic
7384b4e78eaab44693c985192276e31322155e32Stephan Boschvoid auth_policy_finish(void *ctx)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch{
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch struct policy_lookup_ctx *context = ctx;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (context->parser != NULL) {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch const char *error ATTR_UNUSED;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch (void)json_parser_deinit(&(context->parser), &error);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch }
49287618521ff2c69385456de116e5d1581426c0Timo Sirainen if (context->http_request != NULL)
49287618521ff2c69385456de116e5d1581426c0Timo Sirainen http_client_request_abort(&(context->http_request));
49287618521ff2c69385456de116e5d1581426c0Timo Sirainen if (context->request != NULL)
49287618521ff2c69385456de116e5d1581426c0Timo Sirainen auth_request_unref(&context->request);
49287618521ff2c69385456de116e5d1581426c0Timo Sirainen}
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Boschstatic
30f35cf5d1e1374d7fab4231e86144fc106a8e79Stephan Boschvoid auth_policy_parse_response(struct policy_lookup_ctx *context)
30f35cf5d1e1374d7fab4231e86144fc106a8e79Stephan Bosch{
30f35cf5d1e1374d7fab4231e86144fc106a8e79Stephan Bosch enum json_type type;
30f35cf5d1e1374d7fab4231e86144fc106a8e79Stephan Bosch const char *value;
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch int ret;
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch while((ret = json_parse_next(context->parser, &type, &value)) == 1) {
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch if (context->parse_state == POLICY_RESULT) {
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch if (type != JSON_TYPE_OBJECT_KEY)
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch break;
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch else if (strcmp(value, "status") == 0)
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch context->parse_state = POLICY_RESULT_VALUE_STATUS;
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch else if (strcmp(value, "msg") == 0)
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch context->parse_state = POLICY_RESULT_VALUE_MESSAGE;
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch else break;
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch } else if (context->parse_state == POLICY_RESULT_VALUE_STATUS) {
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch if (type != JSON_TYPE_NUMBER || str_to_int(value, &(context->result)) != 0)
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch break;
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch context->parse_state = POLICY_RESULT;
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch } else if (context->parse_state == POLICY_RESULT_VALUE_MESSAGE) {
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch if (type != JSON_TYPE_STRING)
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch break;
4c4c4a740bbb1b674d4b0dae009d1919f8ad96b7Stephan Bosch if (*value != '\0')
4c4c4a740bbb1b674d4b0dae009d1919f8ad96b7Stephan Bosch context->message = p_strdup(context->pool, value);
4c4c4a740bbb1b674d4b0dae009d1919f8ad96b7Stephan Bosch context->parse_state = POLICY_RESULT;
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch } else {
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch break;
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch }
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch }
b99130e4cf4af4e6b103b949456222f3a2dff424Timo Sirainen
b99130e4cf4af4e6b103b949456222f3a2dff424Timo Sirainen if (ret == 0 && !context->payload->eof)
b99130e4cf4af4e6b103b949456222f3a2dff424Timo Sirainen return;
b99130e4cf4af4e6b103b949456222f3a2dff424Timo Sirainen
87c121a4c05b9cee46f1f757ec6999d441519abfStephan Bosch context->parse_error = TRUE;
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch io_remove(&(context->io));
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (context->payload->stream_errno != 0) {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch auth_request_log_error(context->request, "policy",
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen "Error reading policy server result: %s",
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen i_stream_get_error(context->payload));
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen } else if (ret == 0 && context->payload->eof) {
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen auth_request_log_error(context->request, "policy",
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen "Policy server result was too short");
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen } else if (ret == 1) {
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen auth_request_log_error(context->request, "policy",
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen "Policy server response was malformed");
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen } else {
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen const char *error = "unknown";
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen if (json_parser_deinit(&(context->parser), &error) != 0)
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen auth_request_log_error(context->request, "policy",
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen "Policy server response JSON parse error: %s", error);
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen else if (context->parse_state == POLICY_RESULT)
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen context->parse_error = FALSE;
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen }
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen i_stream_unref(&(context->payload));
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen if (context->parse_error) {
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen context->result = (context->set->policy_reject_on_fail ? -1 : 0);
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen }
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen context->request->policy_refusal = FALSE;
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen if (context->result < 0) {
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen if (context->message != NULL) {
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen /* set message here */
84740b03d3ee9e96a2e446a54729188764c99292Timo Sirainen auth_request_log_debug(context->request, "policy",
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch "Policy response %d with message: %s",
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch context->result, context->message);
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch auth_request_set_field(context->request, "reason", context->message, NULL);
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch }
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch context->request->policy_refusal = TRUE;
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch } else {
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch auth_request_log_debug(context->request, "policy",
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch "Policy response %d", context->result);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch }
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
4521d35c263add6af3f1ae55b3760291767ce50cTimo Sirainen if (context->request->policy_refusal == TRUE && context->set->verbose == TRUE) {
4521d35c263add6af3f1ae55b3760291767ce50cTimo Sirainen auth_request_log_info(context->request, "policy", "Authentication failure due to policy server refusal%s%s",
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch (context->message!=NULL?": ":""),
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen (context->message!=NULL?context->message:""));
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch }
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen if (context->callback != NULL) {
4521d35c263add6af3f1ae55b3760291767ce50cTimo Sirainen context->callback(context->result, context->callback_context);
4521d35c263add6af3f1ae55b3760291767ce50cTimo Sirainen }
dde71564d306d07cba63bdf0f40996ffb90ca47aTimo Sirainen};
dde71564d306d07cba63bdf0f40996ffb90ca47aTimo Sirainen
dde71564d306d07cba63bdf0f40996ffb90ca47aTimo Sirainenstatic
4521d35c263add6af3f1ae55b3760291767ce50cTimo Sirainenvoid auth_policy_process_response(const struct http_response *response,
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen void *ctx)
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen{
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen struct policy_lookup_ctx *context = ctx;
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch context->payload = response->payload;
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch
65c0e43da8cfc730eeb4634f8aa384081bbfa4e7Timo Sirainen if ((response->status / 10) != 20) {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch auth_request_log_error(context->request, "policy",
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch "Policy server HTTP error: %d %s", response->status, response->reason);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch if (context->callback != NULL)
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch context->callback(context->result, context->callback_context);
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch return;
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch }
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch if (response->payload == NULL) {
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch if (context->expect_result)
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch auth_request_log_error(context->request, "policy",
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch "Policy server result was empty");
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch if (context->callback != NULL)
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch context->callback(context->result, context->callback_context);
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch return;
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch }
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch if (context->expect_result) {
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch i_stream_ref(response->payload);
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch context->io = io_add_istream(response->payload, auth_policy_parse_response, context);
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch context->parser = json_parser_init(response->payload);
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch auth_policy_parse_response(ctx);
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch } else {
30f35cf5d1e1374d7fab4231e86144fc106a8e79Stephan Bosch auth_request_log_debug(context->request, "policy",
30f35cf5d1e1374d7fab4231e86144fc106a8e79Stephan Bosch "Policy response %d", context->result);
30f35cf5d1e1374d7fab4231e86144fc106a8e79Stephan Bosch if (context->callback != NULL)
30f35cf5d1e1374d7fab4231e86144fc106a8e79Stephan Bosch context->callback(context->result, context->callback_context);
30f35cf5d1e1374d7fab4231e86144fc106a8e79Stephan Bosch }
30f35cf5d1e1374d7fab4231e86144fc106a8e79Stephan Bosch}
30f35cf5d1e1374d7fab4231e86144fc106a8e79Stephan Bosch
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Boschstatic
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Boschvoid auth_policy_send_request(struct policy_lookup_ctx *context)
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch{
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch const char *error;
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch struct http_url *url;
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch if (http_url_parse(context->url, NULL, HTTP_URL_ALLOW_USERINFO_PART,
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch context->pool, &url, &error) != 0) {
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch auth_request_log_error(context->request, "policy",
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch "Could not parse url %s: %s", context->url, error);
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch auth_policy_finish(context);
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch return;
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch }
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch context->http_request = http_client_request_url(http_client,
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch "POST", url, auth_policy_process_response, (void*)context);
de0181258ab66b527ad8dc7e51a8efa76b4658d0Stephan Bosch http_client_request_set_destroy_callback(context->http_request, auth_policy_finish, context);
de0181258ab66b527ad8dc7e51a8efa76b4658d0Stephan Bosch http_client_request_add_header(context->http_request, "Content-Type", "application/json");
de0181258ab66b527ad8dc7e51a8efa76b4658d0Stephan Bosch if (*context->set->policy_server_api_header != 0) {
de0181258ab66b527ad8dc7e51a8efa76b4658d0Stephan Bosch const char *ptr;
de0181258ab66b527ad8dc7e51a8efa76b4658d0Stephan Bosch if ((ptr = strstr(context->set->policy_server_api_header, ":")) != NULL) {
de0181258ab66b527ad8dc7e51a8efa76b4658d0Stephan Bosch const char *header = t_strcut(context->set->policy_server_api_header, ':');
de0181258ab66b527ad8dc7e51a8efa76b4658d0Stephan Bosch http_client_request_add_header(context->http_request, header, ptr + 1);
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch } else {
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch http_client_request_add_header(context->http_request,
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch "X-API-Key", context->set->policy_server_api_header);
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch }
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch }
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch if (url->user != NULL) {
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch /* allow empty password */
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch http_client_request_set_auth_simple(context->http_request, url->user,
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch (url->password != NULL ? url->password : ""));
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch }
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch struct istream *is = i_stream_create_from_buffer(context->json);
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch http_client_request_set_payload(context->http_request, is, FALSE);
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch i_stream_unref(&is);
19db4c57fd7acc9e54e5724ccfa0633a5665dfefTimo Sirainen http_client_request_submit(context->http_request);
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch auth_request_ref(context->request);
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch}
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Boschstatic
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Boschconst char *auth_policy_escape_function(const char *string,
93cc87bb22386e020cee1093b6bd59295e0b33f0Stephan Bosch const struct auth_request *auth_request ATTR_UNUSED)
42630b23d5a1b03cf6db4eaa2eb21e3ec4033b2cTimo Sirainen{
42630b23d5a1b03cf6db4eaa2eb21e3ec4033b2cTimo Sirainen string_t *tmp = t_str_new(64);
42630b23d5a1b03cf6db4eaa2eb21e3ec4033b2cTimo Sirainen json_append_escaped(tmp, string);
42630b23d5a1b03cf6db4eaa2eb21e3ec4033b2cTimo Sirainen return str_c(tmp);
42630b23d5a1b03cf6db4eaa2eb21e3ec4033b2cTimo Sirainen}
b2a3fbfe1b436123bbe1849eeeef9bb0c28b1f90Timo Sirainen
b2a3fbfe1b436123bbe1849eeeef9bb0c28b1f90Timo Sirainenstatic
b2a3fbfe1b436123bbe1849eeeef9bb0c28b1f90Timo Sirainenconst struct var_expand_table *policy_get_var_expand_table(struct auth_request *auth_request,
b2a3fbfe1b436123bbe1849eeeef9bb0c28b1f90Timo Sirainen const char *hashed_password)
b2a3fbfe1b436123bbe1849eeeef9bb0c28b1f90Timo Sirainen{
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen struct var_expand_table *table;
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen unsigned int count = 1;
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen table = auth_request_get_var_expand_table_full(auth_request, auth_policy_escape_function,
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen &count);
1d048c5050f03c24251e5af8087e640de21b2d62Timo Sirainen table[0].key = '\0';
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch table[0].long_key = "hashed_password";
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch table[0].value = hashed_password;
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch if (table[0].value != NULL)
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch table[0].value = auth_policy_escape_function(table[0].value, auth_request);
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch return table;
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch}
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Boschstatic
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Boschvoid auth_policy_create_json(struct policy_lookup_ctx *context,
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch const char *password, bool include_success)
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch{
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch const struct var_expand_table *var_table;
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch context->json = str_new(context->pool, 64);
6ee9ce5ed955a1283dc22ad28980bf9cc23d4c4eStephan Bosch unsigned char *ptr;
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch const struct hash_method *digest = hash_method_lookup(context->set->policy_hash_mech);
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch i_assert(digest != NULL);
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch void *ctx = t_malloc_no0(digest->context_size);
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch string_t *buffer = t_str_new(64);
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch digest->init(ctx);
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch digest->loop(ctx,
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch context->set->policy_hash_nonce,
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch strlen(context->set->policy_hash_nonce));
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch /* use +1 to make sure \0 gets included */
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch digest->loop(ctx, context->request->user, strlen(context->request->user) + 1);
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch if (password != NULL)
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch digest->loop(ctx, password, strlen(password));
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch ptr = (unsigned char*)str_c_modifiable(buffer);
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch digest->result(ctx, ptr);
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch str_truncate(buffer, digest->digest_size);
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch if (context->set->policy_hash_truncate > 0) {
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch buffer_truncate_rshift_bits(buffer, context->set->policy_hash_truncate);
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch }
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch const char *hashed_password = binary_to_hex(str_data(buffer), str_len(buffer));
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch str_append_c(context->json, '{');
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch var_table = policy_get_var_expand_table(context->request, hashed_password);
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch const char *error;
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch if (auth_request_var_expand_with_table(context->json, auth_policy_json_template,
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch context->request, var_table,
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch auth_policy_escape_function, &error) <= 0) {
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch auth_request_log_error(context->request, "policy",
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch "Failed to expand auth policy template: %s", error);
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch }
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch if (include_success) {
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch str_append(context->json, ",\"success\":");
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch if (!context->request->failed && context->request->successful &&
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch !context->request->internal_failure)
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch str_append(context->json, "true");
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch else
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch str_append(context->json, "false");
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch str_append(context->json, ",\"policy_reject\":");
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch str_append(context->json, context->request->policy_refusal ? "true" : "false");
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch }
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch str_append_c(context->json, '}');
6d573191bea1a64d6046be070487a5705a2d0204Stephan Bosch auth_request_log_debug(context->request, "policy",
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch "Policy server request JSON: %s", str_c(context->json));
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch}
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Boschstatic
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Boschvoid auth_policy_url(struct policy_lookup_ctx *context, const char *command)
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch{
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch size_t len = strlen(context->set->policy_server_url);
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch if (context->set->policy_server_url[len-1] == '&')
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch context->url = p_strdup_printf(context->pool, "%scommand=%s",
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch context->set->policy_server_url, command);
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch else
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch context->url = p_strdup_printf(context->pool, "%s?command=%s",
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch context->set->policy_server_url, command);
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch}
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Boschvoid auth_policy_check(struct auth_request *request, const char *password,
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch auth_policy_callback_t cb, void *context)
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch{
a62fe4b300e2f591e939993aec4cac1e7ae30ad1Stephan Bosch if (request->master != NULL || *(request->set->policy_server_url) == '\0') {
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch cb(0, context);
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch return;
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch }
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch struct policy_lookup_ctx *ctx = p_new(request->pool, struct policy_lookup_ctx, 1);
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch ctx->pool = request->pool;
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch ctx->request = request;
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch ctx->expect_result = TRUE;
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch ctx->callback = cb;
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch ctx->callback_context = context;
b66def5dadd3e7c250313a938d26ad113663f86bStephan Bosch ctx->set = request->set;
e47c2f17d8136c4d972d1074a3f84ba2ecef4fdcStephan Bosch
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch auth_policy_url(ctx, "allow");
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch ctx->result = (ctx->set->policy_reject_on_fail ? -1 : 0);
57962a937b214be3a131f78005509afaa26fe4bfTimo Sirainen auth_request_log_debug(request, "policy", "Policy request %s", ctx->url);
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch T_BEGIN {
7384b4e78eaab44693c985192276e31322155e32Stephan Bosch auth_policy_create_json(ctx, password, FALSE);
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch } T_END;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch auth_policy_send_request(ctx);
a991cfe2157e58ee43bc580f517ce9ef0dfb7acfStephan Bosch}
a991cfe2157e58ee43bc580f517ce9ef0dfb7acfStephan Bosch
31fa529029f35f65451fb1d119ed1d5435b62e46Timo Sirainenvoid auth_policy_report(struct auth_request *request)
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch{
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch if (request->master != NULL)
4219de12b28f1936219e27501b9c4b27a4f8d53cStephan Bosch return;
a991cfe2157e58ee43bc580f517ce9ef0dfb7acfStephan Bosch
6bc9fb43cc1ac24693d030a6cbfa43bc7cbc82cbTimo Sirainen if (*(request->set->policy_server_url) == '\0')
a991cfe2157e58ee43bc580f517ce9ef0dfb7acfStephan Bosch return;
a991cfe2157e58ee43bc580f517ce9ef0dfb7acfStephan Bosch struct policy_lookup_ctx *ctx = p_new(request->pool, struct policy_lookup_ctx, 1);
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch ctx->pool = request->pool;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch ctx->request = request;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch ctx->expect_result = FALSE;
069b28a2ef54072a221fe4ac67aaeb4e83fee6c1Timo Sirainen ctx->set = request->set;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch auth_policy_url(ctx, "report");
791fb70b3255a11a91ce0c2dc3ae1460d4cf8459Timo Sirainen auth_request_log_debug(request, "policy", "Policy request %s", ctx->url);
791fb70b3255a11a91ce0c2dc3ae1460d4cf8459Timo Sirainen T_BEGIN {
aab7256cdcfb7abd01c822e3df8dd77a30c572e0Stephan Bosch auth_policy_create_json(ctx, request->mech_password, TRUE);
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch } T_END;
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch auth_policy_send_request(ctx);
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch}
eb325a5a90c1d2655e74972bde0de6a699d2c864Stephan Bosch