/* * ejabberd external authentication program * * (c) Alexander Vdolainen 2013, 2018, 2019, 2021 * * this is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * this is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see ."; * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include unsigned long djb_hash(const char *s) { unsigned long hash = 5381; int c; while((c = *s++)) hash = ((hash << 5) + hash) + c; return hash; } #define MAX_SUPPL_DATA 64 #define PRG_NAME "daemon for ejabberd to provide IMAPS/SMTPS auth" static void print_help(const char *cname) { fprintf(stdout, "\n%s - %s\n\n", cname, PRG_NAME); fprintf(stdout, "USAGE:\n"); fprintf(stdout, "\t%s -S | --smtp-host -s | --smtp-port " "-I | --imap-host -i | --imap-port ", cname); fprintf(stdout, "\n\n\t%s -h | --help\n", cname); fprintf(stdout, "\nNOTE: This program is designed to be used from ejabberd only.\n"); return; } int main(int argc, char **argv) { char *smtp_host, *smtp_port, *imap_host, *imap_port; char msgbuf[MAX_USER_LEN + MAX_DOMAIN_LEN + MAX_PASSWORD_LEN + MAX_SUPPL_DATA]; struct tlsport connection; struct ejabber_msg m; int opt, msgbuflen = 0; smtp_host = smtp_port = imap_port = imap_host = NULL; while(1) { int option_index = 0; static struct option long_options[] = { {"help", no_argument, NULL, 'h'}, {"smtp-host", required_argument, NULL, 'S'}, {"smtp-port", required_argument, NULL, 's'}, {"imap-host", required_argument, NULL, 'I'}, {"imap-port", required_argument, NULL, 'i'}, {NULL, 0, NULL, 0}, }; if((opt = getopt_long(argc, argv, "hS:s:I:i:", long_options, &option_index)) == -1) break; switch(opt) { case 'h': print_help(argv[0]); return 0; break; case 'S': smtp_host = optarg; break; case 's': smtp_port = optarg; break; case 'I': imap_host = optarg; break; case 'i': imap_port = optarg; break; default: abort(); break; } } /* arguments check up */ if(!smtp_host || !smtp_port) { fprintf(stderr, "Error: SMTPs information is not complete.\n"); main_einval_moimoi: print_help(argv[0]); return EINVAL; } if(!imap_port || !imap_host) { fprintf(stderr, "Error: IMAPs information is not complete.\n"); goto main_einval_moimoi; } /* take care about space borrowed from stack */ msgbuflen = MAX_USER_LEN + MAX_DOMAIN_LEN + MAX_PASSWORD_LEN + MAX_SUPPL_DATA; memset(msgbuf, 0, msgbuflen); /* libs init */ ssllib_init(); /* main loop */ while(eport_read(stdin, msgbuf, msgbuflen) > 0) { opt = eport_ejabberd_msgread(msgbuf, msgbuflen, &m); if(opt > 0) { abort_parsing: fprintf(stderr, "Error: message isn't valid.\nExiting.\n"); ssllib_free(); abort(); } /* deal with message */ switch(ejabber_msg_event(&m)) { case EJA_AUTH: if(opt != 3) goto abort_parsing; /* connect to IMAPs */ if(tls_connect(imap_host, imap_port, &connection)) { fprintf(stderr, "Error: unable to connect to IMAPs.\n"); opt = -1; } else { opt = imap_auth(&connection, &m); tls_close(&connection); } break; case EJA_ISUSER: if(opt != 2) goto abort_parsing; /* connect to SMTPs */ if(tls_connect(smtp_host, smtp_port, &connection)) { fprintf(stderr, "Error: unable to connect to SMTPs.\n"); opt = -1; } else { opt = smtp_checkuser(&connection, &m, smtp_host); tls_close(&connection); } break; case EJA_SETPASS: case EJA_TRYREGISTER: case EJA_REMOVEUSER: case EJA_REMOVEUSER3: /* still aren't supported by the program */ fprintf(stderr, "Error: This type of message are not supported.\n"); opt = -1; break; case EJA_UNKNOWN: default: /* something goes wrong with message */ goto abort_parsing; break; } /* finally, reply ... */ eport_write(stdout, (char *)((int16_t *)&opt), sizeof(int16_t)); } ssllib_free(); return 0; }