Browse Source

ldap authentification, invisible password typing, bannlist

Kajetan Johannes Hammerle 5 years ago
parent
commit
f436779adc
11 changed files with 377 additions and 6 deletions
  1. 73 0
      Banns.c
  2. 24 0
      Banns.h
  3. 22 1
      ClientMain.c
  4. 152 0
      LDAP.c
  5. 7 0
      LDAP.h
  6. 3 3
      Makefile
  7. 65 0
      Server.c
  8. 10 0
      Server.h
  9. 16 2
      ServerMain.c
  10. 5 0
      mails/if17b012/if17b012/0
  11. BIN
      mails/if17b012/mailcounter

+ 73 - 0
Banns.c

@@ -0,0 +1,73 @@
+#include "Banns.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <time.h>
+
+BannList* bannsNew()
+{
+    BannList* list = malloc(sizeof(BannList));
+    list->root = NULL;
+    return list;
+}
+
+void bannsRemove(BannList* bl)
+{
+    Bann* b = bl->root;
+    while(b != NULL)
+    {
+        Bann* next = b->next;
+        free(b);
+        b = next;
+    }
+    bl->root = NULL;
+    free(bl);
+}
+
+void bannsAdd(BannList* bl, int ip)
+{
+    Bann* b = malloc(sizeof(Bann));
+    b->ip = ip;
+    time(&b->timeStamp);
+    b->timeStamp += 120; // two minutes
+    b->next = bl->root;
+    bl->root = b;
+}
+
+int bannsIsBanned(BannList* bl, int ip)
+{
+    time_t t;
+    time(&t);
+    
+    Bann* prev = NULL;
+    Bann* b = bl->root;
+    
+    while(b != NULL)
+    {
+        if(b->ip == ip)
+        {
+            if(t < b->timeStamp)
+            {
+                return 1;
+            }
+            else
+            {
+                if(prev == NULL)
+                {
+                    Bann* deleteMe = bl->root;
+                    bl->root = bl->root->next;
+                    free(deleteMe);
+                }
+                else
+                {
+                    prev->next = b->next;
+                    free(b);
+                }
+                return 0;
+            }
+        }
+        
+        prev = b;
+        b = b->next;
+    }
+    return 0;
+}

+ 24 - 0
Banns.h

@@ -0,0 +1,24 @@
+#ifndef BANNS_H
+#define BANNS_H
+
+#include <time.h>
+
+typedef struct Bann
+{
+    int ip;
+    time_t timeStamp;
+    struct Bann* next;
+} Bann;
+
+typedef struct BannList
+{
+    Bann* root;
+} BannList;
+
+BannList* bannsNew();
+void bannsRemove(BannList* bl);
+void bannsAdd(BannList* bl, int ip);
+int bannsIsBanned(BannList* bl, int ip);
+
+#endif
+

+ 22 - 1
ClientMain.c

@@ -1,3 +1,4 @@
+#define	_POSIX_C_SOURCE 1
 #include <stdio.h>
 #include <unistd.h>
 #include <stdlib.h>
@@ -5,6 +6,7 @@
 #include <string.h>
 #include "Client.h"
 #include "String.h"
+#include <termios.h>
 
 Client client;
 
@@ -14,6 +16,21 @@ void interruptHandler(int signal)
     exit(EXIT_SUCCESS);
 }
 
+void toggleTerminalPrinting()
+{
+    struct termios old, new;
+    if(tcgetattr(fileno(stdin), &old) != 0)
+    {
+        return;
+    }
+    new = old;
+    new.c_lflag ^= ECHO;
+    if(tcsetattr(fileno(stdin), TCSAFLUSH, &new) != 0)
+    {
+        return;
+    }
+}
+
 void writeMessageNumber(Stream* out)
 {
     String number;
@@ -175,17 +192,21 @@ void waitForData()
             printf("Type a password: ");
             String password;
             stringInit(&password);
+            toggleTerminalPrinting();
             stringRead(&password);
+            toggleTerminalPrinting();
             l = stringGetLength(&password);
             while(l == 0)
             {
                 printf("Please type a valid password: ");
+                toggleTerminalPrinting();
                 stringRead(&password);
+                toggleTerminalPrinting();
                 l = stringGetLength(&password);
             }
             streamWriteChars(&out, password.data);
             streamWriteChar(&out, '\n');
-            stringRemove(&sender);
+            stringRemove(&password);
             
             // send and clear stream
             clientSendData(&client, &out);

+ 152 - 0
LDAP.c

@@ -0,0 +1,152 @@
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ldap.h>
+
+#define LDAP_URI "ldap://ldap.technikum-wien.at:389"
+#define SEARCHBASE "dc=technikum-wien,dc=at"
+#define SCOPE LDAP_SCOPE_SUBTREE
+#define FILTER "(uid=if17b*)"
+
+static int ldapTryLoginIntern(char* user, char* password)
+{
+    LDAP *ld; // LDAP resource handle
+
+    BerValue *servercredp;
+    BerValue cred;
+    cred.bv_val = password;
+    cred.bv_len = strlen(password);
+    int rc = 0;
+
+    int ldapversion = LDAP_VERSION3;
+
+    /* setup LDAP connection */
+    if(ldap_initialize(&ld, LDAP_URI) != LDAP_SUCCESS)
+    {
+        fprintf(stderr, "ldap_init failed");
+        return 0;
+    }
+
+    if((rc = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &ldapversion)) != LDAP_SUCCESS)
+    {
+        fprintf(stderr, "ldap_set_option(PROTOCOL_VERSION): %s\n", ldap_err2string(rc));
+        ldap_unbind_ext_s(ld, NULL, NULL);
+        return 0;
+    }
+
+    if((rc = ldap_start_tls_s(ld, NULL, NULL)) != LDAP_SUCCESS)
+    {
+        fprintf(stderr, "ldap_start_tls_s(): %s\n", ldap_err2string(rc));
+        ldap_unbind_ext_s(ld, NULL, NULL);
+        return 0;
+    }
+
+    rc = ldap_sasl_bind_s(ld, user, LDAP_SASL_SIMPLE, &cred, NULL, NULL, &servercredp);
+
+    if(rc != LDAP_SUCCESS)
+    {
+        return 0;
+    }
+    ldap_unbind_ext_s(ld, NULL, NULL);
+    return 1;
+}
+
+int ldapTryLogin(char* user, char* password)
+{
+    LDAP *ld; // LDAP resource handle
+    LDAPMessage *result, *e; // LDAP result handle
+    BerElement *ber; // array of attributes
+    char *attribute;
+    BerValue **vals;
+
+    BerValue *servercredp;
+    BerValue cred;
+    cred.bv_val = "";
+    cred.bv_len = 0;
+    int i, rc = 0;
+
+    const char *attribs[] = {"uid", "cn", NULL}; /* attribute array for search */
+
+    int ldapversion = LDAP_VERSION3;
+
+    /* setup LDAP connection */
+    if(ldap_initialize(&ld, LDAP_URI) != LDAP_SUCCESS)
+    {
+        fprintf(stderr, "ldap_init failed");
+        return 0;
+    }
+
+    if((rc = ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &ldapversion)) != LDAP_SUCCESS)
+    {
+        fprintf(stderr, "ldap_set_option(PROTOCOL_VERSION): %s\n", ldap_err2string(rc));
+        ldap_unbind_ext_s(ld, NULL, NULL);
+        return 0;
+    }
+
+    if((rc = ldap_start_tls_s(ld, NULL, NULL)) != LDAP_SUCCESS)
+    {
+        fprintf(stderr, "ldap_start_tls_s(): %s\n", ldap_err2string(rc));
+        ldap_unbind_ext_s(ld, NULL, NULL);
+        return 0;
+    }
+
+    // anonymous bind
+    rc = ldap_sasl_bind_s(ld, "", LDAP_SASL_SIMPLE, &cred, NULL, NULL, &servercredp);
+
+    if(rc != LDAP_SUCCESS)
+    {
+        fprintf(stderr, "LDAP bind error: %s\n", ldap_err2string(rc));
+        ldap_unbind_ext_s(ld, NULL, NULL);
+        return 0;
+    }
+
+    /* perform ldap search */
+    rc = ldap_search_ext_s(ld, SEARCHBASE, SCOPE, FILTER, (char **) attribs, 0, NULL, NULL, NULL, 500, &result);
+
+    if(rc != LDAP_SUCCESS)
+    {
+        fprintf(stderr, "LDAP search error: %s\n", ldap_err2string(rc));
+        ldap_unbind_ext_s(ld, NULL, NULL);
+        return 0;
+    }
+
+    char buffer[1024];
+    buffer[0] = '\0';
+    for(e = ldap_first_entry(ld, result); e != NULL; e = ldap_next_entry(ld, e))
+    {
+        for(attribute = ldap_first_attribute(ld, e, &ber); attribute != NULL; attribute = ldap_next_attribute(ld, e, ber))
+        {
+            if((vals = ldap_get_values_len(ld, e, attribute)) != NULL)
+            {
+                for(i = 0; i < ldap_count_values_len(vals); i++)
+                {
+                    if(strcmp(attribute, "uid") == 0 && strcmp(vals[i]->bv_val, user) == 0)
+                    {
+                        strncpy(buffer, ldap_get_dn(ld, e), 1023);
+                    }
+                }
+                ldap_value_free_len(vals);
+            }
+            // free memory used to store the attribute
+            ldap_memfree(attribute);
+        }
+        // free memory used to store the value structure
+        if(ber != NULL)
+        {
+            ber_free(ber, 0);
+        }
+    }
+    
+    /* free memory used for result */
+    ldap_msgfree(result);
+    printf("LDAP search suceeded\n");
+    ldap_unbind_ext_s(ld, NULL, NULL);
+    
+    if(strlen(buffer) == 0)
+    {
+        return 0;
+    }
+    return ldapTryLoginIntern(buffer, password);
+}
+
+

+ 7 - 0
LDAP.h

@@ -0,0 +1,7 @@
+#ifndef LDAP_H
+#define LDAP_H
+
+int ldapTryLogin(char* user, char* password);
+
+#endif /* LDAP_H */
+

+ 3 - 3
Makefile

@@ -1,5 +1,5 @@
 FLAGS = -std=c11 -Wall
-SERVER_LINKER = -lpthread
+SERVER_LINKER = -lpthread -lldap -llber
 CLIENT_LINKER = -lpthread
 
 all: server client
@@ -8,8 +8,8 @@ run_all: all
 	./server
 	./client 127.0.0.1
 
-server: ServerMain.c Server.c Server.h Stream.c Stream.h SocketUtils.c SocketUtils.h String.c String.h
-	gcc $(FLAGS) -o $@ ServerMain.c Server.c Stream.c SocketUtils.c String.c $(SERVER_LINKER)
+server: ServerMain.c Server.c Server.h Stream.c Stream.h SocketUtils.c SocketUtils.h String.c String.h Banns.c Banns.h LDAP.h LDAP.c
+	gcc $(FLAGS) -o $@ ServerMain.c Server.c Stream.c SocketUtils.c String.c Banns.c LDAP.c $(SERVER_LINKER)
 
 run_server: server
 	./server

+ 65 - 0
Server.c

@@ -16,11 +16,14 @@ void serverInitDefaults(Server* s)
     s->port = -1;
     s->threads = NULL;
     s->clientSockets = NULL;
+    s->loginTries = NULL;
     s->clientUser = NULL;
     s->connectSocket = -1;
     
     s->handler = NULL;
     
+    s->banns = NULL;
+    
     s->directory = NULL;
 }
 
@@ -40,6 +43,8 @@ int serverInit(Server* s, int maxClients, short port, char* directory)
     // initialize storage for clients
     s->threads = malloc(sizeof(pthread_t) * maxClients);
     s->clientSockets = malloc(sizeof(int) * maxClients);
+    s->loginTries = malloc(sizeof(int) * maxClients);
+    s->ips = malloc(sizeof(int) * maxClients);
     s->clientUser = malloc(sizeof(char*) * maxClients);
     
     for(int i = 0; i < maxClients; i++)
@@ -47,6 +52,8 @@ int serverInit(Server* s, int maxClients, short port, char* directory)
         s->threads[i] = -1;
         s->clientSockets[i] = -1;
         s->clientUser[i] = NULL;
+        s->loginTries[i] = 0;
+        s->ips[i] = 0;
     }
     
     // create the socket for clients to connect
@@ -91,6 +98,8 @@ int serverInit(Server* s, int maxClients, short port, char* directory)
         return -1;
     }
     
+    s->banns = bannsNew();
+    
     return 0;
 }
 
@@ -148,6 +157,18 @@ void serverRemove(Server* s)
         s->clientUser = NULL;
     }
     
+    if(s->loginTries != NULL)
+    {
+        free(s->loginTries);
+        s->loginTries = NULL;
+    }
+    
+    if(s->ips != NULL)
+    {
+        free(s->ips);
+        s->ips = NULL;
+    }
+    
     s->maxClients = -1;
     
     if(s->connectSocket != -1)
@@ -164,6 +185,12 @@ void serverRemove(Server* s)
     }
     
     s->handler = NULL;
+    
+    if(s->banns != NULL)
+    {
+        bannsRemove(s->banns);
+        s->banns = NULL;
+    }
 }
 
 static void* clientHandler(void* data)
@@ -208,6 +235,7 @@ static void* clientHandler(void* data)
         printf("%d closed\n", id);
     }
     
+    s->loginTries[id] = 0;
     serverFreeUser(s, id);
     s->clientSockets[id] = -1;
     return NULL;
@@ -234,11 +262,20 @@ void serverWaitForConnection(Server* s)
         {
             printf("Client connected from %s:%d...\n", inet_ntoa(clientSocketData.sin_addr), (int) ntohs(clientSocketData.sin_port));
             
+            if(bannsIsBanned(s->banns, clientSocketData.sin_addr.s_addr))
+            {
+                close(clientSocket);
+                printf("Banned user tried joining\n");
+                continue;
+            }
+            
             int i = 0;
             while(1)
             {
                 if(s->clientSockets[i] == -1)
                 {
+                    s->ips[i] = clientSocketData.sin_addr.s_addr;
+                    
                     if(s->threads[i] != -1)
                     {
                         pthread_cancel(s->threads[i]);
@@ -341,4 +378,32 @@ void serverFreeUser(Server* s, int clientId)
         free(s->clientUser[clientId]);
         s->clientUser[clientId] = NULL;
     }
+}
+
+int serverRaiseLoginFails(Server* s, int clientId)
+{
+    if(clientId < 0 || clientId >= s->maxClients)
+    {
+        return 0;
+    }
+    s->loginTries[clientId]++;
+    return s->loginTries[clientId] >= 3;
+}
+
+void serverResetLoginFails(Server* s, int clientId)
+{
+    if(clientId < 0 || clientId >= s->maxClients)
+    {
+        return;
+    }
+    s->loginTries[clientId] = 0;
+}
+
+void serverBann(Server* s, int clientId)
+{
+    if(clientId < 0 || clientId >= s->maxClients)
+    {
+        return;
+    }
+    bannsAdd(s->banns, s->ips[clientId]);
 }

+ 10 - 0
Server.h

@@ -3,6 +3,7 @@
 
 #include <pthread.h>
 #include "Stream.h"
+#include "Banns.h"
 
 typedef struct Server
 {
@@ -11,8 +12,12 @@ typedef struct Server
     pthread_t* threads;
     int* clientSockets;
     char** clientUser;
+    int* loginTries;
+    int* ips;
     int connectSocket;
     
+    BannList* banns;
+    
     ServerStreamFunction handler;
     
     char* directory;
@@ -37,5 +42,10 @@ int serverSetUser(Server* s, int clientId, char* name);
 char* serverGetUser(Server* s, int clientId);
 void serverFreeUser(Server* s, int clientId);
 
+int serverRaiseLoginFails(Server* s, int clientId);
+void serverResetLoginFails(Server* s, int clientId);
+
+void serverBann(Server* s, int clientId);
+
 #endif
 

+ 16 - 2
ServerMain.c

@@ -13,6 +13,7 @@
 #include <assert.h>
 #include "Server.h"
 #include "String.h"
+#include "LDAP.h"
 #include <string.h>
 
 int getMailCounter()
@@ -636,10 +637,23 @@ int packageLogin(int client, int clientSocket, Stream* in)
     stringInit(&password);
     stringReadStreamLine(&password, in);
     
-    printf("%s %s\n", user.data, password.data);
-    // insert LDAP check here
+    if(!ldapTryLogin(user.data, password.data))
+    {
+        stringRemove(&user);
+        stringRemove(&password);
+        
+        if(serverRaiseLoginFails(&server, client))
+        {
+            serverBann(&server, client);
+            return 1;
+        }
+        
+        packageSendFailAnswer(clientSocket);
+        return 0;
+    }
     
     stringRemove(&password);
+    serverResetLoginFails(&server, client);
     
     if(serverSetUser(&server, client, user.data))
     {

+ 5 - 0
mails/if17b012/if17b012/0

@@ -0,0 +1,5 @@
+if17b012
+if17b012
+Hallo
+Yes ldap works
+yeeess

BIN
mails/if17b012/mailcounter