Client - main page

Client makefile. CC=gcc. OBJS=main.o commands.o operations.o interface.o client: $(OBJS). Global.h. $(CC) -o client $(OBJS) -lxnet -lmd5 -lgen main.o: main.c.
262KB taille 6 téléchargements 262 vues
Client makefile CC=gcc OBJS=main.o commands.o client: $(OBJS)

operations.o

interface.o

Global.h

$(CC) -o client $(OBJS) -lxnet -lmd5 -lgen main.o: main.c $(CC) -c main.c commands.o: commands.c $(CC) -c commands.c operations.o: operations.c $(CC) -c operations.c interface.o: interface.c $(CC) -c interface.c

cygwinmakefile CC=gcc OBJS=main.o commands.o operations.o client: $(OBJS) $(CC) -o client $(OBJS) main.o: main.c $(CC) -c main.c commands.o: commands.c $(CC) -c commands.c operations.o: operations.c $(CC) -c operations.c interface.o: interface.c $(CC) -c interface.c md5.o: md5.c $(CC) -c md5.c

global.h #ifndef GLOBAL__ #define GLOBAL__ #include #include #include #include #include #include #include #include #include #include



#include #include #include #include

"commands.h" "interface.h" "operations.h" "md5.h"

interface.o

md5.o

#endif

/* —— GLOBAL__ —— */

main.c #include "global.h" char login[LOGIN_MAX_LENGTH] ; char password[PASSWORD_MAX_LENGTH] ; unsigned int isRoot ; unsigned int msgMaxLength ; keyword globalKeywords[11] ; void main (unsigned int argc, char ** argv) { int clientSocketID ; if (argc != 3) fprintf (stderr, "Usage error.") ; /* the correct usage is: client */ else if (atoi(argv[2])h_addr, &serverSocket.sin_addr,serverInfo>h_length); if ((serverSocketID = socket(AF_INET, SOCK_STREAM, 0)) < 0) { fprintf(stderr, "Error creating the socket.\n") ; }

exit(0) ;

if (connect(serverSocketID, &serverSocket, sizeof(struct sockaddr_in)) < 0) { /* connection with the server */ fprintf(stderr, "Error connecting with the server.\n") ;

}

close(serverSocketID) ; exit(0) ;

return serverSocketID ; } void closeSocket (int serverSocketID) { the socket ID */ close(serverSocketID) ; }

/* simply closing the socket using

unsigned int sendMsg (int clientSocketID, const char * msg, unsigned int msgLength) { /* simply (?!) sending a message to the client socket */ return send(clientSocketID, msg, msgLength, MSG_FLAG) ; /* returning the number of charaters actually sent */ } unsigned int receiveMsg (int clientSocketID, char * msg, unsigned int msgMaxLength) { /* simply (?!) receive a message from the client socket */ return recv(clientSocketID, msg, msgMaxLength, MSG_FLAG) ; /* returning the number of characters actually received */ } void clientWorkingLoop(int clientSocketID) { validateLogin(clientSocketID) ; receiveMsgLength(clientSocketID) ;

}

initGlobalKeywords() ; globalInterfaceLoop(clientSocketID) ;

void validateLogin(int clientSocketID) { /* ask for login and validate it with the server */ char tmpLogin[LOGIN_MAX_LENGTH] ; char tmpPassword[40]; char pwdnoecho[40]; char tmpPassHash[33]; /*array holding hash value of tmpPassword */ unsigned char digest[MSG_DIGEST_LENGTH]; char serverValidation[7] ; /* "OK" or "NOT OK" */ unsigned int i; MD5_CTX context; unsigned int len; fprintf(stdout, "login: ") ; gets(tmpLogin) ; sprintf(tmpLogin, "%s", tmpLogin) ; fprintf(stdout, "password: ") ; strcpy(tmpPassword, getpass(pwdnoecho)) ; */

/* compute hash function len = strlen (tmpPassword); MD5Init (&context); MD5Update (&context, tmpPassword, len); MD5Final (digest, &context); for( i = 0; i < MSG_DIGEST_LENGTH; i++ ) { sprintf( tmpPassHash + i * 2, "%02x", digest[i] ); }

*/

/* end Hash Function

sendMsg(clientSocketID, tmpLogin, LOGIN_MAX_LENGTH) ; login and password */

/* sending

sendMsg(clientSocketID, tmpPassHash, strlen(tmpPassHash)) ; receiveMsg(clientSocketID, serverValidation, 7) ; receiving validation */

/*

if (strcmp(serverValidation, "NOT OK") == 0) { login and/or password */ fprintf(stderr,"Wrong login or password.\n") ;

/* wrong

exit(0) ; } else if (strcmp(serverValidation, "OK") == 0) { we're in! */ system("clear") ;

/* ok,

strcpy(login, tmpLogin) ; strcpy(password, tmpPassword) ; if (strcmp(login, "root") == 0) /* if the user is root */ isRoot = 1; } else { /* something else */ fprintf(stderr,"Error receiving server validation for login.\n") ;

}

}

exit(0) ;

void receiveMsgLength(int clientSocketID) { if (receiveMsg(clientSocketID, &msgMaxLength, sizeof(int)) < 0) { fprintf(stderr,"Error receiving message length.\n") ;

}

}

exit(0) ;

void initCrypDecryp(unsigned long key) { srand(key) ; /* the only purpose of 'key' is to be the 'salt' of the srand(), if the 'salt' is the same then the rand() will be the same */ } void crypSentence(const char * inSentence, char * outSentence, const unsigned int length) { /* 'outSentence' needs to be allocated before calling 'cryptSentence()' */ char actualChar, modifiedChar ; unsigned int i ; unsigned int randValue ; for (i = 0 ; i < length ; i += 1) { randValue = (rand() % 5) ;

}

}

actualChar = inSentence[i] ; modifiedChar = (actualChar + randValue) % 256 ; outSentence[i] = modifiedChar ;

void decrypSentence(const char * inSentence, char * outSentence, const unsigned int length) { char actualChar ;

int modifiedChar ; /* int because I need 'modifiedChar' to be able to be negative */ unsigned int i ; unsigned int randValue ; for (i = 0 ; (i < length) && (inSentence[i] != '\0') ; i += 1) { randValue = (rand() % 5) ; actualChar = inSentence[i] ; modifiedChar = actualChar - randValue ; if (modifiedChar < 0) modifiedChar = 256 - modifiedChar ;

}

}

outSentence[i] = modifiedChar ;

void MDString (char *string,unsigned char *digest) { MD5_CTX context; // An MD5 context structure that is used as an input argument for the MD5 functions //unsigned char digest[MSG_DIGEST_LENGTH ]; unsigned int len = strlen (string); MD5Init (&context); // This function must be called every time a new hash needs to be computed.takes as input the context structure MD5Update (&context, string, len); //updates the MD5 context updates that will be used in the final hash output MD5Final (digest, &context); //generates the final MD5 hash, using the md5 context that was updated in the calls to MD5Update. //now digest contains the hash value printf ("MD5 (\"%s\") = ", string); MDPrint (digest); //print digest // printf ("\n"); //strcpy(digest,string); } void {

MDPrint (unsigned char *digest)

unsigned int i; for (i = 0; i < MSG_DIGEST_LENGTH ; i++) printf ("%x", digest[i]); printf("\n"); }

md5.h #ifndef _MD5_H_

#define _MD5_H_ #include #define MD5_HASHBYTES 16 typedef struct unsigned unsigned unsigned } MD5_CTX; extern void extern void

MD5Context { long buf[4]; long bits[2]; char in[64];

MD5Init(MD5_CTX *context); MD5Update(MD5_CTX *context, const unsigned char *buf, unsigned int len); MD5Final(unsigned char digest[MD5_HASHBYTES], MD5_CTX *

extern void context); extern void MD5Transform(unsigned long buf[4], const unsigned long in[16]); extern char * MD5End(MD5_CTX *, char *); extern char * MD5File(const char *, char *); extern char * MD5Data (const unsigned char *, unsigned int, char *); #endif /* !_MD5_H_ */

md5.c /* * This code implements the MD5 message-digest algorithm. * The algorithm is due to Ron Rivest. This code was * written by Colin Plumb in 1993, no copyright is claimed. * This code is in the public domain; do with it what you wish. * * Equivalent code is available from RSA Data Security, Inc. * This code has been tested against that, and is equivalent, * except that you don't need to include two pages of legalese * with every copy. * * To compute the message digest of a chunk of bytes, declare an * MD5Context structure, pass it to MD5Init, call MD5Update as * needed on buffers full of bytes, and then call MD5Final, which * will fill a supplied 16-byte array with the digest. */ #include #include "md5.h"

/* for memcpy() */

#if __BYTE_ORDER == 1234 #define byteReverse(buf, len) /* Nothing */ #else void byteReverse(unsigned char *buf, unsigned longs); /* * Note: this code is harmless on little-endian machines. */ void byteReverse(unsigned char *buf, unsigned longs) { u_int32_t t; do { t = (u_int32_t) ((unsigned) buf[3] buf[2] = 0x98badcfe; ctx->buf[3] = 0x10325476;

}

ctx->bits[0] = 0; ctx->bits[1] = 0;

/* * Update context to reflect the concatenation of another buffer full * of bytes. */ void MD5Update(MD5_CTX *ctx, unsigned char const *buf, unsigned len) { u_int32_t t; /* Update bitcount */ t = ctx->bits[0]; if ((ctx->bits[0] = t + ((u_int32_t) len bits[1]++; /* Carry from low to high */ ctx->bits[1] += len >> 29; t = (t >> 3) & 0x3f;

/* Bytes already in shsInfo->data */

/* Handle any leading odd-sized chunks */ if (t) { unsigned char *p = (unsigned char *) ctx->in + t; t = 64 - t; if (len < t) { memcpy(p, buf, len); return; } memcpy(p, buf, t); byteReverse(ctx->in, 16); MD5Transform(ctx->buf, (u_int32_t *) ctx->in); buf += t; len -= t;

} /* Process data in 64-byte chunks */

while (len >= 64) { memcpy(ctx->in, buf, 64); byteReverse(ctx->in, 16); MD5Transform(ctx->buf, (u_int32_t *) ctx->in);

}

buf += 64; len -= 64;

/* Handle any remaining bytes of data. */ }

memcpy(ctx->in, buf, len);

/* * Final wrapup - pad to 64-byte boundary with the bit pattern * 1 0* (64-bit count of bits processed, MSB-first) */ void MD5Final(unsigned char digest[16], MD5_CTX *ctx) { unsigned count; unsigned char *p; /* Compute number of bytes mod 64 */ count = (ctx->bits[0] >> 3) & 0x3F; /* Set the first char of padding to 0x80. always at least one byte free */ p = ctx->in + count; *p++ = 0x80;

This is safe since there is

/* Bytes of padding needed to make 64 bytes */ count = 64 - 1 - count; /* Pad out to 56 mod 64 */ if (count < 8) { /* Two lots of padding: Pad the first block to 64 bytes */ memset(p, 0, count); byteReverse(ctx->in, 16); MD5Transform(ctx->buf, (u_int32_t *) ctx->in); /* Now fill the next block with 56 bytes */ memset(ctx->in, 0, 56); } else { /* Pad block to 56 bytes */ memset(p, 0, count - 8); } byteReverse(ctx->in, 14); /* Append length in bits and transform */ ((u_int32_t *) ctx->in)[14] = ctx->bits[0]; ((u_int32_t *) ctx->in)[15] = ctx->bits[1];

}

MD5Transform(ctx->buf, (u_int32_t *) ctx->in); byteReverse((unsigned char *) ctx->buf, 4); memcpy(digest, ctx->buf, 16); memset((char *) ctx, 0, sizeof(ctx)); /* In case it's sensitive */

/* The four core functions - F1 is optimized somewhat */ /* #define F1(x, #define F1(x, y, #define F2(x, y, #define F3(x, y, #define F4(x, y,

y, z) z) z) z)

z) (x & y | ~x & z) */ (z ^ (x & (y ^ z))) F1(z, x, y) (x ^ y ^ z) (y ^ (x | ~z))

/* This is the central step in the MD5 algorithm. */ #define MD5STEP(f, w, x, y, z, data, s) \ ( w += f(x, y, z) + data, w = w(32-s),

w += x )

/* * The core of the MD5 algorithm, this alters an existing MD5 hash to * reflect the addition of 16 longwords of new data. MD5Update blocks * the data and converts bytes into longwords for this routine. */ void MD5Transform(unsigned long buf[4], const unsigned long in[16]) { register unsigned long a, b, c, d; a b c d

= = = =

buf[0]; buf[1]; buf[2]; buf[3];

MD5STEP(F1, MD5STEP(F1, MD5STEP(F1, MD5STEP(F1, MD5STEP(F1, MD5STEP(F1, MD5STEP(F1, MD5STEP(F1, MD5STEP(F1, MD5STEP(F1, MD5STEP(F1, MD5STEP(F1, MD5STEP(F1, MD5STEP(F1, MD5STEP(F1, MD5STEP(F1,

a, d, c, b, a, d, c, b, a, d, c, b, a, d, c, b,

b, a, d, c, b, a, d, c, b, a, d, c, b, a, d, c,

c, b, a, d, c, b, a, d, c, b, a, d, c, b, a, d,

d, c, b, a, d, c, b, a, d, c, b, a, d, c, b, a,

in[0] + 0xd76aa478, 7); in[1] + 0xe8c7b756, 12); in[2] + 0x242070db, 17); in[3] + 0xc1bdceee, 22); in[4] + 0xf57c0faf, 7); in[5] + 0x4787c62a, 12); in[6] + 0xa8304613, 17); in[7] + 0xfd469501, 22); in[8] + 0x698098d8, 7); in[9] + 0x8b44f7af, 12); in[10] + 0xffff5bb1, 17); in[11] + 0x895cd7be, 22); in[12] + 0x6b901122, 7); in[13] + 0xfd987193, 12); in[14] + 0xa679438e, 17); in[15] + 0x49b40821, 22);

MD5STEP(F2, MD5STEP(F2, MD5STEP(F2, MD5STEP(F2, MD5STEP(F2, MD5STEP(F2, MD5STEP(F2, MD5STEP(F2, MD5STEP(F2, MD5STEP(F2, MD5STEP(F2, MD5STEP(F2, MD5STEP(F2, MD5STEP(F2, MD5STEP(F2, MD5STEP(F2,

a, d, c, b, a, d, c, b, a, d, c, b, a, d, c, b,

b, a, d, c, b, a, d, c, b, a, d, c, b, a, d, c,

c, b, a, d, c, b, a, d, c, b, a, d, c, b, a, d,

d, c, b, a, d, c, b, a, d, c, b, a, d, c, b, a,

in[1] + 0xf61e2562, 5); in[6] + 0xc040b340, 9); in[11] + 0x265e5a51, 14); in[0] + 0xe9b6c7aa, 20); in[5] + 0xd62f105d, 5); in[10] + 0x02441453, 9); in[15] + 0xd8a1e681, 14); in[4] + 0xe7d3fbc8, 20); in[9] + 0x21e1cde6, 5); in[14] + 0xc33707d6, 9); in[3] + 0xf4d50d87, 14); in[8] + 0x455a14ed, 20); in[13] + 0xa9e3e905, 5); in[2] + 0xfcefa3f8, 9); in[7] + 0x676f02d9, 14); in[12] + 0x8d2a4c8a, 20);

MD5STEP(F3, MD5STEP(F3, MD5STEP(F3, MD5STEP(F3, MD5STEP(F3, MD5STEP(F3, MD5STEP(F3, MD5STEP(F3,

a, d, c, b, a, d, c, b,

b, a, d, c, b, a, d, c,

c, b, a, d, c, b, a, d,

d, c, b, a, d, c, b, a,

in[5] + 0xfffa3942, 4); in[8] + 0x8771f681, 11); in[11] + 0x6d9d6122, 16); in[14] + 0xfde5380c, 23); in[1] + 0xa4beea44, 4); in[4] + 0x4bdecfa9, 11); in[7] + 0xf6bb4b60, 16); in[10] + 0xbebfbc70, 23);

MD5STEP(F3, MD5STEP(F3, MD5STEP(F3, MD5STEP(F3, MD5STEP(F3, MD5STEP(F3, MD5STEP(F3, MD5STEP(F3,

a, d, c, b, a, d, c, b,

b, a, d, c, b, a, d, c,

c, b, a, d, c, b, a, d,

d, c, b, a, d, c, b, a,

in[13] + 0x289b7ec6, 4); in[0] + 0xeaa127fa, 11); in[3] + 0xd4ef3085, 16); in[6] + 0x04881d05, 23); in[9] + 0xd9d4d039, 4); in[12] + 0xe6db99e5, 11); in[15] + 0x1fa27cf8, 16); in[2] + 0xc4ac5665, 23);

MD5STEP(F4, MD5STEP(F4, MD5STEP(F4, MD5STEP(F4, MD5STEP(F4, MD5STEP(F4, MD5STEP(F4, MD5STEP(F4, MD5STEP(F4, MD5STEP(F4, MD5STEP(F4, MD5STEP(F4, MD5STEP(F4, MD5STEP(F4, MD5STEP(F4, MD5STEP(F4,

a, d, c, b, a, d, c, b, a, d, c, b, a, d, c, b,

b, a, d, c, b, a, d, c, b, a, d, c, b, a, d, c,

c, b, a, d, c, b, a, d, c, b, a, d, c, b, a, d,

d, c, b, a, d, c, b, a, d, c, b, a, d, c, b, a,

in[0] + 0xf4292244, 6); in[7] + 0x432aff97, 10); in[14] + 0xab9423a7, 15); in[5] + 0xfc93a039, 21); in[12] + 0x655b59c3, 6); in[3] + 0x8f0ccc92, 10); in[10] + 0xffeff47d, 15); in[1] + 0x85845dd1, 21); in[8] + 0x6fa87e4f, 6); in[15] + 0xfe2ce6e0, 10); in[6] + 0xa3014314, 15); in[13] + 0x4e0811a1, 21); in[4] + 0xf7537e82, 6); in[11] + 0xbd3af235, 10); in[2] + 0x2ad7d2bb, 15); in[9] + 0xeb86d391, 21);

buf[0] buf[1] buf[2] buf[3]

+= += += +=

a; b; c; d;

}

interface.h #ifndef INTERFACE__ #define INTERFACE__ typedef struct _keyword { char word[11] ; unsigned int nbForwardingElements ; unsigned char needRoot ; } keyword ; void initGlobalKeywords(void) ; unsigned int findRightKeyword(const char * ) ; unsigned int getRightParameter(const char *, unsigned int, char *) ; unsigned int getRightParameterV2(const char *, unsigned int, unsigned int, char *) ; void reactToRightKeyword(const unsigned int, const char *, int) ; void globalInterfaceLoop(int) ; #endif

/* —— INTERFACE__ —— */

interface.c #include "global.h" extern char login[LOGIN_MAX_LENGTH] ;

extern char password[PASSWORD_MAX_LENGTH] ; extern unsigned int isRoot ; extern unsigned int msgMaxLength = 11 ; extern keyword globalKeywords[11] ; const unsigned int globalKeywordsLength = 11 ; void initGlobalKeywords(void) { strcpy(globalKeywords[0].word,"exit") ; globalKeywords[0].nbForwardingElements = 0 ; globalKeywords[0].needRoot = 0 ; strcpy(globalKeywords[1].word,"addfile") ; globalKeywords[1].nbForwardingElements = 2 ; globalKeywords[1].needRoot = 0 ; strcpy(globalKeywords[2].word,"removefile") ; globalKeywords[2].nbForwardingElements = 1 ; globalKeywords[2].needRoot = 0 ; strcpy(globalKeywords[3].word,"listdir") ; globalKeywords[3].nbForwardingElements = 0 ; globalKeywords[3].needRoot = 0 ; strcpy(globalKeywords[4].word,"listdirfull") ; globalKeywords[4].nbForwardingElements = 0 ; globalKeywords[4].needRoot = 0 ; strcpy(globalKeywords[5].word,"listfile") ; globalKeywords[5].nbForwardingElements = 1 ; globalKeywords[5].needRoot = 0 ; strcpy(globalKeywords[6].word,"adduser") ; globalKeywords[6].nbForwardingElements = 2 ; globalKeywords[6].needRoot = 1 ; strcpy(globalKeywords[7].word,"removeuser") ; globalKeywords[7].nbForwardingElements = 1 ; globalKeywords[7].needRoot = 1 ; strcpy(globalKeywords[8].word,"changepass") ; globalKeywords[8].nbForwardingElements = 2 ; globalKeywords[8].needRoot = 1 ; strcpy(globalKeywords[9].word,"help") ; globalKeywords[9].nbForwardingElements = 0 ; globalKeywords[9].needRoot = 0 ; strcpy(globalKeywords[10].word,"clear") ; globalKeywords[10].nbForwardingElements = 0 ; globalKeywords[10].needRoot = 0 ; } unsigned int findRightKeyword(const char * line) { an error */ unsigned int rightKeyword = 0 ; unsigned int i, j ; regex_t regularExpression; char tmpRegularExpression[128] ; unsigned int regularExpressionError ;

/* return 0 in case of

for (i = 0 ; i < globalKeywordsLength ; i += 1) { if (globalKeywords[i].nbForwardingElements == 0) { sprintf(tmpRegularExpression, "^[\t ]*%s[\t ]*$", globalKeywords[i].word) ; /* any number of 'spaces' followed by the keyword followed by any number of 'spaces' */ } else if (globalKeywords[i].nbForwardingElements == 1) { sprintf(tmpRegularExpression, "^[\t ]*%s[\t ]+[a-z09._]+[\t ]*$", globalKeywords[i].word) ; /* any number of 'spaces' followed by the keyword followed by at least one 'space' followed by another word followed by any number of 'spaces' */

} else if (globalKeywords[i].nbForwardingElements == 2) { sprintf(tmpRegularExpression, "^[\t ]*%s[\t ]+[a-z09._]+[\t ]+[a-z0-9._]+[\t ]*$", globalKeywords[i].word) ; /* any number of 'spaces' followed by the keyword followed by at least one 'space' followed by another word followed by at least one 'space' followed by another another word followed by any number of 'spaces' ouf! we did it! */ /* Is not this perfectly clear?! */ } if ((regularExpressionError = regcomp(®ularExpression, tmpRegularExpression, REG_ICASE | REG_NOSUB | REG_EXTENDED)) != 0) fprintf(stderr, "Regular expression initialisation problem.\n") ; else { if(regexec(®ularExpression, line, 0, NULL, 0) == 0) { /* founded */ rightKeyword = i + 1 ; break ; } } } }

return rightKeyword ;

unsigned int getRightParameter(const char * line, unsigned int parameterID, char * outBuffer) { regex_t regularExpression; char tmpRegularExpression[25] ; regmatch_t tmpRightParameter[2] ; if (parameterID == 1) strcpy(tmpRegularExpression, "^[\t ]*[a-z0-9._]+[\t ]+([a-z09._]+)[\t ]*") ; else if (parameterID == 2) strcpy(tmpRegularExpression, "^[\t ]*[a-z0-9._]+[\t ]+[a-z09._]+[\t ]+([a-z0-9._]+)[\t ]*") ; if (regcomp( ®ularExpression, tmpRegularExpression, REG_ICASE | REG_EXTENDED ) != 0) fprintf(stderr, "Regular expression initialisation problem.\n") ; else { if(regexec(®ularExpression, line, 2, tmpRightParameter, 0) == 0) { /* ouf! we found the right parameter */ strcpy(outBuffer, (line + tmpRightParameter[1].rm_so)) ; /* a bit complicate... but it work... at least... it's suppose to! */ outBuffer[(tmpRightParameter[1].rm_eo tmpRightParameter[1].rm_so)] = '\0' ; } } } unsigned int getRightParameterV2(const char * line, unsigned int rightKeyword, unsigned int parameterID, char * outBuffer) { char findingString[256] ; char tmpBuffer1[256] ; char tmpBuffer2[256] ; if (globalKeywords[rightKeyword].nbForwardingElements == 2) /* writing the string we will use to get the parameter */

sprintf(findingString, "%s %%s %%s\n", globalKeywords[rightKeyword].word) ; else if (globalKeywords[rightKeyword].nbForwardingElements == 1) sprintf(findingString, "%s %%s\n", globalKeywords[rightKeyword].word) ; if (globalKeywords[rightKeyword].nbForwardingElements == 2) sscanf(line, findingString, tmpBuffer1, tmpBuffer2) ; else if (globalKeywords[rightKeyword].nbForwardingElements == 1) sscanf(line, findingString, tmpBuffer1) ;

}

if (parameterID == 1) /* taking the right parameter */ strcpy(outBuffer, tmpBuffer1) ; else if (parameterID == 2) strcpy(outBuffer, tmpBuffer2) ;

void reactToRightKeyword (const unsigned int keywordNumber, const char * line, int clientSocketID) { char tmpCommandParameterBuffer1[256] ; char tmpCommandParameterBuffer2[256] ; switch (keywordNumber) { case 1: /* 01: addfile: when the user want's to add a file on the server */ getRightParameterV2(line, keywordNumber, 1, tmpCommandParameterBuffer1) ; getRightParameterV2(line, keywordNumber, 2, tmpCommandParameterBuffer2) ; addfileCommand(clientSocketID, tmpCommandParameterBuffer1, tmpCommandParameterBuffer2) ; break ; case 2: /* 02: removefile: when the user want's to remove a file from the server */ getRightParameterV2(line, keywordNumber, 1, tmpCommandParameterBuffer1) ; removefileCommand(clientSocketID, tmpCommandParameterBuffer1) ; break ; case 3: /* 03: listdir: when the user want's to see which files are on the server */ listdirCommand(clientSocketID) ; break ; case 4: /* 04: listdirfull: when the user want's to see more informations about his files on the server */ listdirfullCommand(clientSocketID) ; break ; case 5: /* 05: listfile: when the user want's to watch one of his file on the server */ getRightParameterV2(line, keywordNumber, 1, tmpCommandParameterBuffer1) ; listfileCommand(clientSocketID, tmpCommandParameterBuffer1) ;

user */

break ; case 6:

/* 06: adduser: when the root want's to add an

getRightParameterV2(line, keywordNumber, 1, tmpCommandParameterBuffer1) ; getRightParameterV2(line, keywordNumber, 2, tmpCommandParameterBuffer2) ; if (isRoot == 1) adduserCommand(clientSocketID, tmpCommandParameterBuffer1, tmpCommandParameterBuffer2) ; else fprintf(stderr, "It would be easier if you were root! Sorry.\n") ; break ; case 7: /* 07: removeuser: when the root want's to remove an user */ getRightParameterV2(line, keywordNumber, 1, tmpCommandParameterBuffer1) ; if (isRoot == 1) removeuserCommand(clientSocketID, tmpCommandParameterBuffer1) ; else fprintf(stderr, "It would be easier if you were root! Sorry.\n") ; break ; case 8: /* 08: changepass: when the root want's to change an user password */ getRightParameterV2(line, keywordNumber, 1, tmpCommandParameterBuffer1) ; getRightParameterV2(line, keywordNumber, 2, tmpCommandParameterBuffer2) ; if (isRoot == 1) changepassCommand(clientSocketID, tmpCommandParameterBuffer1, tmpCommandParameterBuffer2) ; else fprintf(stderr, "It would be easier if you were root! Sorry.\n") ;

the help */

break ; case 9:

/* 09: help: when the user want's to access to

fprintf(stdout, "______________________________________________________________________\n") ; fprintf(stdout, "help:\t\tprint this (that may be helpfull, who knows?!).\n") ; fprintf(stdout, "clear:\tclear the screen.\n") ; fprintf(stdout, "exit:\t\texit to the shell.\n") ; fprintf(stdout, "addfile:\tsend a file to the server.\n") ; fprintf(stdout, "\taddfile \n") ; fprintf(stdout, "removefile:\tremove a file from the server.\n") ; fprintf(stdout, "\tremovefile \n") ;

fprintf(stdout, "listdir:\tlist your files on server.\n")

;

fprintf(stdout, "listdirfull:\tlist your files on server with informations on them.\n") ; fprintf(stdout, "listfile:\tlist the content of a file on server.\n") ; fprintf(stdout, "\tlistfile \n") ;

screen */

break ; case 10:

/* 10: clear: when the user wants to clear his

system("clear") ;

break ; default: /* normally they shouldn’t be any 'default' instruction */ fprintf(stdout, "There is a recognition error.\n") ;

}

break ;

}

void globalInterfaceLoop(int clientSocketID) { unsigned int resKeyword = 0 ; char tmpLine[50] ; while (resKeyword != 1) { fprintf(stdout, "%s @> ", login) ; gets(tmpLine) ; sprintf(tmpLine, "%s", tmpLine) ; resKeyword = findRightKeyword(tmpLine) ; if (resKeyword == 1) { sendMsg(clientSocketID, "EXIT", 5) ; server to kill himself */

/* tell the

return ; } else if (resKeyword == 0) fprintf(stdout, "The expression \"%s\" have not been reconized.\n", tmpLine) ; else reactToRightKeyword((resKeyword - 1), tmpLine, clientSocketID) ; } }

commands.h #ifndef COMMANDS__ #define COMMANDS__ void void void void void void void

listdirfullCommand(int) ; listdirCommand(int) ; addfileCommand(int, const char *, const char *) ; removefileCommand(int, const char *) ; listfileCommand(int, const char *) ; adduserCommand(int, const char *, const char *) ; removeuserCommand(int, const char *) ;

void changepassCommand(int, const char *, const char *) ; #endif

/* —— COMMANDS__ —— */

commands.c #include "global.h" extern char login[LOGIN_MAX_LENGTH] ; extern char password[PASSWORD_MAX_LENGTH] ; extern unsigned int isRoot ; extern unsigned int msgMaxLength ; extern keyword globalKeywords[11] ; void listdirCommand(int clientSocketID) { the directory */ char tmpFileName[16] ; socket to 'stdout' */ unsigned int fileCount = 0 ;

/* receiving the listing of /* direct print from the

sendMsg(clientSocketID, "LISTDIR", 8) ; do {

receiveMsg(clientSocketID, tmpFileName, 16) ; if (strcmp(tmpFileName, "ENDOFCOMMAND") != 0) { fprintf(stdout, "%s _\n", tmpFileName) ;

fileCount += 1 ; } } while (strcmp(tmpFileName, "ENDOFCOMMAND") != 0) ; fprintf(stdout, "There are/is %i file(s) in your directory.\n", fileCount) ; } void listdirfullCommand(int clientSocketID) { char tmpFileName[16] ; char tmpFileTimestampString[32] ; time_t tmpFileTimestamp ; unsigned int fileCount = 0 ; sendMsg(clientSocketID, "LISTDIRFULL", 12) ; do {

memset(tmpFileName, '\0', 16) ; memset(tmpFileTimestampString, '\0', 16) ; receiveMsg(clientSocketID, tmpFileName, 16) ; if (strcmp(tmpFileName, "ENDOFCOMMAND") != 0) { receiveMsg(clientSocketID, tmpFileTimestampString, 12) ; tmpFileTimestampString[12] = '\0'; tmpFileTimestamp = atoi(tmpFileTimestampString) ;

strcpy(tmpFileTimestampString, asctime(localtime(&tmpFileTimestamp))) ; fprintf(stdout, "%s\t%s", tmpFileName, tmpFileTimestampString) ; fileCount += 1 ; } } while (strcmp(tmpFileName, "ENDOFCOMMAND") != 0) ; fprintf(stdout, "There are/is %i file(s) in your directory.\n", fileCount) ; } void addfileCommand(int clientSocketID, const char * fileName, const char * fileURL) { /* the encryption is on the client side */ FILE * filePtr ; unsigned long encryptionKey ; char tmpFileBuffer[256] ; char tmpEncryptedFileBuffer[256] ; char readCharactersNb ; /* —— first, checking if the file exist on the client —— */ if ((filePtr = fopen(fileURL, "rb")) == NULL) { fprintf(stderr, "The file '%s' does not exist.\n", fileURL) ; }

return ;

/* ————————————————————————————————————————————————————— */ /* —— sending the information from the file — waiting for the encryption key —— */ sendMsg(clientSocketID, "ADDFILE", 8) ; sendMsg(clientSocketID, fileName, (strlen(fileName) + 1)) ; receiveMsg(clientSocketID, &encryptionKey, sizeof(long)) ; /* —————————————————————————————————————————————————————————————————— —————————— */ /* —— encrypt the file and send it to the server —— */ initCrypDecryp(encryptionKey) ; while ((readCharactersNb = fread(tmpFileBuffer, 1, msgMaxLength, filePtr)) > 0) { crypSentence(tmpFileBuffer, tmpEncryptedFileBuffer, readCharactersNb) ; /* encrypting the buffer */ sendMsg(clientSocketID, tmpEncryptedFileBuffer, readCharactersNb) ; /* sending the buffer */ } sendMsg(clientSocketID, "ENDOFFILE", 10) ; /* ———————————————————————————————————————————————— */ fclose(filePtr) ; fprintf(stdout, "The file '%s' as correctly been sent to the server.\n", fileName) ;

} void removefileCommand(int clientSocketID, const char * fileName) { char tmpCallBack[13] ; unsigned int fileCount = 0 ; sendMsg(clientSocketID, "REMOVEFILE", 11) ; sendMsg(clientSocketID, fileName, (strlen(fileName) + 1)) ; receiveMsg(clientSocketID, tmpCallBack, 13) ; if (strcmp(tmpCallBack, "NOTEXIST") == 0) fprintf(stderr, "The file '%s' does not exist.\n", fileName) ; else if (strcmp(tmpCallBack, "ENDOFCOMMAND") != 0) { fprintf(stderr, "Error receiving the command receip.\n") ; exit(0) ; } else fprintf(stdout, "'%s' as been successfully removed from the server.\n", fileName) ; } void listfileCommand(int clientSocketID, const char * fileName) { unsigned long encryptionKey ; char tmpFileBuffer[256] ; char tmpDecryptedFileBuffer[256] ; unsigned int readCharactersNb ; /* —— asking (politly!) to the server for the file —— */ sendMsg(clientSocketID, "LISTFILE", 9) ; sendMsg(clientSocketID, fileName, (strlen(fileName) + 1)) ; receiveMsg(clientSocketID, &encryptionKey, sizeof(long)) ; the server respond with the encryption key */

/*

/* —— now receiving the encrypted file, decrypting it and put it on the screen —— */ initCrypDecryp(encryptionKey) ; while (strcmp(tmpFileBuffer, "ENDOFFILE") != 0) { memset(tmpFileBuffer, '\0', 256) ; memset(tmpDecryptedFileBuffer, '\0', 256) ; readCharactersNb = receiveMsg(clientSocketID, tmpFileBuffer, msgMaxLength) ; /* receiving the encrypted buffer */ if (strcmp((tmpFileBuffer + (strlen(tmpFileBuffer) - 9)), "ENDOFFILE") != 0) { decrypSentence(tmpFileBuffer, tmpDecryptedFileBuffer, readCharactersNb) ; fputs(tmpDecryptedFileBuffer, stdout) ; } else if (strcmp(tmpFileBuffer, "NOTEXIST") == 0) { /* testting if the file really exist */ fprintf(stderr, "The file '%s' does not exist.\n", fileName) ; return ; } else { tmpFileBuffer[(strlen(tmpFileBuffer) - 9)] = '\0' ;

decrypSentence(tmpFileBuffer, tmpDecryptedFileBuffer, readCharactersNb) ; fputs(tmpDecryptedFileBuffer, stdout) ; }

}

break ;

/* —————————————————————————————————————————————————————————————————— ———————————— */ fprintf(stdout, "\n") ;

}

/* —— euh! that's all! great! —— */ /* ————————————————————————————— */

void adduserCommand(int clientSocketID, const char * newUserName, const char * newPassword) { char tmpCallBack[13] ; /* compute hash of 2nd parameter=password */ char tmpPassHash[33]; /* array holding hash value of tmpPassword */ unsigned char digest[MSG_DIGEST_LENGTH]; unsigned int i; unsigned int len; MD5_CTX context; len = strlen (newPassword); sendMsg(clientSocketID, "ADDUSER", 8) ; sendMsg(clientSocketID, newUserName, 16) ; MD5Init (&context); MD5Update (&context, newPassword, len); MD5Final (digest, &context); {

for( i = 0; i < MSG_DIGEST_LENGTH; i++ ) }

sprintf( tmpPassHash + i * 2, "%02x", digest[i] );

strcat(tmpPassHash,":"); sendMsg(clientSocketID, tmpPassHash,strlen(tmpPassHash)); receiveMsg(clientSocketID, tmpCallBack, 13) ; if (strcmp(tmpCallBack, "ENDOFCOMMAND") != 0) { fprintf(stderr, "Error receiving the command receip.\n") ; exit(0) ; } else fprintf(stdout, "We are proud to annonce that '%s' can now access the server.\n", newUserName) ; } void removeuserCommand(int clientSocketID, const char * userName) { char tmpCallBack[13] ;

sendMsg(clientSocketID, "REMOVEUSER", 11) ; sendMsg(clientSocketID, userName, (strlen(userName) + 1)) ; receiveMsg(clientSocketID, tmpCallBack, 13) ; if (strcmp(tmpCallBack, "NOTEXIST") == 0) fprintf(stderr, "The user '%s' does not exist.\n", userName) ; else if (strcmp(tmpCallBack, "ENDOFCOMMAND") != 0) { fprintf(stderr, "Error receiving the command receip.\n") ; exit(0) ; } else fprintf(stdout, "'%s' cannot anymore access the server.\n", userName) ; } void changepassCommand(int clientSocketID, const char * userName, const char * newPassword) { char tmpCallBack[13] ; /* compute hash of 2nd parameter=password */ char tmpPassHash[34]; /*array holding hash value of tmpPassword */ unsigned char digest[MSG_DIGEST_LENGTH]; unsigned int i; unsigned int len = strlen (newPassword); MD5_CTX context; sendMsg(clientSocketID, "CHANGEPASS", 10) ; sendMsg(clientSocketID, userName, 16) ; MD5Init (&context); MD5Update (&context, newPassword, len); MD5Final (digest, &context); for( i = 0; i < MSG_DIGEST_LENGTH; i++ ) { sprintf( tmpPassHash + i * 2, "%02x", digest[i]); } strcat(tmpPassHash,":") ; /* end password hash */ sendMsg(clientSocketID, tmpPassHash,34) ; receiveMsg(clientSocketID, tmpCallBack, 13) ; if (strcmp(tmpCallBack, "NOTEXIST") == 0) fprintf(stderr, "The user '%s' does not exist.\n", userName) ; else if (strcmp(tmpCallBack, "ENDOFCOMMAND") != 0) { fprintf(stderr, "Error receiving the command receip.\n") ; exit(0) ; } else fprintf(stdout, "'%s' 's password has successfully been changed.\n", userName) ; }

Server makefile CC=gcc OBJS=main.o commands.o operations.o server: $(OBJS) $(CC) -o server $(OBJS) -lxnet main.o: main.c $(CC) -c main.c commands.o: commands.c $(CC) -c commands.c operations.o: operations.c $(CC) -c operations.c

cygwinmakefile CC=gcc OBJS=main.o commands.o operations.o server: $(OBJS) $(CC) -o server $(OBJS) main.o: main.c $(CC) -c main.c commands.o: commands.c $(CC) -c commands.c operations.o: operations.c $(CC) -c operations.c

global.h #ifndef GLOBAL__ #define GLOBAL__ #include #include #include #include #include #include #include #include #include #include



#include "commands.h" #include "operations.h" #endif

/* —— GLOBAL__ —— */

main.c #include "global.h" unsigned int msgMaxLength ; char login[LOGIN_MAX_LENGTH] ;

char password[PASSWORD_MAX_LENGTH] ; unsigned int isRoot = 0 ; void main (unsigned int argc, char ** argv) { /* nothing is establish to shutdown the server properly - we love Ctrl+C */ int serverSocketID ; if (argc != 2 && argc != 3) fprintf (stderr, "Usage error.\n") ; is : server [message length] */

/* the correct usage

else if ((argc == 2) && (atoi(argv[1]) >= 1024) ){ msgMaxLength = 15 ; /* default value */ serverSocketID = establishSocket(atoi(argv[1])) ; /* using 'atoi()' to convert the string made of the port number into an integer */ listenMultipleConnections(serverSocketID) ; } else if ((argc == 3)&& (atoi(argv[1]) >= 1024) ) { msgMaxLength = atoi(argv[2]) ; /* not the default value */ serverSocketID = establishSocket(atoi(argv[1])) ; listenMultipleConnections(serverSocketID) ; } else fprintf(stderr, "Cannot connect to well known ports.\n"); }

operations.h #ifndef OPERATIONS__ #define OPERATIONS__ #define MAX_HOSTNAME_LENGTH 15 #define MSG_FLAG 0 #define LOGIN_MAX_LENGTH 15 #define PASSWORD_MAX_LENGTH 32 #define MSG_DIGEST_LENGTH 16 int establishSocket (unsigned int) ; int acceptConnection (int) ; void closeSocket (int) ; void listenMultipleConnections (int) ; unsigned int sendMsg (int, const char *, unsigned int) ; unsigned int receiveMsg (int, char *, unsigned int) ; int checkuserpwd(FILE *ptr,const char*,const char*); void clientWorkingLoop(int, int) ; unsigned int validateLogin(int) ; void sendMsgLength(int) ; #endif

/* —— OPERATIONS__ —— */

operations.c #include "global.h" extern char login[LOGIN_MAX_LENGTH] ;

extern char password[PASSWORD_MAX_LENGTH] ; extern unsigned int msgMaxLength ; int establishSocket (unsigned int portNumber) { binding */ char serverName[MAX_HOSTNAME_LENGTH] ; int serverSocketID ; struct sockaddr_in serverSocket ; struct hostent * serverInfo ;

/* socket creation and

gethostname(serverName, (MAX_HOSTNAME_LENGTH - 1)) ; /* getting my own name and address */ serverInfo = gethostbyname(serverName) ; if (serverInfo == NULL) { fprintf(stderr, "Error finding our adress.\n") ; }

exit(0);

serverSocket.sin_family = AF_INET ; serverSocket.sin_port = htons(portNumber) ; serverSocket.sin_addr.s_addr = INADDR_ANY; if ((serverSocketID = socket(AF_INET, SOCK_STREAM, 0)) < 0) { socket creation using TCP protocol */ fprintf(stderr, "Error creating the socket.\n") ; } 0) {

exit(0) ;

if (bind(serverSocketID, &serverSocket, sizeof(struct sockaddr_in)) < /* socket binding */ fprintf(stderr, "Error binding the socket.\n") ;

}

close(serverSocketID) ; exit(0) ;

listen(serverSocketID, 3) ; }

/*

/* 3 connections max. */

return(serverSocketID) ;

int acceptConnection (int serverSocketID) { struct sockaddr_in clientSocket ; unsigned int sizeofSocketAdress ; /* to accept a connection I need to store 'sizeof(struct sockaddr_in)' */ int clientSocketID ; sizeofSocketAdress = sizeof(struct sockaddr_in) ; if ((clientSocketID = accept(serverSocketID, &clientSocket, &sizeofSocketAdress)) < 0) { /* trying to accept the connection */ fprintf(stderr, "Error accepting a connection.\n") ; }

exit(0) ;

return clientSocketID ;

} void closeSocket (int serverSocketID) { the socket ID */ close(serverSocketID) ; }

/* simply closing the socket using

void listenMultipleConnections (int serverSocketID) { /* waiting for connections and make a 'fork()' for each of them */ int clientSocketID ; while (1) { /* main loop - waiting for connection */ clientSocketID = acceptConnection(serverSocketID) ; switch(fork()) { /* here is the famous 'fork()' */ case -1: fprintf(stderr, "Error making a child processus.\n") ; closeSocket(serverSocketID) ; closeSocket(clientSocketID) ; exit(0) ; useful but... */

break ;

/* the 'break' is kinf of not

case 0: /* child processus: here is the real work with the client */ clientWorkingLoop(serverSocketID, clientSocketID) ; exit(0) ; break ; default: /* father processus: continue waiting for other connections */ closeSocket(clientSocketID) ;

}

}

}

continue;

unsigned int sendMsg (int serverSocketID, const char * msg, unsigned int msgLength) { /* simply (?!) sending a message to the client socket */ return send(serverSocketID, msg, msgLength, MSG_FLAG) ; /* returning the number of characters actually sent */ } unsigned int receiveMsg (int serverSocketID, char * msg, unsigned int msgMaxLength) { /* simply (?!) receive a message from the client socket */ return recv(serverSocketID, msg, msgMaxLength, MSG_FLAG) ; /* returning the number of characters actually received */ } void clientWorkingLoop(int serverSocketID, int clientSocketID) { if (validateLogin(clientSocketID)) { sendMsgLength(clientSocketID) ; waitingCommandLoop(clientSocketID) ;

}

}

unsigned int validateLogin(int serverSocketID) { /* test if the login and password send by the client are correct */ char tmpLogin[LOGIN_MAX_LENGTH] ; char tmpPassword[40] ; char serverValidation[7] ; /* "OK" or "NOT OK" */ char passwordFileName[] = "logins" ; /* no possibility to specify the path of the file outside the program :( */ FILE * ptrPasswordFile ; char tmpFileLogin[LOGIN_MAX_LENGTH] ; char tmpFilePassword[PASSWORD_MAX_LENGTH] ; char tmpFileLine[256] ; unsigned int flag = 0 ; int found; receiveMsg(serverSocketID, tmpLogin, LOGIN_MAX_LENGTH) ; receiving login and password */ receiveMsg(serverSocketID, tmpPassword, PASSWORD_MAX_LENGTH) ;

/*

/* searching for the login and password sent in the login file */ ptrPasswordFile = fopen(passwordFileName, "rb") ; found = checkuserpwd(ptrPasswordFile,tmpLogin,tmpPassword) ; if (found>0) strcpy(serverValidation, "NOT OK") ; else if (found==-1) { flag=1; strcpy(serverValidation, "OK") ; } strcpy(login, tmpLogin) ; strcpy(password, tmpPassword) ; /* ——————————————————————————————————————————————————————————— */ if (sendMsg(serverSocketID, serverValidation, 7) < 0) { /* sending validation */ fprintf(stderr,"Error sending validation to the client.\n") ; exit(0) ; } else if (strcmp(serverValidation, "OK") == 0) fprintf(stdout, "Connection established with %s.\n", login) ; }

return flag ;

void sendMsgLength(int serverSocketID) { if (sendMsg(serverSocketID, &msgMaxLength, sizeof(int)) < 0) { fprintf(stderr,"Error sending message length.\n") ;

}

}

exit(0) ;

int checkuserpwd(FILE *fd,const char *user,const char *pwd) { char buff[200]; char *str; int retry;

{

while(fgets(buff, 200, fd)) str=strtok(buff,"\t" ); //at this point... str contains user name! //need to check username against one given! if (strcmp(user,str)==0) { // Now checking password,given that username is correct str = strtok(NULL, ":"); if (strcmp(str,pwd)==0) { //UserName and Password Correct!! //Successful Login!! retry=-1; break; } else

{ //"Unsuccessful Login..username corect but password is wrong retry++; } } else against forthcoming

}

retry++;

//while loop

fclose(fd); return retry; }

commands.h #ifndef COMMANDS__ #define COMMANDS__ #define PASSWORD_MAX_LENGTH 32 #define MSG_DIGEST_LENGTH 16 void waitingCommandLoop(int) ; void listdirfullCommand(int) ;

//username wrong..continue loop and check //username and password in file.

void void void void void void void

listdirCommand(int) ; addfileCommand(int) ; removefileCommand(int) ; listfileCommand(int) ; adduserCommand(int) ; removeuserCommand(int) ; changepassCommand(int) ;

#endif

/* —— COMMANDS__ —— */

commands.c #include "global.h" extern char login[LOGIN_MAX_LENGTH] ; extern char password[PASSWORD_MAX_LENGTH] ; extern unsigned int msgMaxLength ; void waitingCommandLoop(int serverSocketID) { char commandBuffer[12] ; caracters long */

/* the larger command is 11

while (strcmp(commandBuffer, "EXIT") != 0) { if (receiveMsg(serverSocketID, commandBuffer, 11) > 0) { fprintf(stdout, "Received command from %s: %s.\n", login, commandBuffer) ; if (strcmp(commandBuffer, "LISTDIR") == 0) listdirCommand(serverSocketID) ; else if (strcmp(commandBuffer, "LISTDIRFULL") == 0) listdirfullCommand(serverSocketID) ; else if (strcmp(commandBuffer, "ADDFILE") == 0) addfileCommand(serverSocketID) ; else if (strcmp(commandBuffer, "REMOVEFILE") == 0) removefileCommand(serverSocketID) ; else if (strcmp(commandBuffer, "LISTFILE") == 0) listfileCommand(serverSocketID) ; else if (strcmp(commandBuffer, "ADDUSER") == 0) adduserCommand(serverSocketID) ; else if (strcmp(commandBuffer, "REMOVEUSER") == 0) removeuserCommand(serverSocketID) ; else if (strcmp(commandBuffer, "CHANGEPASS") == 0) changepassCommand(serverSocketID) ; fprintf(stdout, "Received command from %s: %s: OK.\n", login, commandBuffer) ; } } }

fprintf(stdout, "Connection with %s lost.\n", login) ;

void listdirCommand(int serverSocketID) { directory are listed in the 'index' file */ char indexFileName[16] ; FILE * ptrIndexFile ; char tmpFileLine[256] ; char * tmpNameOfFile ;

/* all the files in the

strcpy(indexFileName, login) ; strcat(indexFileName, "/index") ; ptrIndexFile = fopen(indexFileName, "rb") ; while (fgets(tmpFileLine, 256, ptrIndexFile) != NULL) { tmpNameOfFile = strtok(tmpFileLine, "\t") ; 1)) ;

}

sendMsg(serverSocketID, tmpNameOfFile, (strlen(tmpNameOfFile) + /* sending the file name */

sendMsg(serverSocketID, "ENDOFCOMMAND", 13) ; }

/* finished! */

fclose(ptrIndexFile) ;

void listdirfullCommand(int serverSocketID) { char indexFileName[16] ; FILE * ptrIndexFile ; char tmpFileLine[256] ; char * tmpNameOfFile ; char * tmpTimestampOfFile ; strcpy(indexFileName, login) ; strcat(indexFileName, "/index") ; ptrIndexFile = fopen(indexFileName, "rb") ; while (fgets(tmpFileLine, 256, ptrIndexFile) != NULL) { tmpNameOfFile = strtok (tmpFileLine, "\t") ; tmpTimestampOfFile = strtok (NULL, "\t") ; sendMsg(serverSocketID, tmpNameOfFile, 16) ; sending the file name */ sendMsg(serverSocketID, tmpTimestampOfFile, 12) ; sending directly the timestamp - the client has to format it */ } sendMsg(serverSocketID, "ENDOFCOMMAND", 13) ; }

void addfileCommand(int serverSocketID) { char tmpFileName[16] ; char tmpFileLine[256] ; char indexFileName[16] ; FILE * ptrIndexFile ; unsigned long tmpFileTimestamp ; char tmpFileBuffer[256] ; FILE * ptrReceivedFile ; char receivedFileName[16] ; receiveMsg(serverSocketID, tmpFileName, 16) ; /* —— creating the file in the index —— */ strcpy(indexFileName, login) ; strcat(indexFileName, "/index") ;

tmpFileTimestamp = time(NULL) ;

/*

/* finished! */

fclose(ptrIndexFile) ;

ptrIndexFile = fopen(indexFileName, "ab") ;

/*

sprintf(tmpFileLine, "%s\t%i\n", tmpFileName, tmpFileTimestamp) ; fputs(tmpFileLine, ptrIndexFile) ; fclose(ptrIndexFile) ; sendMsg(serverSocketID, &tmpFileTimestamp, sizeof(long)) ; /* sending the encryption key */ /* ———————————————————————————————————— */ /* —— receiving the encrypted file —— */ strcpy(receivedFileName, login) ; strcat(receivedFileName, "/") ; strcat(receivedFileName, tmpFileName) ; ptrReceivedFile = fopen(receivedFileName, "wb") ; while (strcmp((tmpFileBuffer + (strlen(tmpFileBuffer) - 9)), "ENDOFFILE") != 0) { receiveMsg(serverSocketID, tmpFileBuffer, msgMaxLength) ; receiving the encrypted buffer */

/*

if (strcmp((tmpFileBuffer + (strlen(tmpFileBuffer) - 9)), "ENDOFFILE") != 0) fwrite(tmpFileBuffer, 1, msgMaxLength, ptrReceivedFile) ; /* putting it in our file */ else fwrite(tmpFileBuffer, 1, (strlen(tmpFileBuffer) - 9), ptrReceivedFile) ; } fclose(ptrReceivedFile) ; }

/* —————————————————————————————————— */

void removefileCommand(int serverSocketID) { /* the function used to remove a file is 'unlink()' */ char tmpFileName[16] ; /* name of the file to delete */ char indexFileName[16] ; char removingFileName[16] ; char tmpFileLine[256] ; char tmpCopyFileLine[256] ; FILE * indexFilePtr ; char * tmpNameOfFile ; /* name of the curent file in the loop where looking for the file in the 'index' file */ unsigned int flag = 0 ; FILE * index2FilePtr ; char index2FileName[16] ; receiveMsg(serverSocketID, tmpFileName, 16) ; file name */

/* receiving the

/* first, checking if the file exist in the 'index' */ strcpy(indexFileName, login) ; strcat(indexFileName, "/index") ; indexFilePtr = fopen(indexFileName, "rb") ; while (fgets(tmpFileLine, 256, indexFilePtr) != NULL) {

tmpNameOfFile = strtok (tmpFileLine, "\t") ;

}

if (strcmp(tmpNameOfFile, tmpFileName) == 0) flag = 1 ;

if (flag != 1) { sendMsg(serverSocketID, "NOTEXIST", 13) ; }

return ;

fclose(indexFilePtr) ; /* ———————————————————————————————————————————————— */ /* deleting the file from the index file */ strcpy(index2FileName, login) ; strcat(index2FileName, "/index2") ; /* we can't have a buffer for the entire file, so we copy 'index' into another 'index' */ indexFilePtr = fopen(indexFileName, "rb") ; index2FilePtr = fopen(index2FileName, "wb") ; while (fgets(tmpFileLine, 256, indexFilePtr) != NULL) { strcpy(tmpCopyFileLine, tmpFileLine) ; tmpNameOfFile = strtok (tmpFileLine, "\t") ;

}

if (strcmp(tmpNameOfFile, tmpFileName) != 0) fputs(tmpCopyFileLine, indexFilePtr) ;

fclose(indexFilePtr) ; fclose(index2FilePtr) ;

/* closing both files */

rename(index2FileName, indexFileName) ;

/* who saw the trick! */

/* ————————————————————————————————————— */ /* finaly, deleting the real file from the disk */ strcpy(removingFileName, login) ; strcat(removingFileName, "/") ; strcat(removingFileName, tmpFileName) ; unlink(removingFileName) ; /* in fact, the only simple thing to do... is to delete this *^@¨#& file! :) */ /* ———————————————————————————————————————————— */ sendMsg(serverSocketID, "ENDOFCOMMAND", 13) ; /* sending the confirmation */ } void listfileCommand(int serverSocketID) { char tmpFileName[16] ; char indexFileName[16] ; char removingFileName[16] ; char tmpFileLine[256] ; FILE * indexFilePtr ; char * tmpNameOfFile ; unsigned int flag = 0 ;

unsigned int tmpFileTimestamp ; char * tmpStrFileTimestamp ; char tmpFindingString[256] ; FILE * ptrSentFile ; char sentFileName[16] ; unsigned int readCharactersNb ; memset(tmpFileLine, '\0', 256) ;

/* just for security */

receiveMsg(serverSocketID, tmpFileName, 16) ; /* first, checking if the file exist in the 'index' */ strcpy(indexFileName, login) ; strcat(indexFileName, "/index") ; indexFilePtr = fopen(indexFileName, "rb") ; while (fgets(tmpFileLine, 256, indexFilePtr) != NULL) { tmpNameOfFile = strtok(tmpFileLine, "\t") ; if (strcmp(tmpNameOfFile, tmpFileName) == 0) { flag = 1 ; tmpStrFileTimestamp = strtok(NULL, "\n") ; tmpFileTimestamp = atol(tmpStrFileTimestamp) ; ;

sendMsg(serverSocketID, &tmpFileTimestamp, sizeof(long)) /* sending the encryption key */ } } if (flag != 1) { sendMsg(serverSocketID, "NOTEXIST", 9) ; }

return ;

fclose(indexFilePtr) ; /* ———————————————————————————————————————————————— */ /* —— read the file — send buffers —— */ strcpy(sentFileName, login) ; /* we could have done: sprintf(sentFileName, "%s/%s", login, tmpFileName) ; */ strcat(sentFileName, "/") ; strcat(sentFileName, tmpFileName) ; ptrSentFile = fopen(sentFileName, "rb") ; while ((readCharactersNb = fread(tmpFileLine, 1, msgMaxLength, ptrSentFile)) > 0) { sendMsg(serverSocketID, tmpFileLine, msgMaxLength) ; memset(tmpFileLine, '\0', 256) ; } sendMsg(serverSocketID, "ENDOFFILE", msgMaxLength) ; /* —————————————————————————————————— */ fclose(ptrSentFile) ; }

void adduserCommand(int serverSocketID) { char tmpUserName[16] ; char tmpPassword[40] ; char tmpFileLine[256] ; /* ok, (16 + 1 + 16 + 1) does not make 256 but... */ FILE * ptrLoginFile ; char loginFileName[] = "logins" ; FILE * tmpUserIndexFile ; char tmpUserIndexFileName[16] ; receiveMsg(serverSocketID, tmpUserName, 16) ; receiveMsg(serverSocketID, tmpPassword, 33) ; sprintf(tmpFileLine, "%s\t%s\n", tmpUserName, tmpPassword) ; don't forget the '\n' at the end of the line */

/*

ptrLoginFile = fopen(loginFileName, "ab") ; fputs(tmpFileLine, ptrLoginFile) ; fclose(ptrLoginFile) ; mkdir(tmpUserName, 755) ; directory - he will be pleased! */

/* creation of the new user

strcpy(tmpUserIndexFileName, tmpUserName) ; strcat(tmpUserIndexFileName, "/index") ; tmpUserIndexFile = fopen(tmpUserIndexFileName, "wb") ; just to create the file */ fclose(tmpUserIndexFile) ; }

sendMsg(serverSocketID, "ENDOFCOMMAND", 13) ;

/*

/* finished! */

void removeuserCommand(int serverSocketID) { char tmpUserName[16] ; char userFileName[] = "logins" ; char tmpFileLine[256] ; char tmpCopyFileLine[256] ; FILE * userFilePtr ; char * tmpNameOfUser ; unsigned int flag = 0 ; FILE * user2FilePtr ; char user2FileName[] = "logins2" ; DIR * directoryInfo ; for this function */ struct dirent * fileInfo ; char pathFileInfo[256] ;

/* starting to have a lot of variables

receiveMsg(serverSocketID, tmpUserName, 16) ; user name */

/* receiving the

/* —— first, checking if the user exist in the 'index' —— */ userFilePtr = fopen(userFileName, "rb") ; while (fgets(tmpFileLine, 256, userFilePtr) != NULL) {

tmpNameOfUser = strtok (tmpFileLine, "\t") ;

}

if (strcmp(tmpNameOfUser, tmpUserName) == 0) flag = 1 ;

if (flag != 1) { sendMsg(serverSocketID, "NOTEXIST", 9) ; }

return ;

fclose(userFilePtr) ; /* —————————————————————————————————————————————————————— */ /* —— now we delete the user in the index file —— */ userFilePtr = fopen(userFileName, "rb") ; user2FilePtr = fopen(user2FileName, "wb") ; while (fgets(tmpFileLine, 256, userFilePtr) != NULL) { strcpy(tmpCopyFileLine, tmpFileLine) ; tmpNameOfUser = strtok (tmpFileLine, "\t") ;

}

if (strcmp(tmpNameOfUser, tmpUserName) != 0) fputs(tmpCopyFileLine, user2FilePtr) ;

fclose(userFilePtr) ; fclose(user2FilePtr) ;

/* closing both files */

rename(user2FileName, userFileName) ; /* —————————————————————————————————————————————— */ /* —— new things: remove the user directory —— */ directoryInfo = opendir(tmpUserName) ; while((fileInfo = readdir(directoryInfo)) != NULL) { if ((strcmp(fileInfo->d_name, ".") != 0) && (strcmp(fileInfo>d_name, "..") != 0)) { strcpy(pathFileInfo, tmpUserName) ; strcat(pathFileInfo, "/") ; strcat(pathFileInfo, fileInfo->d_name) ; unlink(pathFileInfo) ; he didn't like his files */ } }

/* deleting all files — hope

closedir(directoryInfo) ; rmdir(tmpUserName) ; so we can delete it */

/* normally the directory is now empty

/* ——————————————————————————————————————————— */ sendMsg(serverSocketID, "ENDOFCOMMAND", 13) ; confirmation */ }

/* sending the

void changepassCommand(int serverSocketID) { char tmpUserName[16] ; char tmpNewPassword[34] ; char userFileName[] = "logins" ; char tmpFileLine[256] ; char tmpCopyFileLine[256] ; FILE * userFilePtr ; char * tmpNameOfUser ; unsigned int flag = 0 ; FILE * user2FilePtr ; /* yes, we are using the same trick as in 'removefileCommand()', we'll write a new user file */ char user2FileName[] = "logins2" ; receiveMsg(serverSocketID, tmpUserName, 16) ; user name */ receiveMsg(serverSocketID, tmpNewPassword,34) ; new password */

/* receiving the /* receiving the

/* —— first, checking if the user exist in the 'index' —— */ userFilePtr = fopen(userFileName, "rb") ; while (fgets(tmpFileLine, 256, userFilePtr) != NULL) { tmpNameOfUser = strtok (tmpFileLine, "\t") ;

}

if (strcmp(tmpNameOfUser, tmpUserName) == 0) flag = 1 ;

if (flag != 1) { sendMsg(serverSocketID, "NOTEXIST", 9) ; }

return ;

fclose(userFilePtr) ; /* —————————————————————————————————————————————————————— */ /* —— now we can change the password — great isn't it? —— */ userFilePtr = fopen(userFileName, "rb") ; user2FilePtr = fopen(user2FileName, "wb") ; while (fgets(tmpFileLine, 256, userFilePtr) != NULL) { strcpy(tmpCopyFileLine, tmpFileLine) ; tmpNameOfUser = strtok (tmpFileLine, "\t") ; if (strcmp(tmpNameOfUser, tmpUserName) != 0) fputs(tmpCopyFileLine, user2FilePtr) ; else { /* putting the new password in the file */ strcpy(tmpFileLine, tmpUserName) ; strcat(tmpFileLine, "\t") ; strcat(tmpFileLine, tmpNewPassword) ; strcat(tmpFileLine, "\n") ;

}

}

fputs(tmpFileLine, user2FilePtr) ;

fclose(userFilePtr) ; fclose(user2FilePtr) ;

/* closing both files */

rename(user2FileName, userFileName) ; /* ————————————————————————————————————— */ sendMsg(serverSocketID, "ENDOFCOMMAND", 13) ; confirmation */ }

/* sending the