Compare commits
10 Commits
1aff05ea29
...
923a4aaf6f
Author | SHA1 | Date |
---|---|---|
Alexander Vdolainen | 923a4aaf6f | 4 years ago |
Alexander Vdolainen | b833c9891e | 4 years ago |
Alexander Vdolainen | 1facc7f484 | 4 years ago |
Alexander Vdolainen | cbfc031438 | 4 years ago |
Alexander Vdolainen | 591ee61a6f | 4 years ago |
Alexander Vdolainen | 51e43425ce | 4 years ago |
Alexander Vdolainen | c0f4b10721 | 4 years ago |
Alexander Vdolainen | d737e5f836 | 4 years ago |
Alexander Vdolainen | 109d071fed | 4 years ago |
Alexander Vdolainen | 5e009b70d3 | 4 years ago |
@ -0,0 +1,277 @@
|
|||||||
|
/*
|
||||||
|
* ejabberd external authentication program
|
||||||
|
*
|
||||||
|
* (c) Alexander Vdolainen 2013, 2018, 2019, 2021 <alex@vapaa.xyz>
|
||||||
|
*
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.";
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <netdb.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <openssl/ssl.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
|
#include <ejabbermsg.h>
|
||||||
|
#include <eport.h>
|
||||||
|
|
||||||
|
#define PRG_NAME "ejabberauth erlang port function test"
|
||||||
|
|
||||||
|
extern int ejda_username_split(char *buf, char **user, char **domain);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Test is simple - create a pipe, write a message with eport interface
|
||||||
|
* read it, reply with erport interface.
|
||||||
|
* for supported commands replies ok, fail otherwise
|
||||||
|
*/
|
||||||
|
|
||||||
|
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 -u | --user <username>"
|
||||||
|
" -P | --password <password> [ -v | --verbose ]",
|
||||||
|
cname);
|
||||||
|
fprintf(stdout, "\n\n\t%s -h | --help\n", cname);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *tfmt[] = {
|
||||||
|
"auth:%s:%s:%s",
|
||||||
|
"isuser:%s:%s",
|
||||||
|
"setpass:%s:%s:%s",
|
||||||
|
"tryregister:%s:%s:%s",
|
||||||
|
"removeuser:%s:%s",
|
||||||
|
"removeuser3:%s:%s:%s",
|
||||||
|
"weird-stuff",
|
||||||
|
};
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
char *domain, *user, *password;
|
||||||
|
char *utbuf = NULL, *msgbuf = NULL;
|
||||||
|
int verbose = 0, opt, msgbuf_len = 0, items = 0;
|
||||||
|
FILE *inp, *outp;
|
||||||
|
int pfd[2];
|
||||||
|
struct ejabber_msg m;
|
||||||
|
|
||||||
|
domain = user = password = NULL;
|
||||||
|
inp = outp = NULL;
|
||||||
|
|
||||||
|
/* parse options */
|
||||||
|
while(1) {
|
||||||
|
int option_index = 0;
|
||||||
|
static struct option long_options[] = {
|
||||||
|
{"help", no_argument, NULL, 'h'},
|
||||||
|
{"user", required_argument, NULL, 'u'},
|
||||||
|
{"password", required_argument, NULL, 'P'},
|
||||||
|
{"verbose", no_argument, NULL, 'v'},
|
||||||
|
{NULL, 0, NULL, 0},
|
||||||
|
};
|
||||||
|
|
||||||
|
if((opt = getopt_long(argc, argv, "hu:P:v", long_options,
|
||||||
|
&option_index)) == -1) break;
|
||||||
|
switch(opt) {
|
||||||
|
case 'h':
|
||||||
|
/* print help information and exit */
|
||||||
|
print_help(argv[0]);
|
||||||
|
return 0;
|
||||||
|
break;
|
||||||
|
case 'u': user = optarg; break;
|
||||||
|
case 'P': password = optarg; break;
|
||||||
|
case 'v': verbose = 1; break;
|
||||||
|
default: abort(); break; /* something that's shouldn't ever happen */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!user) {
|
||||||
|
fprintf(stderr, "Error: no username is given.\n");
|
||||||
|
main_einval:
|
||||||
|
print_help(argv[0]);
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
if(!password) {
|
||||||
|
fprintf(stderr, "Error: no password provided.\n");
|
||||||
|
goto main_einval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* split user name */
|
||||||
|
opt = strlen(user) + sizeof(char);
|
||||||
|
if((utbuf = malloc(opt)) == NULL) {
|
||||||
|
fprintf(stderr, "Error: not enough memory\n");
|
||||||
|
return ENOMEM;
|
||||||
|
} else {
|
||||||
|
memset(utbuf, '\0', opt);
|
||||||
|
memcpy(utbuf, user, opt - sizeof(char));
|
||||||
|
if(ejda_username_split(utbuf, &user, &domain)) {
|
||||||
|
fprintf(stderr, "Error: username is invalid.\n");
|
||||||
|
free(utbuf);
|
||||||
|
return EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* allocate a message buffer */
|
||||||
|
msgbuf_len = strlen("removeuser3") + strlen(user) + strlen(domain) +
|
||||||
|
strlen(password) + sizeof(uint16_t) + sizeof(char)*4;
|
||||||
|
if((msgbuf = malloc(msgbuf_len)) == NULL) {
|
||||||
|
fprintf(stderr, "Error: not enough memory\n");
|
||||||
|
free(utbuf);
|
||||||
|
return ENOMEM;
|
||||||
|
} else memset(msgbuf, 0, msgbuf_len);
|
||||||
|
|
||||||
|
if(pipe(pfd) == -1) {
|
||||||
|
fprintf(stderr, "Error: cannot create pipe\n");
|
||||||
|
opt = -1;
|
||||||
|
goto finit0;
|
||||||
|
} else {
|
||||||
|
opt = -1;
|
||||||
|
inp = fdopen(pfd[0], "r"); /* port to read from */
|
||||||
|
outp = fdopen(pfd[1], "w"); /* port to write to */
|
||||||
|
if(!inp || !outp) {
|
||||||
|
fprintf(stderr, "Cannot create file stream.\n");
|
||||||
|
goto finit1;
|
||||||
|
} else opt = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
/* do the message write */
|
||||||
|
switch(opt) {
|
||||||
|
case 0:
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
case 5:
|
||||||
|
snprintf(msgbuf, msgbuf_len, tfmt[opt], user, domain, password);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
case 4:
|
||||||
|
snprintf(msgbuf, msgbuf_len, tfmt[opt], user, domain);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
snprintf(msgbuf, msgbuf_len, tfmt[opt]);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
opt = -1;
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
if(verbose) {
|
||||||
|
fprintf(stdout, "Push (%s) ... ", msgbuf);
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
if(eport_write(outp, msgbuf, strlen(msgbuf)) < 0) {
|
||||||
|
opt = -1;
|
||||||
|
if(verbose) fprintf(stdout, "fail\n");
|
||||||
|
else fprintf(stderr, "Error write to out port.\n");
|
||||||
|
} else {
|
||||||
|
if(verbose) fprintf(stdout, "ok\n");
|
||||||
|
/* try to read */
|
||||||
|
if(verbose) {
|
||||||
|
fprintf(stdout, "Pull ... ");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
if(eport_read(inp, msgbuf, msgbuf_len) < 0) {
|
||||||
|
opt = -1;
|
||||||
|
if(verbose) fprintf(stdout, "fail\n");
|
||||||
|
else fprintf(stderr, "Error on reading in port.\n");
|
||||||
|
} else if((items = eport_ejabberd_msgread(msgbuf, msgbuf_len, &m)) == -1) {
|
||||||
|
if(verbose) fprintf(stdout, "fail on parsing\n");
|
||||||
|
else fprintf(stderr, "Error on parsing data from in port.\n");
|
||||||
|
opt = -1;
|
||||||
|
}
|
||||||
|
if(opt != -1) {
|
||||||
|
if(verbose) {
|
||||||
|
fprintf(stdout, "ok, has been parsed\n");
|
||||||
|
fprintf(stdout, "Checking data ... ");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
/* check the data first */
|
||||||
|
switch(items) {
|
||||||
|
case 3:
|
||||||
|
if(strcmp(m.password, password)) {
|
||||||
|
opt = -1;
|
||||||
|
if(verbose) fprintf(stdout, "password data is incorrect\n");
|
||||||
|
else fprintf(stderr, "Password data is invalid.\n");
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
if(strcmp(m.user, user)) {
|
||||||
|
opt = -1;
|
||||||
|
if(verbose) fprintf(stdout, "user data is incorrect\n");
|
||||||
|
else fprintf(stderr, "User data is invalid.\n");
|
||||||
|
}
|
||||||
|
if(strcmp(m.domain, domain)) {
|
||||||
|
opt = -1;
|
||||||
|
if(verbose) fprintf(stdout, "domain data is incorrect\n");
|
||||||
|
else fprintf(stderr, "Domain data is invalid.\n");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 0:
|
||||||
|
default:
|
||||||
|
if(opt != 6) opt = -1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(opt != -1) { /* check command */
|
||||||
|
if(verbose) {
|
||||||
|
fprintf(stdout, "ok\n");
|
||||||
|
fprintf(stdout, "Check event ... ");
|
||||||
|
fflush(stdout);
|
||||||
|
}
|
||||||
|
switch(opt) {
|
||||||
|
case 0: if(m.aev != EJA_AUTH) opt = -1; break;
|
||||||
|
case 1: if(m.aev != EJA_ISUSER) opt = -1; break;
|
||||||
|
case 2: if(m.aev != EJA_SETPASS) opt = -1; break;
|
||||||
|
case 3: if(m.aev != EJA_TRYREGISTER) opt = -1; break;
|
||||||
|
case 4: if(m.aev != EJA_REMOVEUSER) opt = -1; break;
|
||||||
|
case 5: if(m.aev != EJA_REMOVEUSER3) opt = -1; break;
|
||||||
|
default:
|
||||||
|
opt = -1;
|
||||||
|
}
|
||||||
|
if(opt == -1) {
|
||||||
|
if(verbose) fprintf(stdout, "fail\n");
|
||||||
|
else fprintf(stderr, "Event cmd invalid.\n");
|
||||||
|
} else {
|
||||||
|
if(verbose) fprintf(stdout, "ok\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(msgbuf, 0, msgbuf_len);
|
||||||
|
|
||||||
|
if(opt != -1) opt++;
|
||||||
|
} while((opt < 6) && (opt != -1));
|
||||||
|
|
||||||
|
if(opt > 0) opt = 0;
|
||||||
|
|
||||||
|
finit1:
|
||||||
|
if(!inp) close(pfd[0]);
|
||||||
|
else fclose(inp);
|
||||||
|
if(!outp) close(pfd[1]);
|
||||||
|
else fclose(outp);
|
||||||
|
finit0:
|
||||||
|
free(utbuf);
|
||||||
|
free(msgbuf);
|
||||||
|
|
||||||
|
return opt;
|
||||||
|
}
|
Loading…
Reference in New Issue