Novell NDS Object Enum

A long time ago, I needed a working nds object enumerator. I know there exist some on packetstorm, but they needed to be fixed and so I thought why not doing something more reliable just because.
This small tool came out as a result and helped me since then.
Sample output:

 ./nds_enum -a -n 10.1.1.1
  [+] Connecting to 10.1.1.1:524
  [+] Initializing connection with 10.1.1.1
  [+] Request Type: 0x3333
  [+] Attached to 10.1.1.1 with connection number : 106
   [NDS Object Information]
   [Server Information]
   Server Name           : XXX-01
   Version               : 5
   Sub-version           : 70
   Max Connections       : 129
   Conn(s) in use        : 99
   Revision              : 7
   SFT level             : 2
   TTS level             : 1
   Max conn ever used    : 113
   Account version       : 1
   VAP version           : 1
   Queue version         : 1
   Print version         : 0
   Virtual console vers  : 1
   Restriction level     : 1
   Internet bridge       : 1
   NDS Tree Name         : XX-TREE______________________
   Object ID Type         Name
   --------- ------------ ------------------------------------------------
   fb8b0000  Print Queue  XX-INTRATEST_BACKUP_QUEUE
   11990000  User         ADMIN-XX
   08990000  Group        ADMIN-XXP
   53800000  Group        ADMINGROUP
   e9800000  User         ADMINNSS_XXX-VIE-01
   e2800000  User         ADMINNSS_XXX-VIE-02
   76800000  User         BACKUP
   d4800000  User         PUBLICUSER_01
   feb00000  User         FWALERT
   9e820000  User         GHOST
   f6800000  User         IBUSER
   5fc70000  User         NFSUSER
   aa8b0000  Group        NORTONANTIVIRUSADMIN
   ab8b0000  Group        NORTONANTIVIRUSUSER*   9baf0000  User         PROXY-GW
   57800000  User         PROXY-SAMBA
   f9920000  Print Queue  XXX-01_BACKUP_JOB_QUEUE
   a8810000  User         SYSINSTALL
   47800000  File Server  XXX-01
   80c90000  Dir Server   XX-TREE_________________________
  [+] EOF
/**
 * \file nds_enum.c
 * \brief This is the main file of the nds enumeration tool.
 * \author coma
 *
 * I know this tool kinda reinvents the wheel as there is already
 * a tool out which is able to create an ncpquery, but when I needed
 * it it was not compiling and had some other issues I didn't liked,
 * so I decided to code my own version of it.
 *
 * More information can be found here:
 * http://www.packetstormsecurity.org/Netware/adv_novellleak.txt
 * http://packetstormsecurity.org/Netware/penetration/ncpquery-1.3.tar.gz
 *
 * This program 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 program 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 .
*/
/*
 * includes for different OSs
 *
 */
#define LINUX
#if ( defined(FBSD) || defined(LINUX) )
    #define GNUS
    #undef Win32
#endif
#ifdef GNUS
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <stdio.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <stdlib.h>
    #include <string.h>
    #include <ctype.h>
#endif
#ifdef WIN32
    #include <windows.h>
    #include <winsock2.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
#endif
/*
 * defines of global variables
 */
/**
 * \def NCP_PORT
 * \brief default ncp port is 524
 */
#define NCP_PORT 524
/**
 * \def req_hdr_sz
 * \brief default request header size is 22
 */
/*
 * By other sources it should be like
 *   #define NCP_RQST_HDR_LENGTH 7
 *   #define NCP_RPLY_HDR_LENGTH 8
 * but i had no time to verify that
 */
#define req_hdr_sz  22
#ifdef WIN32
/**
 * \def bzero
 * \brief On win32 systems bzero does not exist
 * to prevent ifdefs in the code, I tried to
 * solve it this way.
 */
    #define bzero(a, b) memset(a, 0x0, b)
#endif
/*
 * define the sizes so it's more portable
 */
/**
 * \typedef unsigned char uint8
 * \brief Basic data type 8 bits
 */
typedef unsigned char uint8;
/**
 * \typedef unsigned short uint16
 * \brief Basic data type 16 bits
 */
typedef unsigned short uint16;
/**
 * \typedef unsigned long uint32
 * \brief Basic data type 32 bits
 */
typedef unsigned long uint32;
/**
 * \struct NCP_Req
 * \brief Structure for NCP Server Info Request
 * to gather basic information about the server.
 */
typedef struct NCP_Req
{
    /**
     * \var uint32 sig
     * \brief signature identifies the packet type (0x446d6454)
     */
    uint32 sig;
    /**
     * \var uint32 len
     * \brief length = 0x0000001a (26)
     */
    uint32 len;
    /**
     * \var uint32 ver
     * \brief version = 0x00000001
     */
    uint32 ver;
    /**
     * \var uint32 reqbuf
     * \brief reply buffer size = 0x00000080 (128)
     */
    uint32 reqbuf;
    /**
     * \var uint16 reqtype
     * \brief 0x2222 (request)
     */
    uint16 reqtype;
    /**
     * \var uint8 seq
     * \brief 0x01 sequence number is incremented by one
     */
    uint8  seq;
    /**
     * \var uint8 connlow
     * \brief Conn low 0x0e (14)
     */
    uint8  connlow;
    /**
     * \var task
     * \brief Task # 0x01
     */
    uint8  task;
    /**
     * \var uint8 connhi
     * \brief Conn hi 0x00 (0)
     */
    uint8  connhi;
    /*
     * For full compliance I will need to add
     * uint 32 req;        // 0x17000111 (23,0,1,17)
     */
}
/**
 * \var typedef NCP_Req NCP_req
 * \brief Pre-initialised type definition for NCP_Req.
 */
NCP_req;
/**
 * \var struct NCP_Rep
 * \brief Structure for NCP Replies
 */
typedef struct NCP_Rep
{
    /**
     * \var uint32 sig
     * \brief 4 byte signature
     */
    uint32 sig;
    /**
     * \var uint32 len
     * \brief length = 0x00000090 (144)
     */
    uint32 len;
    /**
     * \var uint16 reqtype
     * \brief 0x3333 (reply)
     */
    uint16 reqtype;
    /**
     * \var uint8 seq
     * \brief 0x01 sequence number
     */
    uint8  seq;
    /**
     * \var uint8 connlow
     * \brief Conn low 0x0e (14)
     */
    uint8  connlow;
    /**
     * \var uint8 task
     * \brief Task # 0x01
     */
    uint8  task;
    /**
     * \var uint8 connhi
     * \brief Conn hi 0x00 (0)
     */
    uint8  connhi;
    /**
     * \var uint8 data[400]
     * \brief This is a easy way of putting all in one place
     * will need to change this to the correct fields, but
     * I didn't had a lot of time so I based it on some example source
     * How it should be:
     * uint8  cc;         // completion code = 0x00 (ok)
     * uint8  cs;         // connection status flags = 0x00 (ok)
     * uint8[47] svrname; // object name = 0x50 41 4e (PAN)
     * uint8  ser_ver;    // file service version = 0x05
     * uint8  ser_subver; // file service sub-version = 0x00
     * uint16 max_conn;   // max service connections = 0x000e
     * uint16 conn_use;   // connections in use = 0x0000
     * uint16 max_vols;   // maximum volumes = 0x00ff
     * uint8  rev;        // revision = 0x00
     * uint8  sft;        // sft level = 0x02
     * uint8  tts;        // tts level = 0x01
     * uint16 max_used;   // max conn ever used = 0x01
     * uint8  acct;       // account version = 0x01
     * uint8  vap;        // VAP version = 0x01
     * uint8  queue;      // Queue version = 0x01
     * uint8  print;      // Print version = 0x00
     * uint8  virt_con;   // Virtual console version = 0x01
     * uint8  int_brdg;   // Internet bridge = 0x01
     */
    uint8  data[400];
}
/**
 * \var typedef struct NCP_Rep NCP_rep
 * \brief Pre-initialised type definition for NCP_Rep
 */
NCP_rep;
/*
 * Functions
 */
/**
 * \fn uint8 increment_seq (uint8 seq)
 * \brief This function will increment the sequence number by 1 until 255
 * \param seq initial sequence number
 * \return the incremented sequence number, if 255 it returns 0
 */
uint8 increment_seq (uint8 seq)
{
    /*
     * if it's 255 return 0
     */
    if(seq == 0xff)
    {
        return(0x00);
    } else {
        /*
         * else increment by 1
         */
        return(seq + 1);
    }
}
/**
 * \fn void usage(char *prog)
 * \brief This function will print a little usage banner
 * \param prog pointer to argv[0] for the program name
 * \return no return (void)
 */
void usage(char *prog)
{
    printf("USAGE: ");
    printf("%s [opts] -n \n\n",prog);
    printf("\t-h\tthis help screen\n");
    printf("\t-v\tverbose\n");
    printf("\t-n\tSpecify Target\n");
    printf("\t-i\tget server info\n");
    printf("\t-s\tenumerate server object types\n");
    printf("\t-g\tenumerate group object types\n");
    printf("\t-u\tenumerate user object types (default)\n");
    printf("\t-a\tenumerate all object types\n");
    printf("\n");
}
/**
 * \fn int initialize_conn(char *target)
 * \brief This function will perfom the first connection with the ncp service
 * \param target Target IP Address
 * \return 0
 */
int initialize_conn(char *target)
{
    int sockfd, result;
    struct sockaddr_in address;
    /*
     * Create the socket
     */
    if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("[-] Error creating socket\n");
        exit(EXIT_FAILURE);
    }
    /*
     * reset sockaddr struct to 0
     */
    bzero(&address,sizeof(address));
    address.sin_family = AF_INET;
    address.sin_addr.s_addr = inet_addr(target);
    address.sin_port = htons(NCP_PORT);
    printf("[+] Connecting to %s:%i\n", target, NCP_PORT);
    /*
     * Connect to target server
     */
    if ( (result = connect(sockfd, (struct sockaddr *)&address, sizeof(address))) < 0)
    {
        printf("[-] Unable to connect to server %s, error : %i\n",target, result);
        exit(EXIT_FAILURE);
    }
    /*
     * return the socket file descriptor
     */
    return sockfd;
}
/**
 * \fn struct NCP_Req initialize_ncp(struct NCP_Req ncpreq, int sockfd, int verbose)
 * \brief This function will perform the NCP "Handshake"
 * \param ncpreq structure to the ncp request header
 * \param sockfd socket file descriptor from initialize_conn
 * \param verbose verbosity flag
 * \return ncpreq NCP request structure
 */
struct NCP_Req initialize_ncp(struct NCP_Req ncpreq, int sockfd, int verbose)
{
    char sendbuff[1024], recvbuff[1024];
    int result, conn;
    struct NCP_Rep ncpresponse;
    /*
     * Reset buffers to 0
     */
    memset(sendbuff, 0, sizeof(sendbuff));
    memset(recvbuff, 0, sizeof(recvbuff));
    /*
     * Build the NCP request
     */
    ncpreq.sig = 0x54646d44;
    ncpreq.len = 0x17000000;
    ncpreq.ver = 0x01000000;
    ncpreq.reqbuf = 0x00000000;
    ncpreq.reqtype = 0x1111;
    ncpreq.seq = 0x00;
    ncpreq.connlow = 0xff;
    ncpreq.task = 0x01;
    ncpreq.connhi = 0xff;
    memcpy(sendbuff,&ncpreq, sizeof(ncpreq)-1);
    if (verbose)
    {
        printf("[+] Initializing connection with server\n");
    }
    /*
     * Send it
     */
    if ( (write(sockfd, &sendbuff,sizeof(ncpreq)-1)) == -1)
    {
        printf("[-] Error in writing to socket\n");
        exit(EXIT_FAILURE);
    }
    /*
     * Get the answer
     */
    if ( (result = read(sockfd, recvbuff, 16)) == -1)
    {
        printf("[-] Error communicating with server server\n");
        exit(EXIT_FAILURE);
    }
    memcpy(&ncpresponse,recvbuff,result);
    /*
     * Check if the NCP reply contains a correct
     * NCP reply identifier
     */
    if(ncpresponse.reqtype != 0x3333)
    {
        close(sockfd);
        printf("[-] Error connecting to server (NCP Reply = %x)\n", ncpresponse.reqtype);
        exit(EXIT_FAILURE);
    } else if (verbose)
    {
        printf("[+] Request Type: 0x%x\n", ncpresponse.reqtype);
    }
    ncpreq.connlow = ncpresponse.connlow;
    ncpreq.connhi = ncpresponse.connhi;
    ncpreq.seq = increment_seq(ncpresponse.seq);
    if (verbose)
    {
        conn = ncpresponse.connlow + ncpresponse.connhi;
        printf("[+] Attached to server with connection number : %d\n", conn);
    }
    return ncpreq;
}
/**
 * \fn struct NCP_Req get_server_info(struct NCP_Req ncpreq, int sockfd)
 * \brief This function will send an NCP Server Info Request and print the result
 * \param ncpreq NCP Request structure
 * \param sockfd socket file descriptor from initialize_conn
 * \return ncpreq NCP_Req structure
 */
struct NCP_Req get_server_info(struct NCP_Req ncpreq, int sockfd)
{
    char sendbuff[1024], recvbuff[1024];
    int result, i;
    struct NCP_Rep ncpresponse;
    /*
     * Reset buffers to 0
     */
    memset(sendbuff, 0, sizeof(sendbuff));
    memset(recvbuff, 0, sizeof(recvbuff));
    printf("\n\t[Server Information]\n\n");
    /*
     * Create NCP Request
     */
    ncpreq.sig = 0x54646d44;
    ncpreq.len = 0x1a000000;
    ncpreq.reqbuf = 0x80000000;
    ncpreq.reqtype = 0x2222;
    memcpy(sendbuff,&ncpreq,sizeof(ncpreq));
    sendbuff[req_hdr_sz] = 0x17;
    sendbuff[req_hdr_sz+1] = 0x00;
    sendbuff[req_hdr_sz+2] = 0x01;
    sendbuff[req_hdr_sz+3] = 0x11;
    /*
     * send the request
     */
    if ( (write(sockfd, &sendbuff, 26)) == -1)
    {
        printf("[-] Error in writing to socket\n");
        exit(EXIT_FAILURE);
    }
    /*
     * get the answer
     */
    if ( (result = read(sockfd, recvbuff, 256)) == -1)
    {
        printf("[-] Error communicating with server during info query\n");
        exit(EXIT_FAILURE);
    }
    memcpy(&ncpresponse,recvbuff,result);
    /*
     * check if the NCP reply contains a
     * correct NCP reply signature
     */
    if(ncpresponse.reqtype != 0x3333)
    {
        close(sockfd);
        printf("[-] Error getting data from server (NCP Reply = %x)\n",ncpresponse.reqtype);
        exit(EXIT_FAILURE);
    }
    ncpreq.seq = increment_seq(ncpresponse.seq);
    /*
     * Big ugly hack from ncpquery tool
     * This obviously needs to be fixed during my next audit
     * where I have a NDS server
     */
    if(ncpresponse.data[0] == 0x00)
    {
        printf("\tServer Name           : ");
        for (i=0; i<48; i++)
            if (ncpresponse.data[2+i] != 0x00) fprintf(stdout,"%c",ncpresponse.data[2+i]);
        printf("\n");
        printf("\tVersion               : %d\n",ncpresponse.data[50]);
        printf("\tSub-version           : %d\n",ncpresponse.data[51]);
        printf("\tMax Connections       : %d\n",ncpresponse.data[52] + ncpresponse.data[53]);
        printf("\tConn(s) in use        : %d\n",ncpresponse.data[54] + ncpresponse.data[55]);
        printf("\tRevision              : %d\n",ncpresponse.data[58]);
        printf("\tSFT level             : %d\n",ncpresponse.data[59]);
        printf("\tTTS level             : %d\n",ncpresponse.data[60]);
        printf("\tMax conn ever used    : %d\n",ncpresponse.data[61] + ncpresponse.data[62]);
        printf("\tAccount version       : %d\n",ncpresponse.data[63]);
        printf("\tVAP version           : %d\n",ncpresponse.data[64]);
        printf("\tQueue version         : %d\n",ncpresponse.data[65]);
        printf("\tPrint version         : %d\n",ncpresponse.data[66]);
        printf("\tVirtual console vers  : %d\n",ncpresponse.data[67]);
        printf("\tRestriction level     : %d\n",ncpresponse.data[68]);
        printf("\tInternet bridge       : %d\n",ncpresponse.data[69]);
    } else {
        close(sockfd);
        printf("[-] Error getting data from server (cc = %d)\n",ncpresponse.data[0]);
        exit(EXIT_FAILURE);
    }
    return ncpreq;
}
/**
 * \fn struct NCP_Req get_tree_name(struct NCP_Req ncpreq, int sockfd)
 * \brief This function will get the NDS Tree Name
 * \param ncpreq NCP_Req structure
 * \param sockfd socket file descriptor from intialize_conn
 * \return ncpreq NCP_Req structure
 */
struct NCP_Req get_tree_name(struct NCP_Req ncpreq, int sockfd)
{
    char sendbuff[1024], recvbuff[1024];
    int result, i;
    struct NCP_Rep ncpresponse;
    /*
     * Reset buffers to 0
     */
    memset(sendbuff, 0, sizeof(sendbuff));
    memset(recvbuff, 0, sizeof(recvbuff));
    /*
     * Create NCP query
     */
    ncpreq.sig = 0x54646d44;
    ncpreq.len = 0x1b000000;
    ncpreq.reqbuf = 0x28000000;
    ncpreq.reqtype = 0x2222;
    memcpy(sendbuff,&ncpreq,sizeof(ncpreq));
    sendbuff[req_hdr_sz] = 0x68;
    sendbuff[req_hdr_sz+1] = 0x01;
    sendbuff[req_hdr_sz+2] = 0x00;
    sendbuff[req_hdr_sz+3] = 0x00;
    /*
     * send the query
     */
    if ( (write(sockfd, &sendbuff, 27)) == -1)
    {
        printf("[-] Error in writing to socket\n");
        exit(EXIT_FAILURE);
    }
    /*
     * get the answer
     */
    if ( (result = read(sockfd, recvbuff, 256)) == -1)
    {
        printf("[-] Error communicating with server during NDS Ping\n");
        exit(EXIT_FAILURE);
    }
    memcpy(&ncpresponse,recvbuff,result);
    /*
     * check if the NCP reply contains a
     * correct NCP reply signature
     */
    if(ncpresponse.reqtype != 0x3333)
    {
        close(sockfd);
        printf("[-] Error getting data from server (NCP Reply = %x)\n",ncpresponse.reqtype);
        exit(EXIT_FAILURE);
    }
    ncpreq.seq = increment_seq(ncpresponse.seq);
    /*
     * again the ugly hack
     */
    if(ncpresponse.data[0] == 0x00)
    {
        printf("\n\tNDS Tree Name         : ");
        for (i=0; i<32; i++)
            if (ncpresponse.data[7+i] != 0x00) printf("%c",ncpresponse.data[7+i]);
            printf("\n");
    } else {
        close(sockfd);
        printf("[-] Error getting data from server (cc = %d)\n",ncpresponse.data[0]);
        exit(EXIT_FAILURE);
    }
    return ncpreq;
}
/**
 * \fn int get_custom_info(struct NCP_Req ncpreq, int sockfd, int all, int user, int group, int server)
 * \brief This function will get all NDS object information
 * \param ncpreq NCP Request structure
 * \param sockfd socket file descriptor from intialize_conn
 * \param all flag to print all information possible
 * \param user flag to print only user information
 * \param group flag to print only group information
 * \param server flag to print only server information
 * \return 0
 */
int get_custom_info(struct NCP_Req ncpreq, int sockfd, int all, int user, int group, int server)
{
    char sendbuff[1024], recvbuff[1024];
    int i, result;
    struct NCP_Rep ncpresponse;
    /*
     * Reset buffers to 0
     */
    memset(sendbuff, 0, sizeof(sendbuff));
    memset(recvbuff, 0, sizeof(recvbuff));
    /*
     * Create NCP query
     */
    ncpreq.sig = 0x54646d44;
    ncpreq.len = 0x22000000;
    ncpreq.reqbuf = 0x39000000;
    ncpreq.reqtype = 0x2222;
    ncpreq.task = 0x04;
    printf("\n\tObject ID Type         Name\n");
    printf("\t--------- ------------ ------------------------------------------------\n");
    for (i=0;i<4;i++) ncpresponse.data[2+i] = 0xff;
    while(1)
    {
        memcpy(sendbuff,&ncpreq,sizeof(ncpreq));
        sendbuff[req_hdr_sz] = 0x17;
        sendbuff[req_hdr_sz+1] = 0x00;
        sendbuff[req_hdr_sz+2] = 0x09;
        sendbuff[req_hdr_sz+3] = 0x37;
            for (i=0;i<4;i++)
                sendbuff[req_hdr_sz+4+i] = ncpresponse.data[2+i];
            sendbuff[req_hdr_sz+8] = 0xff;
            sendbuff[req_hdr_sz+9] = 0xff;
            sendbuff[req_hdr_sz+10] = 0x01;
            sendbuff[req_hdr_sz+11] = 0x2a;
            /*
             * send the request
             */
            if ( (write(sockfd, &sendbuff, 34)) == -1)
            {
                printf("[-] Error writing to socket\n");
                exit(EXIT_FAILURE);
            }
            /*
             * get the answer
             */
            if ( (result = read(sockfd, recvbuff, 256)) == -1)
            {
                printf("[-] Error communicating with server during object query\n");
                exit(EXIT_FAILURE);
            }
            memcpy(&ncpresponse,recvbuff,result);
            /*
             * check if the NCP reply contains a
             * correct NCP reply signature
             */
            if(ncpresponse.reqtype != 0x3333)
            {
                close(sockfd);
                printf("[-] Error getting data from server (NCP Reply = %x)\n",ncpresponse.reqtype);
                exit(EXIT_FAILURE);
            }
            if(ncpresponse.data[0] != 0x00)
            {
                printf("[+] EOF\n");
                break;
            }
            ncpreq.seq = increment_seq(ncpresponse.seq);
            /*
             * UgLy AgAiN
             * NeEdS tO bE fIxEd
			 * Getting tired of quick hacks in this code.
             */
            if((ncpresponse.data[6] == 0x00) && (ncpresponse.data[7] == 0x04) && (server))
            {
                printf("\t");
                for (i=0; i<4; i++)
                {
                    printf("%02x",ncpresponse.data[2+i]);
                }
                printf("  File Server  ");
                for (i=0; i<48; i++)
                    if (isprint(ncpresponse.data[8+i])) printf("%c",ncpresponse.data[8+i]);
                printf("\n");
            } else if ((ncpresponse.data[6] == 0x00) && (ncpresponse.data[7] == 0x02) && (group))
            {
                printf("\t");
                for (i=0; i<4; i++) printf("%02x",ncpresponse.data[2+i]);
                printf("  Group        ");
                for (i=0; i<48; i++)
                    if (isprint(ncpresponse.data[8+i])) printf("%c",ncpresponse.data[8+i]);
                printf("\n");
            } else if((ncpresponse.data[6] == 0x00) && (ncpresponse.data[7] == 0x01) && (user))
            {
                printf("\t");
                for (i=0; i<4; i++) printf("%02x",ncpresponse.data[2+i]);
                printf("  User         ");
                for (i=0; i<48; i++)
                    if (isprint(ncpresponse.data[8+i])) printf("%c",ncpresponse.data[8+i]);
                printf("\n");
            } else if(all)
            {
                printf("\t");
                for (i=0; i<4; i++) printf("%02x",ncpresponse.data[2+i]);
                if((ncpresponse.data[6] == 0x00) && (ncpresponse.data[7] == 0x03))
                    printf("  Print Queue  ");
                else if((ncpresponse.data[6] == 0x00) && (ncpresponse.data[7] == 0x07))
                    printf("  Print Server ");
                else if((ncpresponse.data[6] == 0x00) && (ncpresponse.data[7] == 0x47))
                    printf("  Adv Prnt Svr ");
                else if((ncpresponse.data[6] == 0x00) && (ncpresponse.data[7] == 0x77))
                    printf("  Unkn. Novell ");
                else if((ncpresponse.data[6] == 0x00) && (ncpresponse.data[7] == 0x4b))
                    printf("  Btrieve      ");
                else if((ncpresponse.data[6] == 0x01) && (ncpresponse.data[7] == 0x07))
                    printf("  RSPX         ");
                else if((ncpresponse.data[6] == 0x02) && (ncpresponse.data[7] == 0x6b))
                    printf("  NDS Tree     ");
                else if((ncpresponse.data[6] == 0x06) && (ncpresponse.data[7] == 0x40))
                    printf("  NT RPC Obj   ");
                else if((ncpresponse.data[6] == 0x06) && (ncpresponse.data[7] == 0x4e))
                    printf("  NT IIS Svr   ");
                else if((ncpresponse.data[6] == 0x03) && (ncpresponse.data[7] == 0x0c))
                    printf("  HP Jet Dir   ");
                else if((ncpresponse.data[6] == 0x02) && (ncpresponse.data[7] == 0x78))
                    printf("  Dir Server   ");
                else if((ncpresponse.data[6] == 0x02) && (ncpresponse.data[7] == 0x37))
                    printf("  NMS IPX      ");
                else if((ncpresponse.data[6] == 0x02) && (ncpresponse.data[7] == 0x38))
                    printf("  NMS IP       ");
                else if((ncpresponse.data[6] == 0x02) && (ncpresponse.data[7] == 0x3f))
                    printf("  SMS          ");
                else if((ncpresponse.data[6] == 0x82) && (ncpresponse.data[7] == 0x02))
                    printf("  NDPS Broker  ");
                else printf("  Other 0x%02x%02x ",ncpresponse.data[6],ncpresponse.data[7]);
                    for (i=0; i<48; i++)
                        if (isprint(ncpresponse.data[8+i])) printf("%c",ncpresponse.data[8+i]);
                    printf("\n");
            }
        }
    return 0;
}
/**
 * \fn int main(int argc, char **argv)
 * \brief This function is the main function
 * \param argc command line argument count
 * \param argv command line arguments
 * \return 0
 */
int main(int argc, char **argv)
{
    struct NCP_Req ncpreq;
    char ch;
    int sockfd, result;
    int verbose = 0;
    char *target;
    int server = 0, user = 0, group = 0, info = 0, all = 0;
    /*
     * get command line arguments
     */
    while ((ch = getopt(argc, argv, "iasughvn:")) != EOF)
    {
        switch(ch)
        {
            case 'i':
                info = 1;
                break;
            case 'a':
                all = 1;
                break;
            case 's':
                server = 1;
                break;
            case 'u':
                user = 1;
                break;
            case 'n':
                result = 0;
                target = optarg;
                break;
            case 'g':
                group = 1;
                break;
            case 'h':
                usage(argv[0]);
                exit(EXIT_SUCCESS);
            case 'v':
                verbose = 1;
                break;
            default:
                usage(argv[0]);
                exit(EXIT_FAILURE);
        }
    }
    if(!result)
    {
        printf("[-] No target specified\n");
        usage(argv[0]);
        exit(EXIT_FAILURE);
    }
    /*
     * Set default selection
     */
    if( (!info) && (!all) && (!user) && (!group) && (!server) ) user = 1;
    if(all)
    {
            info = 1;
        user = 1;
        group = 1;
        server = 1;
    }
    /*
     * do the work()
     */
    sockfd = initialize_conn(target);
    ncpreq = initialize_ncp(ncpreq, sockfd, verbose);
    ncpreq = get_server_info(ncpreq, sockfd);
    ncpreq = get_tree_name(ncpreq, sockfd);
    get_custom_info(ncpreq, sockfd, all, user, group, server);
    close(sockfd);
    return 0;
}
/*
 * EOF
*/

© 2015 coma. All rights reserved.
Disclaimer: There are NO warranties, implied or otherwise, with regard to this information or its use. Any use of this information is at the user's risk.
In no event shall the author be held liable for any damages whatsoever arising out of or in connection with the use or spread of this information.