mirror of
https://github.com/vanhauser-thc/thc-hydra.git
synced 2025-07-07 13:31:39 -07:00
rtsp
This commit is contained in:
parent
08fedd8583
commit
b6f3e73b65
5 changed files with 4231 additions and 4068 deletions
|
@ -16,7 +16,7 @@ SRC = hydra-vnc.c hydra-pcnfs.c hydra-rexec.c hydra-nntp.c hydra-socks5.c \
|
||||||
hydra-oracle.c hydra-vmauthd.c hydra-asterisk.c hydra-firebird.c hydra-afp.c hydra-ncp.c \
|
hydra-oracle.c hydra-vmauthd.c hydra-asterisk.c hydra-firebird.c hydra-afp.c hydra-ncp.c \
|
||||||
hydra-oracle-sid.c hydra-http-proxy.c hydra-http-form.c hydra-irc.c \
|
hydra-oracle-sid.c hydra-http-proxy.c hydra-http-form.c hydra-irc.c \
|
||||||
hydra-rdp.c hydra-s7-300.c hydra-redis.c \
|
hydra-rdp.c hydra-s7-300.c hydra-redis.c \
|
||||||
crc32.c d3des.c bfg.c ntlm.c sasl.c hmacmd5.c hydra-mod.c
|
crc32.c d3des.c bfg.c ntlm.c sasl.c hmacmd5.c hydra-mod.c hydra-rtsp.c
|
||||||
OBJ = hydra-vnc.o hydra-pcnfs.o hydra-rexec.o hydra-nntp.o hydra-socks5.o \
|
OBJ = hydra-vnc.o hydra-pcnfs.o hydra-rexec.o hydra-nntp.o hydra-socks5.o \
|
||||||
hydra-telnet.o hydra-cisco.o hydra-http.o hydra-ftp.o hydra-imap.o \
|
hydra-telnet.o hydra-cisco.o hydra-http.o hydra-ftp.o hydra-imap.o \
|
||||||
hydra-pop3.o hydra-smb.o hydra-icq.o hydra-cisco-enable.o hydra-ldap.o \
|
hydra-pop3.o hydra-smb.o hydra-icq.o hydra-cisco-enable.o hydra-ldap.o \
|
||||||
|
@ -27,7 +27,7 @@ OBJ = hydra-vnc.o hydra-pcnfs.o hydra-rexec.o hydra-nntp.o hydra-socks5.o \
|
||||||
hydra-oracle-sid.o hydra-oracle.o hydra-vmauthd.o hydra-asterisk.o hydra-firebird.o hydra-afp.o hydra-ncp.o \
|
hydra-oracle-sid.o hydra-oracle.o hydra-vmauthd.o hydra-asterisk.o hydra-firebird.o hydra-afp.o hydra-ncp.o \
|
||||||
hydra-http-proxy.o hydra-http-form.o hydra-irc.o hydra-redis.o \
|
hydra-http-proxy.o hydra-http-form.o hydra-irc.o hydra-redis.o \
|
||||||
hydra-rdp.o hydra-s7-300.c \
|
hydra-rdp.o hydra-s7-300.c \
|
||||||
crc32.o d3des.o bfg.o ntlm.o sasl.o hmacmd5.o hydra-mod.o
|
crc32.o d3des.o bfg.o ntlm.o sasl.o hmacmd5.o hydra-mod.o hydra-rtsp.o
|
||||||
BINS = hydra pw-inspector
|
BINS = hydra pw-inspector
|
||||||
|
|
||||||
EXTRA_DIST = README README.arm README.palm CHANGES TODO INSTALL LICENSE \
|
EXTRA_DIST = README README.arm README.palm CHANGES TODO INSTALL LICENSE \
|
||||||
|
|
247
hydra-rtsp.c
Normal file
247
hydra-rtsp.c
Normal file
|
@ -0,0 +1,247 @@
|
||||||
|
//
|
||||||
|
// hydra-rtsp.c
|
||||||
|
// hydra-rtsp
|
||||||
|
//
|
||||||
|
// Created by Javier Sánchez on 18/04/15.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include "hydra-mod.h"
|
||||||
|
#include <string.h>
|
||||||
|
#include "sasl.h"
|
||||||
|
|
||||||
|
extern char *HYDRA_EXIT;
|
||||||
|
char *buf;
|
||||||
|
char packet[500];
|
||||||
|
char packet2[500];
|
||||||
|
|
||||||
|
int is_Unauthorized(char * s){
|
||||||
|
|
||||||
|
if (strstr(s,"401 Unauthorized")!= NULL){
|
||||||
|
return 1;
|
||||||
|
}else{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int is_NotFound(char * s){
|
||||||
|
|
||||||
|
if (strstr(s,"404 Stream Not Found")!= NULL){
|
||||||
|
return 1;
|
||||||
|
}else{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int is_Authorized(char * s){
|
||||||
|
|
||||||
|
if (strstr(s,"200 OK")!= NULL){
|
||||||
|
return 1;
|
||||||
|
}else{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int use_Basic_Auth(char * s){
|
||||||
|
|
||||||
|
if(strstr(s,"WWW-Authenticate: Basic")!=NULL){
|
||||||
|
return 1;
|
||||||
|
}else{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int use_Digest_Auth(char * s){
|
||||||
|
|
||||||
|
if(strstr(s,"WWW-Authenticate: Digest")!=NULL){
|
||||||
|
return 1;
|
||||||
|
}else{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void create_core_packet(int control,char* ip, int port){
|
||||||
|
|
||||||
|
char buffer[500];
|
||||||
|
char * target=hydra_address2string(ip);
|
||||||
|
if (control==0){
|
||||||
|
if (strlen(packet) <= 0){
|
||||||
|
sprintf(packet, "DESCRIBE rtsp://%s:%i RTSP/1.0\r\nCSeq: 2\r\n\r\n",target,port);
|
||||||
|
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if (strlen(packet2) <= 0){
|
||||||
|
sprintf(packet2, "DESCRIBE rtsp://%s:%i RTSP/1.0\r\nCSeq: 3\r\n",target,port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int start_rtsp(int s, char *ip, int port, unsigned char options, char *miscptr, FILE * fp)
|
||||||
|
{
|
||||||
|
char *empty = "";
|
||||||
|
char *login, *pass, buffer[500],buffer2[500];
|
||||||
|
|
||||||
|
char * lresp;
|
||||||
|
|
||||||
|
if (strlen(login = hydra_get_next_login()) == 0)
|
||||||
|
login = empty;
|
||||||
|
if (strlen(pass = hydra_get_next_password()) == 0)
|
||||||
|
pass = empty;
|
||||||
|
|
||||||
|
|
||||||
|
create_core_packet(0,ip,port);
|
||||||
|
|
||||||
|
if (hydra_send(s, packet, strlen(packet), 0) < 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
lresp = hydra_receive_line(s);
|
||||||
|
|
||||||
|
if (lresp == NULL){
|
||||||
|
printf("null");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_NotFound(lresp)){
|
||||||
|
printf("Server dont need credentials\r\n");
|
||||||
|
hydra_completed_pair_found();
|
||||||
|
if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0){
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
|
||||||
|
create_core_packet(1,ip, port);
|
||||||
|
|
||||||
|
if (use_Basic_Auth(lresp)==1) {
|
||||||
|
|
||||||
|
sprintf(buffer2,"%s:%s",login,pass);
|
||||||
|
hydra_tobase64((unsigned char *) buffer2, strlen(buffer2), sizeof(buffer2));
|
||||||
|
|
||||||
|
sprintf(buffer, "%sAuthorization: : Basic %s\r\n\r\n",packet2,buffer2);
|
||||||
|
|
||||||
|
if (debug){
|
||||||
|
hydra_report(stderr, "C:%s\n", buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(use_Digest_Auth(lresp)==1){
|
||||||
|
|
||||||
|
char dbuffer[500];
|
||||||
|
char aux[500];
|
||||||
|
|
||||||
|
|
||||||
|
char *pbuffer = hydra_strcasestr(lresp,"WWW-Authenticate: Digest ");
|
||||||
|
strncpy(aux,pbuffer + strlen("WWW-Authenticate: Digest "), sizeof(buffer));
|
||||||
|
aux[sizeof(aux)-1]='\0';
|
||||||
|
|
||||||
|
#ifdef LIBOPENSSL
|
||||||
|
|
||||||
|
sasl_digest_md5(&dbuffer, login, pass, aux, miscptr, "rtsp", hydra_address2string(ip), port, "");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (dbuffer==NULL) {
|
||||||
|
printf("digest fail, dbuffer null\r\n");
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
sprintf(buffer, "%sAuthorization: Digest %s\r\n\r\n", packet2, dbuffer);
|
||||||
|
|
||||||
|
if (debug){
|
||||||
|
hydra_report(stderr, "C:%s\n", buffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hydra_send(s, buffer, strlen(buffer), 0) < 0) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
lresp = NULL;
|
||||||
|
|
||||||
|
lresp = hydra_receive_line(s);
|
||||||
|
|
||||||
|
if ((is_NotFound(lresp))){
|
||||||
|
|
||||||
|
hydra_completed_pair_found();
|
||||||
|
|
||||||
|
if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0){
|
||||||
|
return 3;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
hydra_completed_pair();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
|
||||||
|
return 3;
|
||||||
|
|
||||||
|
//not rechead
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
void service_rtsp(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port) {
|
||||||
|
int run = 1, next_run = 1, sock = -1;
|
||||||
|
int myport = PORT_RTSP, mysslport = PORT_RTSP_SSL;
|
||||||
|
char *ptr, *ptr2;
|
||||||
|
|
||||||
|
hydra_register_socket(sp);
|
||||||
|
|
||||||
|
if (memcmp(hydra_get_next_pair(), &HYDRA_EXIT, sizeof(HYDRA_EXIT)) == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
|
||||||
|
switch (run) {
|
||||||
|
case 1: /* connect and service init function */
|
||||||
|
if (sock >= 0){
|
||||||
|
sock = hydra_disconnect(sock);
|
||||||
|
}
|
||||||
|
if ((options & OPTION_SSL) == 0) {
|
||||||
|
if (port != 0){
|
||||||
|
myport = port;
|
||||||
|
}
|
||||||
|
sock = hydra_connect_tcp(ip, myport);
|
||||||
|
port = myport;
|
||||||
|
}
|
||||||
|
if (sock < 0) {
|
||||||
|
if (verbose || debug)
|
||||||
|
hydra_report(stderr, "[ERROR] Child with pid %d terminating, can not connect\n", (int) getpid());
|
||||||
|
hydra_child_exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
next_run=2;
|
||||||
|
break;
|
||||||
|
case 2: /* run the cracking function */
|
||||||
|
next_run = start_rtsp(sock, ip, port, options, miscptr, fp);
|
||||||
|
break;
|
||||||
|
case 3: /* clean exit */
|
||||||
|
if (sock >= 0) {
|
||||||
|
sock = hydra_disconnect(sock);
|
||||||
|
}
|
||||||
|
hydra_child_exit(0);
|
||||||
|
printf("end");
|
||||||
|
return;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
hydra_report(stderr, "[ERROR] Caught unknown return code, exiting!\n");
|
||||||
|
hydra_child_exit(0);
|
||||||
|
}
|
||||||
|
run = next_run;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int service_rtsp_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port) {
|
||||||
|
// called before the childrens are forked off, so this is the function
|
||||||
|
// which should be filled if initial connections and service setup has to be
|
||||||
|
// performed once only.
|
||||||
|
//
|
||||||
|
// fill if needed.
|
||||||
|
//
|
||||||
|
// return codes:
|
||||||
|
// 0 all OK
|
||||||
|
// -1 error, hydra will exit, so print a good error message here
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
22
hydra.c
22
hydra.c
|
@ -51,6 +51,10 @@ extern void service_s7_300(char *ip, int sp, unsigned char options, char *miscpt
|
||||||
|
|
||||||
// ADD NEW SERVICES HERE
|
// ADD NEW SERVICES HERE
|
||||||
|
|
||||||
|
extern void service_rtsp(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port);
|
||||||
|
|
||||||
|
// ADD NEW SERVICES HERE
|
||||||
|
|
||||||
#ifdef HAVE_MATH_H
|
#ifdef HAVE_MATH_H
|
||||||
extern void service_mysql(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port);
|
extern void service_mysql(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port);
|
||||||
extern int service_mysql_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port);
|
extern int service_mysql_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port);
|
||||||
|
@ -137,10 +141,11 @@ extern int service_s7_300_init(char *ip, int sp, unsigned char options, char *mi
|
||||||
|
|
||||||
// ADD NEW SERVICES HERE
|
// ADD NEW SERVICES HERE
|
||||||
|
|
||||||
|
extern int service_rtsp_init(char *ip, int sp, unsigned char options, char *miscptr, FILE * fp, int port);
|
||||||
|
|
||||||
// ADD NEW SERVICES HERE
|
// ADD NEW SERVICES HERE
|
||||||
char *SERVICES =
|
char *SERVICES =
|
||||||
"asterisk afp cisco cisco-enable cvs firebird ftp ftps http[s]-{head|get} http[s]-{get|post}-form http-proxy http-proxy-urlenum icq imap[s] irc ldap2[s] ldap3[-{cram|digest}md5][s] mssql mysql ncp nntp oracle oracle-listener oracle-sid pcanywhere pcnfs pop3[s] postgres rdp redis rexec rlogin rsh s7-300 sapr3 sip smb smtp[s] smtp-enum snmp socks5 ssh sshkey svn teamspeak telnet[s] vmauthd vnc xmpp";
|
"asterisk afp cisco cisco-enable cvs firebird ftp ftps http[s]-{head|get} http[s]-{get|post}-form http-proxy http-proxy-urlenum icq imap[s] irc ldap2[s] ldap3[-{cram|digest}md5][s] mssql mysql ncp nntp oracle oracle-listener oracle-sid pcanywhere pcnfs pop3[s] postgres rdp redis rexec rlogin rsh s7-300 sapr3 sip smb smtp[s] smtp-enum snmp socks5 ssh sshkey svn teamspeak telnet[s] vmauthd vnc xmpp rtsp";
|
||||||
|
|
||||||
#define MAXBUF 520
|
#define MAXBUF 520
|
||||||
#define MAXLINESIZE ( ( MAXBUF / 2 ) - 4 )
|
#define MAXLINESIZE ( ( MAXBUF / 2 ) - 4 )
|
||||||
|
@ -1182,6 +1187,9 @@ void hydra_service_init(int target_no) {
|
||||||
x = service_s7_300_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port);
|
x = service_s7_300_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port);
|
||||||
// ADD NEW SERVICES HERE
|
// ADD NEW SERVICES HERE
|
||||||
|
|
||||||
|
if (strcmp(hydra_options.service, "rtsp") == 0)
|
||||||
|
x = service_rtsp_init(hydra_targets[target_no]->ip, -1, options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port);
|
||||||
|
|
||||||
if (x != 0 && x != 99) {
|
if (x != 0 && x != 99) {
|
||||||
if (x > 0 && x < 4)
|
if (x > 0 && x < 4)
|
||||||
hydra_targets[target_no]->done = x;
|
hydra_targets[target_no]->done = x;
|
||||||
|
@ -1246,8 +1254,11 @@ int hydra_spawn_head(int head_no, int target_no) {
|
||||||
service_asterisk(hydra_targets[target_no]->ip, hydra_heads[head_no]->sp[1], options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port);
|
service_asterisk(hydra_targets[target_no]->ip, hydra_heads[head_no]->sp[1], options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port);
|
||||||
if (strcmp(hydra_options.service, "telnet") == 0)
|
if (strcmp(hydra_options.service, "telnet") == 0)
|
||||||
service_telnet(hydra_targets[target_no]->ip, hydra_heads[head_no]->sp[1], options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port);
|
service_telnet(hydra_targets[target_no]->ip, hydra_heads[head_no]->sp[1], options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port);
|
||||||
if (strcmp(hydra_options.service, "ftp") == 0)
|
if (strcmp(hydra_options.service, "ftp") == 0){
|
||||||
|
|
||||||
service_ftp(hydra_targets[target_no]->ip, hydra_heads[head_no]->sp[1], options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port);
|
service_ftp(hydra_targets[target_no]->ip, hydra_heads[head_no]->sp[1], options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port);
|
||||||
|
|
||||||
|
}
|
||||||
if (strcmp(hydra_options.service, "ftps") == 0)
|
if (strcmp(hydra_options.service, "ftps") == 0)
|
||||||
service_ftps(hydra_targets[target_no]->ip, hydra_heads[head_no]->sp[1], options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port);
|
service_ftps(hydra_targets[target_no]->ip, hydra_heads[head_no]->sp[1], options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port);
|
||||||
if (strcmp(hydra_options.service, "redis") == 0)
|
if (strcmp(hydra_options.service, "redis") == 0)
|
||||||
|
@ -1377,6 +1388,10 @@ int hydra_spawn_head(int head_no, int target_no) {
|
||||||
service_s7_300(hydra_targets[target_no]->ip, hydra_heads[head_no]->sp[1], options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port);
|
service_s7_300(hydra_targets[target_no]->ip, hydra_heads[head_no]->sp[1], options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port);
|
||||||
// ADD NEW SERVICES HERE
|
// ADD NEW SERVICES HERE
|
||||||
|
|
||||||
|
if (strcmp(hydra_options.service, "rtsp") == 0){
|
||||||
|
|
||||||
|
service_rtsp(hydra_targets[target_no]->ip, hydra_heads[head_no]->sp[1], options, hydra_options.miscptr, hydra_brains.ofp, hydra_targets[target_no]->port);
|
||||||
|
}
|
||||||
// just in case a module returns (which it shouldnt) we let it exit here
|
// just in case a module returns (which it shouldnt) we let it exit here
|
||||||
exit(-1);
|
exit(-1);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1471,6 +1486,7 @@ int hydra_lookup_port(char *service) {
|
||||||
{"asterisk", PORT_ASTERISK, PORT_ASTERISK_SSL},
|
{"asterisk", PORT_ASTERISK, PORT_ASTERISK_SSL},
|
||||||
{"s7-300", PORT_S7_300, PORT_S7_300_SSL},
|
{"s7-300", PORT_S7_300, PORT_S7_300_SSL},
|
||||||
// ADD NEW SERVICES HERE - add new port numbers to hydra.h
|
// ADD NEW SERVICES HERE - add new port numbers to hydra.h
|
||||||
|
{"rtsp", PORT_RTSP, PORT_RTSP_SSL},
|
||||||
{"", PORT_NOPORT, PORT_NOPORT}
|
{"", PORT_NOPORT, PORT_NOPORT}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2797,6 +2813,8 @@ int main(int argc, char *argv[]) {
|
||||||
bail("-m option is required to specify the DN\n");
|
bail("-m option is required to specify the DN\n");
|
||||||
}
|
}
|
||||||
// ADD NEW SERVICES HERE
|
// ADD NEW SERVICES HERE
|
||||||
|
if (strcmp(hydra_options.service, "rtsp") == 0)
|
||||||
|
i = 1;
|
||||||
if (strcmp(hydra_options.service, "s7-300") == 0) {
|
if (strcmp(hydra_options.service, "s7-300") == 0) {
|
||||||
if (hydra_options.tasks > 8) {
|
if (hydra_options.tasks > 8) {
|
||||||
fprintf(stderr, "[INFO] Reduced number of tasks to 8 (the PLC does not like more connections)\n");
|
fprintf(stderr, "[INFO] Reduced number of tasks to 8 (the PLC does not like more connections)\n");
|
||||||
|
|
2
hydra.h
2
hydra.h
|
@ -118,6 +118,8 @@
|
||||||
#define PORT_S7_300_SSL 102
|
#define PORT_S7_300_SSL 102
|
||||||
#define PORT_REDIS 6379
|
#define PORT_REDIS 6379
|
||||||
#define PORT_REDIS_SSL 6379
|
#define PORT_REDIS_SSL 6379
|
||||||
|
#define PORT_RTSP 554
|
||||||
|
#define PORT_RTSP_SSL 554
|
||||||
|
|
||||||
#define False 0
|
#define False 0
|
||||||
#define True 1
|
#define True 1
|
||||||
|
|
120
sasl.c
120
sasl.c
|
@ -1,15 +1,11 @@
|
||||||
#include "sasl.h"
|
#include "sasl.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
print_hex is used for debug
|
print_hex is used for debug
|
||||||
it displays the string buf hexa values of size len
|
it displays the string buf hexa values of size len
|
||||||
|
|
||||||
*/
|
*/
|
||||||
int print_hex(unsigned char *buf, int len) {
|
int print_hex(unsigned char *buf, int len) {
|
||||||
int i;
|
int i;
|
||||||
int n;
|
int n;
|
||||||
|
|
||||||
for (i = 0, n = 0; i < len; i++) {
|
for (i = 0, n = 0; i < len; i++) {
|
||||||
if (n > 7) {
|
if (n > 7) {
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
@ -19,23 +15,16 @@ int print_hex(unsigned char *buf, int len) {
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
RFC 4013: SASLprep: Stringprep Profile for User Names and Passwords
|
RFC 4013: SASLprep: Stringprep Profile for User Names and Passwords
|
||||||
code based on gsasl_saslprep from GSASL project
|
code based on gsasl_saslprep from GSASL project
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int sasl_saslprep(const char *in, sasl_saslprep_flags flags, char **out) {
|
int sasl_saslprep(const char *in, sasl_saslprep_flags flags, char **out) {
|
||||||
#if LIBIDN
|
#if LIBIDN
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = stringprep_profile(in, out, "SASLprep", (flags & SASL_ALLOW_UNASSIGNED) ? STRINGPREP_NO_UNASSIGNED : 0);
|
rc = stringprep_profile(in, out, "SASLprep", (flags & SASL_ALLOW_UNASSIGNED) ? STRINGPREP_NO_UNASSIGNED : 0);
|
||||||
|
|
||||||
if (rc != STRINGPREP_OK) {
|
if (rc != STRINGPREP_OK) {
|
||||||
*out = NULL;
|
*out = NULL;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -47,10 +36,8 @@ int sasl_saslprep(const char *in, sasl_saslprep_flags flags, char **out) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
size_t i, inlen = strlen(in);
|
size_t i, inlen = strlen(in);
|
||||||
|
|
||||||
for (i = 0; i < inlen; i++) {
|
for (i = 0; i < inlen; i++) {
|
||||||
if (in[i] & 0x80) {
|
if (in[i] & 0x80) {
|
||||||
*out = NULL;
|
*out = NULL;
|
||||||
|
@ -67,37 +54,26 @@ int sasl_saslprep(const char *in, sasl_saslprep_flags flags, char **out) {
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
RFC 4616: The PLAIN Simple Authentication and Security Layer (SASL) Mechanism
|
RFC 4616: The PLAIN Simple Authentication and Security Layer (SASL) Mechanism
|
||||||
|
|
||||||
sasl_plain computes the plain authentication from strings login and password
|
sasl_plain computes the plain authentication from strings login and password
|
||||||
and stored the value in variable result
|
and stored the value in variable result
|
||||||
|
|
||||||
the first parameter result must be able to hold at least 255 bytes!
|
the first parameter result must be able to hold at least 255 bytes!
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void sasl_plain(char *result, char *login, char *pass) {
|
void sasl_plain(char *result, char *login, char *pass) {
|
||||||
char *preplogin;
|
char *preplogin;
|
||||||
char *preppasswd;
|
char *preppasswd;
|
||||||
|
|
||||||
int rc = sasl_saslprep(login, SASL_ALLOW_UNASSIGNED, &preplogin);
|
int rc = sasl_saslprep(login, SASL_ALLOW_UNASSIGNED, &preplogin);
|
||||||
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
result = NULL;
|
result = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = sasl_saslprep(pass, 0, &preppasswd);
|
rc = sasl_saslprep(pass, 0, &preppasswd);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
free(preplogin);
|
free(preplogin);
|
||||||
result = NULL;
|
result = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (2 * strlen(preplogin) + 3 + strlen(preppasswd) < 180) {
|
if (2 * strlen(preplogin) + 3 + strlen(preppasswd) < 180) {
|
||||||
strcpy(result, preplogin);
|
strcpy(result, preplogin);
|
||||||
strcpy(result + strlen(preplogin) + 1, preplogin);
|
strcpy(result + strlen(preplogin) + 1, preplogin);
|
||||||
|
@ -107,21 +83,14 @@ void sasl_plain(char *result, char *login, char *pass) {
|
||||||
free(preplogin);
|
free(preplogin);
|
||||||
free(preppasswd);
|
free(preppasswd);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef LIBOPENSSL
|
#ifdef LIBOPENSSL
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
RFC 2195: IMAP/POP AUTHorize Extension for Simple Challenge/Response
|
RFC 2195: IMAP/POP AUTHorize Extension for Simple Challenge/Response
|
||||||
|
|
||||||
sasl_cram_md5 computes the cram-md5 authentication from password string
|
sasl_cram_md5 computes the cram-md5 authentication from password string
|
||||||
and the challenge sent by the server, and stored the value in variable
|
and the challenge sent by the server, and stored the value in variable
|
||||||
result
|
result
|
||||||
|
|
||||||
the parameter result must be able to hold at least 100 bytes!
|
the parameter result must be able to hold at least 100 bytes!
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void sasl_cram_md5(char *result, char *pass, char *challenge) {
|
void sasl_cram_md5(char *result, char *pass, char *challenge) {
|
||||||
char ipad[64];
|
char ipad[64];
|
||||||
char opad[64];
|
char opad[64];
|
||||||
|
@ -129,21 +98,17 @@ void sasl_cram_md5(char *result, char *pass, char *challenge) {
|
||||||
MD5_CTX md5c;
|
MD5_CTX md5c;
|
||||||
int i, rc;
|
int i, rc;
|
||||||
char *preppasswd;
|
char *preppasswd;
|
||||||
|
|
||||||
if (challenge == NULL) {
|
if (challenge == NULL) {
|
||||||
result = NULL;
|
result = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = sasl_saslprep(pass, 0, &preppasswd);
|
rc = sasl_saslprep(pass, 0, &preppasswd);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
result = NULL;
|
result = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(ipad, 0, sizeof(ipad));
|
memset(ipad, 0, sizeof(ipad));
|
||||||
memset(opad, 0, sizeof(opad));
|
memset(opad, 0, sizeof(opad));
|
||||||
|
|
||||||
if (strlen(preppasswd) >= 64) {
|
if (strlen(preppasswd) >= 64) {
|
||||||
MD5_Init(&md5c);
|
MD5_Init(&md5c);
|
||||||
MD5_Update(&md5c, preppasswd, strlen(preppasswd));
|
MD5_Update(&md5c, preppasswd, strlen(preppasswd));
|
||||||
|
@ -154,7 +119,6 @@ void sasl_cram_md5(char *result, char *pass, char *challenge) {
|
||||||
strcpy(ipad, preppasswd); // safe
|
strcpy(ipad, preppasswd); // safe
|
||||||
strcpy(opad, preppasswd); // safe
|
strcpy(opad, preppasswd); // safe
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < 64; i++) {
|
for (i = 0; i < 64; i++) {
|
||||||
ipad[i] ^= 0x36;
|
ipad[i] ^= 0x36;
|
||||||
opad[i] ^= 0x5c;
|
opad[i] ^= 0x5c;
|
||||||
|
@ -163,7 +127,6 @@ void sasl_cram_md5(char *result, char *pass, char *challenge) {
|
||||||
MD5_Update(&md5c, ipad, 64);
|
MD5_Update(&md5c, ipad, 64);
|
||||||
MD5_Update(&md5c, challenge, strlen(challenge));
|
MD5_Update(&md5c, challenge, strlen(challenge));
|
||||||
MD5_Final(md5_raw, &md5c);
|
MD5_Final(md5_raw, &md5c);
|
||||||
|
|
||||||
MD5_Init(&md5c);
|
MD5_Init(&md5c);
|
||||||
MD5_Update(&md5c, opad, 64);
|
MD5_Update(&md5c, opad, 64);
|
||||||
MD5_Update(&md5c, md5_raw, MD5_DIGEST_LENGTH);
|
MD5_Update(&md5c, md5_raw, MD5_DIGEST_LENGTH);
|
||||||
|
@ -174,15 +137,11 @@ void sasl_cram_md5(char *result, char *pass, char *challenge) {
|
||||||
}
|
}
|
||||||
free(preppasswd);
|
free(preppasswd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
sasl_cram_sha1 computes the cram-sha1 authentication from password string
|
sasl_cram_sha1 computes the cram-sha1 authentication from password string
|
||||||
and the challenge sent by the server, and stored the value in variable
|
and the challenge sent by the server, and stored the value in variable
|
||||||
result
|
result
|
||||||
|
|
||||||
the parameter result must be able to hold at least 100 bytes!
|
the parameter result must be able to hold at least 100 bytes!
|
||||||
|
|
||||||
*/
|
*/
|
||||||
void sasl_cram_sha1(char *result, char *pass, char *challenge) {
|
void sasl_cram_sha1(char *result, char *pass, char *challenge) {
|
||||||
char ipad[64];
|
char ipad[64];
|
||||||
|
@ -191,21 +150,17 @@ void sasl_cram_sha1(char *result, char *pass, char *challenge) {
|
||||||
SHA_CTX shac;
|
SHA_CTX shac;
|
||||||
int i, rc;
|
int i, rc;
|
||||||
char *preppasswd;
|
char *preppasswd;
|
||||||
|
|
||||||
if (challenge == NULL) {
|
if (challenge == NULL) {
|
||||||
result = NULL;
|
result = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = sasl_saslprep(pass, 0, &preppasswd);
|
rc = sasl_saslprep(pass, 0, &preppasswd);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
result = NULL;
|
result = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(ipad, 0, sizeof(ipad));
|
memset(ipad, 0, sizeof(ipad));
|
||||||
memset(opad, 0, sizeof(opad));
|
memset(opad, 0, sizeof(opad));
|
||||||
|
|
||||||
if (strlen(preppasswd) >= 64) {
|
if (strlen(preppasswd) >= 64) {
|
||||||
SHA1_Init(&shac);
|
SHA1_Init(&shac);
|
||||||
SHA1_Update(&shac, preppasswd, strlen(preppasswd));
|
SHA1_Update(&shac, preppasswd, strlen(preppasswd));
|
||||||
|
@ -216,37 +171,29 @@ void sasl_cram_sha1(char *result, char *pass, char *challenge) {
|
||||||
strcpy(ipad, preppasswd); // safe
|
strcpy(ipad, preppasswd); // safe
|
||||||
strcpy(opad, preppasswd); // safe
|
strcpy(opad, preppasswd); // safe
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < 64; i++) {
|
for (i = 0; i < 64; i++) {
|
||||||
ipad[i] ^= 0x36;
|
ipad[i] ^= 0x36;
|
||||||
opad[i] ^= 0x5c;
|
opad[i] ^= 0x5c;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHA1_Init(&shac);
|
SHA1_Init(&shac);
|
||||||
SHA1_Update(&shac, ipad, 64);
|
SHA1_Update(&shac, ipad, 64);
|
||||||
SHA1_Update(&shac, challenge, strlen(challenge));
|
SHA1_Update(&shac, challenge, strlen(challenge));
|
||||||
SHA1_Final(sha1_raw, &shac);
|
SHA1_Final(sha1_raw, &shac);
|
||||||
|
|
||||||
SHA1_Init(&shac);
|
SHA1_Init(&shac);
|
||||||
SHA1_Update(&shac, opad, 64);
|
SHA1_Update(&shac, opad, 64);
|
||||||
SHA1_Update(&shac, sha1_raw, SHA_DIGEST_LENGTH);
|
SHA1_Update(&shac, sha1_raw, SHA_DIGEST_LENGTH);
|
||||||
SHA1_Final(sha1_raw, &shac);
|
SHA1_Final(sha1_raw, &shac);
|
||||||
|
|
||||||
for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
|
for (i = 0; i < SHA_DIGEST_LENGTH; i++) {
|
||||||
sprintf(result, "%02x", sha1_raw[i]);
|
sprintf(result, "%02x", sha1_raw[i]);
|
||||||
result += 2;
|
result += 2;
|
||||||
}
|
}
|
||||||
free(preppasswd);
|
free(preppasswd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
sasl_cram_sha256 computes the cram-sha256 authentication from password string
|
sasl_cram_sha256 computes the cram-sha256 authentication from password string
|
||||||
and the challenge sent by the server, and stored the value in variable
|
and the challenge sent by the server, and stored the value in variable
|
||||||
result
|
result
|
||||||
|
|
||||||
the parameter result must be able to hold at least 100 bytes!
|
the parameter result must be able to hold at least 100 bytes!
|
||||||
|
|
||||||
*/
|
*/
|
||||||
void sasl_cram_sha256(char *result, char *pass, char *challenge) {
|
void sasl_cram_sha256(char *result, char *pass, char *challenge) {
|
||||||
char ipad[64];
|
char ipad[64];
|
||||||
|
@ -255,21 +202,17 @@ void sasl_cram_sha256(char *result, char *pass, char *challenge) {
|
||||||
SHA256_CTX sha256c;
|
SHA256_CTX sha256c;
|
||||||
int i, rc;
|
int i, rc;
|
||||||
char *preppasswd;
|
char *preppasswd;
|
||||||
|
|
||||||
if (challenge == NULL) {
|
if (challenge == NULL) {
|
||||||
result = NULL;
|
result = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(ipad, 0, sizeof(ipad));
|
memset(ipad, 0, sizeof(ipad));
|
||||||
memset(opad, 0, sizeof(opad));
|
memset(opad, 0, sizeof(opad));
|
||||||
|
|
||||||
rc = sasl_saslprep(pass, 0, &preppasswd);
|
rc = sasl_saslprep(pass, 0, &preppasswd);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
result = NULL;
|
result = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strlen(preppasswd) >= 64) {
|
if (strlen(preppasswd) >= 64) {
|
||||||
SHA256_Init(&sha256c);
|
SHA256_Init(&sha256c);
|
||||||
SHA256_Update(&sha256c, preppasswd, strlen(preppasswd));
|
SHA256_Update(&sha256c, preppasswd, strlen(preppasswd));
|
||||||
|
@ -280,35 +223,27 @@ void sasl_cram_sha256(char *result, char *pass, char *challenge) {
|
||||||
strcpy(ipad, preppasswd); // safe
|
strcpy(ipad, preppasswd); // safe
|
||||||
strcpy(opad, preppasswd); // safe
|
strcpy(opad, preppasswd); // safe
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < 64; i++) {
|
for (i = 0; i < 64; i++) {
|
||||||
ipad[i] ^= 0x36;
|
ipad[i] ^= 0x36;
|
||||||
opad[i] ^= 0x5c;
|
opad[i] ^= 0x5c;
|
||||||
}
|
}
|
||||||
|
|
||||||
SHA256_Init(&sha256c);
|
SHA256_Init(&sha256c);
|
||||||
SHA256_Update(&sha256c, ipad, 64);
|
SHA256_Update(&sha256c, ipad, 64);
|
||||||
SHA256_Update(&sha256c, challenge, strlen(challenge));
|
SHA256_Update(&sha256c, challenge, strlen(challenge));
|
||||||
SHA256_Final(sha256_raw, &sha256c);
|
SHA256_Final(sha256_raw, &sha256c);
|
||||||
|
|
||||||
SHA256_Init(&sha256c);
|
SHA256_Init(&sha256c);
|
||||||
SHA256_Update(&sha256c, opad, 64);
|
SHA256_Update(&sha256c, opad, 64);
|
||||||
SHA256_Update(&sha256c, sha256_raw, SHA256_DIGEST_LENGTH);
|
SHA256_Update(&sha256c, sha256_raw, SHA256_DIGEST_LENGTH);
|
||||||
SHA256_Final(sha256_raw, &sha256c);
|
SHA256_Final(sha256_raw, &sha256c);
|
||||||
|
|
||||||
for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
|
for (i = 0; i < SHA256_DIGEST_LENGTH; i++) {
|
||||||
sprintf(result, "%02x", sha256_raw[i]);
|
sprintf(result, "%02x", sha256_raw[i]);
|
||||||
result += 2;
|
result += 2;
|
||||||
}
|
}
|
||||||
free(preppasswd);
|
free(preppasswd);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
RFC 2831: Using Digest Authentication as a SASL Mechanism
|
RFC 2831: Using Digest Authentication as a SASL Mechanism
|
||||||
|
|
||||||
the parameter result must be able to hold at least 500 bytes!!
|
the parameter result must be able to hold at least 500 bytes!!
|
||||||
|
|
||||||
*/
|
*/
|
||||||
void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *miscptr, char *type, char *webtarget, int webport, char *header) {
|
void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *miscptr, char *type, char *webtarget, int webport, char *header) {
|
||||||
char *pbuffer = NULL;
|
char *pbuffer = NULL;
|
||||||
|
@ -320,16 +255,12 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
|
||||||
MD5_CTX md5c;
|
MD5_CTX md5c;
|
||||||
char *preplogin;
|
char *preplogin;
|
||||||
char *preppasswd;
|
char *preppasswd;
|
||||||
|
|
||||||
int rc = sasl_saslprep(login, SASL_ALLOW_UNASSIGNED, &preplogin);
|
int rc = sasl_saslprep(login, SASL_ALLOW_UNASSIGNED, &preplogin);
|
||||||
|
|
||||||
memset(realm, 0, sizeof(realm));
|
memset(realm, 0, sizeof(realm));
|
||||||
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
result = NULL;
|
result = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = sasl_saslprep(pass, 0, &preppasswd);
|
rc = sasl_saslprep(pass, 0, &preppasswd);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
free(preplogin);
|
free(preplogin);
|
||||||
|
@ -340,7 +271,6 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
|
||||||
//DEBUG S: nonce="1Mr6c8WjOd/x5r8GUnGeQIRNUtOVtItu3kQOGAmsZfM=",realm="test.com",qop="auth,auth-int,auth-conf",cipher="rc4-40,rc4-56,rc4,des,3des",maxbuf=4096,charset=utf-8,algorithm=md5-sess
|
//DEBUG S: nonce="1Mr6c8WjOd/x5r8GUnGeQIRNUtOVtItu3kQOGAmsZfM=",realm="test.com",qop="auth,auth-int,auth-conf",cipher="rc4-40,rc4-56,rc4,des,3des",maxbuf=4096,charset=utf-8,algorithm=md5-sess
|
||||||
//warning some not well configured xmpp server is sending no realm
|
//warning some not well configured xmpp server is sending no realm
|
||||||
//DEBUG S: nonce="3448160828",qop="auth",charset=utf-8,algorithm=md5-sess
|
//DEBUG S: nonce="3448160828",qop="auth",charset=utf-8,algorithm=md5-sess
|
||||||
|
|
||||||
pbuffer = buffer;
|
pbuffer = buffer;
|
||||||
do {
|
do {
|
||||||
currentpos++;
|
currentpos++;
|
||||||
|
@ -361,7 +291,6 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
|
||||||
}
|
}
|
||||||
pbuffer++;
|
pbuffer++;
|
||||||
} while ((pbuffer[0] != '\0') && (pbuffer[0] > 31) && (ind < array_size));
|
} while ((pbuffer[0] != '\0') && (pbuffer[0] > 31) && (ind < array_size));
|
||||||
|
|
||||||
//save the latest one
|
//save the latest one
|
||||||
if (ind < array_size) {
|
if (ind < array_size) {
|
||||||
array[ind] = malloc(currentpos + 1);
|
array[ind] = malloc(currentpos + 1);
|
||||||
|
@ -369,12 +298,10 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
|
||||||
array[ind][currentpos] = '\0';
|
array[ind][currentpos] = '\0';
|
||||||
ind++;
|
ind++;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < ind; i++) {
|
for (i = 0; i < ind; i++) {
|
||||||
//removing space chars between comma separated value if any
|
//removing space chars between comma separated value if any
|
||||||
while ((array[i] != NULL) && (array[i][0] == ' ')) {
|
while ((array[i] != NULL) && (array[i][0] == ' ')) {
|
||||||
char *tmp = strdup(array[i]);
|
char *tmp = strdup(array[i]);
|
||||||
|
|
||||||
memset(array[i], 0, sizeof(array[i]));
|
memset(array[i], 0, sizeof(array[i]));
|
||||||
strcpy(array[i], tmp + 1);
|
strcpy(array[i], tmp + 1);
|
||||||
free(tmp);
|
free(tmp);
|
||||||
|
@ -384,13 +311,11 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
|
||||||
if (strstr(array[i], "\"") != NULL) {
|
if (strstr(array[i], "\"") != NULL) {
|
||||||
//assume last char is also a double-quote
|
//assume last char is also a double-quote
|
||||||
int nonce_string_len = strlen(array[i]) - strlen("nonce=\"") - 1;
|
int nonce_string_len = strlen(array[i]) - strlen("nonce=\"") - 1;
|
||||||
|
|
||||||
if ((nonce_string_len > 0) && (nonce_string_len <= sizeof(nonce) - 1)) {
|
if ((nonce_string_len > 0) && (nonce_string_len <= sizeof(nonce) - 1)) {
|
||||||
strncpy(nonce, strstr(array[i], "nonce=") + strlen("nonce=") + 1, nonce_string_len);
|
strncpy(nonce, strstr(array[i], "nonce=") + strlen("nonce=") + 1, nonce_string_len);
|
||||||
nonce[nonce_string_len] = '\0';
|
nonce[nonce_string_len] = '\0';
|
||||||
} else {
|
} else {
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
for (j = 0; j < ind; j++)
|
for (j = 0; j < ind; j++)
|
||||||
if (array[j] != NULL)
|
if (array[j] != NULL)
|
||||||
free(array[j]);
|
free(array[j]);
|
||||||
|
@ -407,13 +332,11 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
|
||||||
if (strstr(array[i], "\"") != NULL) {
|
if (strstr(array[i], "\"") != NULL) {
|
||||||
//assume last char is also a double-quote
|
//assume last char is also a double-quote
|
||||||
int realm_string_len = strlen(array[i]) - strlen("realm=\"") - 1;
|
int realm_string_len = strlen(array[i]) - strlen("realm=\"") - 1;
|
||||||
|
|
||||||
if ((realm_string_len > 0) && (realm_string_len <= sizeof(realm) - 1)) {
|
if ((realm_string_len > 0) && (realm_string_len <= sizeof(realm) - 1)) {
|
||||||
strncpy(realm, strstr(array[i], "realm=") + strlen("realm=") + 1, realm_string_len);
|
strncpy(realm, strstr(array[i], "realm=") + strlen("realm=") + 1, realm_string_len);
|
||||||
realm[realm_string_len] = '\0';
|
realm[realm_string_len] = '\0';
|
||||||
} else {
|
} else {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < ind; i++)
|
for (i = 0; i < ind; i++)
|
||||||
if (array[i] != NULL)
|
if (array[i] != NULL)
|
||||||
free(array[i]);
|
free(array[i]);
|
||||||
|
@ -435,7 +358,6 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
|
||||||
auth_find = 1;
|
auth_find = 1;
|
||||||
if ((strstr(array[i], "\"auth\"") == NULL) && (strstr(array[i], "\"auth,") == NULL) && (strstr(array[i], ",auth\"") == NULL)) {
|
if ((strstr(array[i], "\"auth\"") == NULL) && (strstr(array[i], "\"auth,") == NULL) && (strstr(array[i], ",auth\"") == NULL)) {
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
for (j = 0; j < ind; j++)
|
for (j = 0; j < ind; j++)
|
||||||
if (array[j] != NULL)
|
if (array[j] != NULL)
|
||||||
free(array[j]);
|
free(array[j]);
|
||||||
|
@ -448,13 +370,11 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
|
||||||
if (strstr(array[i], "\"") != NULL) {
|
if (strstr(array[i], "\"") != NULL) {
|
||||||
//assume last char is also a double-quote
|
//assume last char is also a double-quote
|
||||||
int algo_string_len = strlen(array[i]) - strlen("algorithm=\"") - 1;
|
int algo_string_len = strlen(array[i]) - strlen("algorithm=\"") - 1;
|
||||||
|
|
||||||
if ((algo_string_len > 0) && (algo_string_len <= sizeof(algo) - 1)) {
|
if ((algo_string_len > 0) && (algo_string_len <= sizeof(algo) - 1)) {
|
||||||
strncpy(algo, strstr(array[i], "algorithm=") + strlen("algorithm=") + 1, algo_string_len);
|
strncpy(algo, strstr(array[i], "algorithm=") + strlen("algorithm=") + 1, algo_string_len);
|
||||||
algo[algo_string_len] = '\0';
|
algo[algo_string_len] = '\0';
|
||||||
} else {
|
} else {
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
for (j = 0; j < ind; j++)
|
for (j = 0; j < ind; j++)
|
||||||
if (array[j] != NULL)
|
if (array[j] != NULL)
|
||||||
free(array[j]);
|
free(array[j]);
|
||||||
|
@ -468,7 +388,6 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
|
||||||
}
|
}
|
||||||
if ((strstr(algo, "MD5") == NULL) && (strstr(algo, "md5") == NULL)) {
|
if ((strstr(algo, "MD5") == NULL) && (strstr(algo, "md5") == NULL)) {
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
for (j = 0; j < ind; j++)
|
for (j = 0; j < ind; j++)
|
||||||
if (array[j] != NULL)
|
if (array[j] != NULL)
|
||||||
free(array[j]);
|
free(array[j]);
|
||||||
|
@ -480,7 +399,6 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
|
||||||
free(array[i]);
|
free(array[i]);
|
||||||
array[i] = NULL;
|
array[i] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!strlen(algo)) {
|
if (!strlen(algo)) {
|
||||||
//assuming by default algo is MD5
|
//assuming by default algo is MD5
|
||||||
memset(algo, 0, sizeof(algo));
|
memset(algo, 0, sizeof(algo));
|
||||||
|
@ -489,19 +407,15 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
|
||||||
//xmpp case, some xmpp server is not sending the realm so we have to set it up
|
//xmpp case, some xmpp server is not sending the realm so we have to set it up
|
||||||
if ((strlen(realm) == 0) && (strstr(type, "xmpp") != NULL))
|
if ((strlen(realm) == 0) && (strstr(type, "xmpp") != NULL))
|
||||||
snprintf(realm, sizeof(realm), "%s", miscptr);
|
snprintf(realm, sizeof(realm), "%s", miscptr);
|
||||||
|
|
||||||
//compute ha1
|
//compute ha1
|
||||||
//support for algo = MD5
|
//support for algo = MD5
|
||||||
snprintf(buffer, 500, "%s:%s:%s", preplogin, realm, preppasswd);
|
snprintf(buffer, 500, "%s:%s:%s", preplogin, realm, preppasswd);
|
||||||
|
|
||||||
MD5_Init(&md5c);
|
MD5_Init(&md5c);
|
||||||
MD5_Update(&md5c, buffer, strlen(buffer));
|
MD5_Update(&md5c, buffer, strlen(buffer));
|
||||||
MD5_Final(response, &md5c);
|
MD5_Final(response, &md5c);
|
||||||
|
|
||||||
//for MD5-sess
|
//for MD5-sess
|
||||||
if (strstr(algo, "5-sess") != NULL) {
|
if (strstr(algo, "5-sess") != NULL) {
|
||||||
buffer[0] = 0; //memset(buffer, 0, sizeof(buffer)); => buffer is char*!
|
buffer[0] = 0; //memset(buffer, 0, sizeof(buffer)); => buffer is char*!
|
||||||
|
|
||||||
/* per RFC 2617 Errata ID 1649 */
|
/* per RFC 2617 Errata ID 1649 */
|
||||||
if ((strstr(type, "proxy") != NULL) || (strstr(type, "GET") != NULL) || (strstr(type, "HEAD") != NULL)) {
|
if ((strstr(type, "proxy") != NULL) || (strstr(type, "GET") != NULL) || (strstr(type, "HEAD") != NULL)) {
|
||||||
memset(buffer3, 0, sizeof(buffer3));
|
memset(buffer3, 0, sizeof(buffer3));
|
||||||
|
@ -515,7 +429,6 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
|
||||||
memcpy(buffer, response, sizeof(response));
|
memcpy(buffer, response, sizeof(response));
|
||||||
sprintf(buffer + sizeof(response), ":%s:%s", nonce, "hydra");
|
sprintf(buffer + sizeof(response), ":%s:%s", nonce, "hydra");
|
||||||
}
|
}
|
||||||
|
|
||||||
MD5_Init(&md5c);
|
MD5_Init(&md5c);
|
||||||
MD5_Update(&md5c, buffer, strlen(buffer));
|
MD5_Update(&md5c, buffer, strlen(buffer));
|
||||||
MD5_Final(response, &md5c);
|
MD5_Final(response, &md5c);
|
||||||
|
@ -526,7 +439,6 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
|
||||||
sprintf(pbuffer, "%02x", response[i]);
|
sprintf(pbuffer, "%02x", response[i]);
|
||||||
pbuffer += 2;
|
pbuffer += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
//compute ha2
|
//compute ha2
|
||||||
//proxy case
|
//proxy case
|
||||||
if (strstr(type, "proxy") != NULL)
|
if (strstr(type, "proxy") != NULL)
|
||||||
|
@ -541,18 +453,20 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
|
||||||
sprintf(buffer, "REGISTER:%s:%s", type, miscptr);
|
sprintf(buffer, "REGISTER:%s:%s", type, miscptr);
|
||||||
else
|
else
|
||||||
//others
|
//others
|
||||||
|
if (strstr(type, "rtsp") != NULL)
|
||||||
|
sprintf(buffer, "DESCRIBE:%s://%s:%i", type, webtarget, port);
|
||||||
|
else
|
||||||
|
//others
|
||||||
sprintf(buffer, "AUTHENTICATE:%s/%s", type, realm);
|
sprintf(buffer, "AUTHENTICATE:%s/%s", type, realm);
|
||||||
|
|
||||||
MD5_Init(&md5c);
|
MD5_Init(&md5c);
|
||||||
MD5_Update(&md5c, buffer, strlen(buffer));
|
MD5_Update(&md5c, buffer, strlen(buffer));
|
||||||
MD5_Final(response, &md5c);
|
MD5_Final(response, &md5c);
|
||||||
|
|
||||||
pbuffer = buffer2;
|
pbuffer = buffer2;
|
||||||
for (i = 0; i < MD5_DIGEST_LENGTH; i++) {
|
for (i = 0; i < MD5_DIGEST_LENGTH; i++) {
|
||||||
sprintf(pbuffer, "%02x", response[i]);
|
sprintf(pbuffer, "%02x", response[i]);
|
||||||
pbuffer += 2;
|
pbuffer += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
//compute response
|
//compute response
|
||||||
if (!auth_find)
|
if (!auth_find)
|
||||||
snprintf(buffer, 500, "%s:%s", nonce, buffer2);
|
snprintf(buffer, 500, "%s:%s", nonce, buffer2);
|
||||||
|
@ -563,13 +477,11 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
|
||||||
MD5_Update(&md5c, ":", 1);
|
MD5_Update(&md5c, ":", 1);
|
||||||
MD5_Update(&md5c, buffer, strlen(buffer));
|
MD5_Update(&md5c, buffer, strlen(buffer));
|
||||||
MD5_Final(response, &md5c);
|
MD5_Final(response, &md5c);
|
||||||
|
|
||||||
pbuffer = buffer;
|
pbuffer = buffer;
|
||||||
for (i = 0; i < MD5_DIGEST_LENGTH; i++) {
|
for (i = 0; i < MD5_DIGEST_LENGTH; i++) {
|
||||||
sprintf(pbuffer, "%02x", response[i]);
|
sprintf(pbuffer, "%02x", response[i]);
|
||||||
pbuffer += 2;
|
pbuffer += 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
//create the auth response
|
//create the auth response
|
||||||
if (strstr(type, "proxy") != NULL) {
|
if (strstr(type, "proxy") != NULL) {
|
||||||
snprintf(result, 500,
|
snprintf(result, 500,
|
||||||
|
@ -584,6 +496,9 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
|
||||||
if (strstr(type, "sip") != NULL) {
|
if (strstr(type, "sip") != NULL) {
|
||||||
snprintf(result, 500, "username=\"%s\",realm=\"%s\",nonce=\"%s\",uri=\"%s:%s\",response=%s", preplogin, realm, nonce, type, realm, buffer);
|
snprintf(result, 500, "username=\"%s\",realm=\"%s\",nonce=\"%s\",uri=\"%s:%s\",response=%s", preplogin, realm, nonce, type, realm, buffer);
|
||||||
} else{
|
} else{
|
||||||
|
if (strstr(type, "rtsp") != NULL) {
|
||||||
|
snprintf(result, 500, "username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s://%s:%i\", response=\"%s\"\r\n", preplogin, realm, nonce, type, webtarget, port, buffer);
|
||||||
|
} else {
|
||||||
if (use_proxy == 1 && proxy_authentication != NULL)
|
if (use_proxy == 1 && proxy_authentication != NULL)
|
||||||
snprintf(result, 500,
|
snprintf(result, 500,
|
||||||
"%s http://%s:%d%s HTTP/1.0\r\nHost: %s\r\nAuthorization: Digest username=\"%s\", realm=\"%s\", response=\"%s\", nonce=\"%s\", cnonce=\"hydra\", nc=00000001, algorithm=%s, qop=auth, uri=\"%s\"\r\nProxy-Authorization: Basic %s\r\nUser-Agent: Mozilla/4.0 (Hydra)\r\nConnection: keep-alive\r\n%s\r\n",
|
"%s http://%s:%d%s HTTP/1.0\r\nHost: %s\r\nAuthorization: Digest username=\"%s\", realm=\"%s\", response=\"%s\", nonce=\"%s\", cnonce=\"hydra\", nc=00000001, algorithm=%s, qop=auth, uri=\"%s\"\r\nProxy-Authorization: Basic %s\r\nUser-Agent: Mozilla/4.0 (Hydra)\r\nConnection: keep-alive\r\n%s\r\n",
|
||||||
|
@ -601,21 +516,16 @@ void sasl_digest_md5(char *result, char *login, char *pass, char *buffer, char *
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
free(preplogin);
|
free(preplogin);
|
||||||
free(preppasswd);
|
free(preppasswd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
RFC 5802: Salted Challenge Response Authentication Mechanism
|
RFC 5802: Salted Challenge Response Authentication Mechanism
|
||||||
Note: SCRAM is a client-first SASL mechanism
|
Note: SCRAM is a client-first SASL mechanism
|
||||||
|
|
||||||
I want to thx Simon Josefsson for his public server test,
|
I want to thx Simon Josefsson for his public server test,
|
||||||
and my girlfriend that let me work on that 2 whole nights ;)
|
and my girlfriend that let me work on that 2 whole nights ;)
|
||||||
|
|
||||||
clientfirstmessagebare must be at least 500 bytes in size!
|
clientfirstmessagebare must be at least 500 bytes in size!
|
||||||
|
|
||||||
*/
|
*/
|
||||||
void sasl_scram_sha1(char *result, char *pass, char *clientfirstmessagebare, char *serverfirstmessage) {
|
void sasl_scram_sha1(char *result, char *pass, char *clientfirstmessagebare, char *serverfirstmessage) {
|
||||||
int saltlen = 0;
|
int saltlen = 0;
|
||||||
|
@ -632,18 +542,14 @@ void sasl_scram_sha1(char *result, char *pass, char *clientfirstmessagebare, cha
|
||||||
char ClientProof[SHA_DIGEST_LENGTH];
|
char ClientProof[SHA_DIGEST_LENGTH];
|
||||||
unsigned char clientproof_b64[50];
|
unsigned char clientproof_b64[50];
|
||||||
char *preppasswd;
|
char *preppasswd;
|
||||||
|
|
||||||
int rc = sasl_saslprep(pass, 0, &preppasswd);
|
int rc = sasl_saslprep(pass, 0, &preppasswd);
|
||||||
|
|
||||||
if (rc) {
|
if (rc) {
|
||||||
result = NULL;
|
result = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*client-final-message */
|
/*client-final-message */
|
||||||
if (debug)
|
if (debug)
|
||||||
hydra_report(stderr, "DEBUG S: %s\n", serverfirstmessage);
|
hydra_report(stderr, "DEBUG S: %s\n", serverfirstmessage);
|
||||||
|
|
||||||
//r=hydra28Bo7kduPpAZLzhRQiLxc8Y9tiwgw+yP,s=ldDgevctH+Kg7b8RnnA3qA==,i=4096
|
//r=hydra28Bo7kduPpAZLzhRQiLxc8Y9tiwgw+yP,s=ldDgevctH+Kg7b8RnnA3qA==,i=4096
|
||||||
if (strstr(serverfirstmessage, "r=") == NULL) {
|
if (strstr(serverfirstmessage, "r=") == NULL) {
|
||||||
hydra_report(stderr, "Error: Can't understand server message\n");
|
hydra_report(stderr, "Error: Can't understand server message\n");
|
||||||
|
@ -657,7 +563,6 @@ void sasl_scram_sha1(char *result, char *pass, char *clientfirstmessagebare, cha
|
||||||
//continue to search from the previous successful call
|
//continue to search from the previous successful call
|
||||||
salt = strtok(NULL, ",");
|
salt = strtok(NULL, ",");
|
||||||
ic = strtok(NULL, ",");
|
ic = strtok(NULL, ",");
|
||||||
|
|
||||||
iter = atoi(ic + 2);
|
iter = atoi(ic + 2);
|
||||||
if (iter == 0) {
|
if (iter == 0) {
|
||||||
hydra_report(stderr, "Error: Can't understand server response\n");
|
hydra_report(stderr, "Error: Can't understand server response\n");
|
||||||
|
@ -665,7 +570,6 @@ void sasl_scram_sha1(char *result, char *pass, char *clientfirstmessagebare, cha
|
||||||
result = NULL;
|
result = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((nonce != NULL) && (strlen(nonce) > 2))
|
if ((nonce != NULL) && (strlen(nonce) > 2))
|
||||||
snprintf(clientfinalmessagewithoutproof, sizeof(clientfinalmessagewithoutproof), "c=biws,%s", nonce);
|
snprintf(clientfinalmessagewithoutproof, sizeof(clientfinalmessagewithoutproof), "c=biws,%s", nonce);
|
||||||
else {
|
else {
|
||||||
|
@ -674,7 +578,6 @@ void sasl_scram_sha1(char *result, char *pass, char *clientfirstmessagebare, cha
|
||||||
result = NULL;
|
result = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((salt != NULL) && (strlen(salt) > 2) && (strlen(salt) <= sizeof(buffer)))
|
if ((salt != NULL) && (strlen(salt) > 2) && (strlen(salt) <= sizeof(buffer)))
|
||||||
//s=ghgIAfLl1+yUy/Xl1WD5Tw== remove the header s=
|
//s=ghgIAfLl1+yUy/Xl1WD5Tw== remove the header s=
|
||||||
strcpy(buffer, salt + 2);
|
strcpy(buffer, salt + 2);
|
||||||
|
@ -684,32 +587,25 @@ void sasl_scram_sha1(char *result, char *pass, char *clientfirstmessagebare, cha
|
||||||
result = NULL;
|
result = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* SaltedPassword := Hi(Normalize(password), salt, i) */
|
/* SaltedPassword := Hi(Normalize(password), salt, i) */
|
||||||
saltlen = from64tobits((char *) salt, buffer);
|
saltlen = from64tobits((char *) salt, buffer);
|
||||||
|
|
||||||
if (PKCS5_PBKDF2_HMAC_SHA1(preppasswd, strlen(preppasswd), (unsigned char *) salt, saltlen, iter, SHA_DIGEST_LENGTH, SaltedPassword) != 1) {
|
if (PKCS5_PBKDF2_HMAC_SHA1(preppasswd, strlen(preppasswd), (unsigned char *) salt, saltlen, iter, SHA_DIGEST_LENGTH, SaltedPassword) != 1) {
|
||||||
hydra_report(stderr, "Error: Failed to generate PBKDF2\n");
|
hydra_report(stderr, "Error: Failed to generate PBKDF2\n");
|
||||||
free(preppasswd);
|
free(preppasswd);
|
||||||
result = NULL;
|
result = NULL;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ClientKey := HMAC(SaltedPassword, "Client Key") */
|
/* ClientKey := HMAC(SaltedPassword, "Client Key") */
|
||||||
#define CLIENT_KEY "Client Key"
|
#define CLIENT_KEY "Client Key"
|
||||||
HMAC(EVP_sha1(), SaltedPassword, SHA_DIGEST_LENGTH, (const unsigned char *) CLIENT_KEY, strlen(CLIENT_KEY), ClientKey, &resultlen);
|
HMAC(EVP_sha1(), SaltedPassword, SHA_DIGEST_LENGTH, (const unsigned char *) CLIENT_KEY, strlen(CLIENT_KEY), ClientKey, &resultlen);
|
||||||
|
|
||||||
/* StoredKey := H(ClientKey) */
|
/* StoredKey := H(ClientKey) */
|
||||||
SHA1((const unsigned char *) ClientKey, SHA_DIGEST_LENGTH, StoredKey);
|
SHA1((const unsigned char *) ClientKey, SHA_DIGEST_LENGTH, StoredKey);
|
||||||
|
|
||||||
/* ClientSignature := HMAC(StoredKey, AuthMessage) */
|
/* ClientSignature := HMAC(StoredKey, AuthMessage) */
|
||||||
snprintf(AuthMessage, 500, "%s,%s,%s", clientfirstmessagebare, serverfirstmessage, clientfinalmessagewithoutproof);
|
snprintf(AuthMessage, 500, "%s,%s,%s", clientfirstmessagebare, serverfirstmessage, clientfinalmessagewithoutproof);
|
||||||
HMAC(EVP_sha1(), StoredKey, SHA_DIGEST_LENGTH, (const unsigned char *) AuthMessage, strlen(AuthMessage), ClientSignature, &resultlen);
|
HMAC(EVP_sha1(), StoredKey, SHA_DIGEST_LENGTH, (const unsigned char *) AuthMessage, strlen(AuthMessage), ClientSignature, &resultlen);
|
||||||
|
|
||||||
/* ClientProof := ClientKey XOR ClientSignature */
|
/* ClientProof := ClientKey XOR ClientSignature */
|
||||||
xor(ClientProof, (char *) ClientKey, (char *) ClientSignature, 20);
|
xor(ClientProof, (char *) ClientKey, (char *) ClientSignature, 20);
|
||||||
to64frombits(clientproof_b64, (const unsigned char *) ClientProof, 20);
|
to64frombits(clientproof_b64, (const unsigned char *) ClientProof, 20);
|
||||||
|
|
||||||
snprintf(result, 500, "%s,p=%s", clientfinalmessagewithoutproof, clientproof_b64);
|
snprintf(result, 500, "%s,p=%s", clientfinalmessagewithoutproof, clientproof_b64);
|
||||||
if (debug)
|
if (debug)
|
||||||
hydra_report(stderr, "DEBUG C: %s\n", result);
|
hydra_report(stderr, "DEBUG C: %s\n", result);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue