LDAP Login, Makefile, Output Color

This commit is contained in:
Georg Reisinger 2020-10-27 18:19:21 +01:00
parent 7afb97993e
commit ddada8bb82
6 changed files with 683 additions and 365 deletions

BIN
client

Binary file not shown.

View File

@ -54,26 +54,68 @@ int main (int argc, char **argv) {
if (connect ( create_socket, (struct sockaddr *) &address, sizeof (address)) == 0)
{
printf ("Connection with server (%s) established\n", inet_ntoa (address.sin_addr));
printf ("\x1b[32mConnection with server (%s) established\n\x1b[0m", inet_ntoa (address.sin_addr));
size=recv(create_socket,buffer,BUF-1, 0);
if (size>0)
{
buffer[size]= '\0';
printf("%s",buffer);
printf("\x1b[36m%s\x1b[0m",buffer);
}
}
else
{
perror("Connect error - no server available");
perror("\x1b[31mConnect error - no server available\x1b[0m");
return EXIT_FAILURE;
}
bool login = false;
do {
//command vom user überprüfen
char command[6] = "";
printf ("\nEnter Command: \n");
fgets (command, 6, stdin);
char command[7] = "";
printf ("\n\x1b[35mEnter Command:\x1b[0m \n");
fgets (command, 7, stdin);
if (startsWith("login", command) == true && login == false)
{
char username[10] = "";
char pw[50] = "";
char bufferString[BUF] = "";
strcpy(bufferString, "login;");
//User Dateneingabe und daten einlesen
printf("\x1b[35m<Username max. 8 Zeichen>\x1b[0m\n");
fgets (username, 10, stdin);
printf("\x1b[35m<Passwort max. 50 Zeichen>\x1b[0m\n");
fgets (pw, 50, stdin);
strcat(bufferString, username);
strcat(bufferString, ";");
strcat(bufferString, pw);
remN(bufferString);
send(create_socket, bufferString, strlen (bufferString), 0);
//Response vom Server (OK oder ERR) empfangen und ausgeben
char readBuffer[BUF] = "";
read(create_socket , readBuffer, 1024);
printf("\n%s\n", readBuffer);
if (strncmp(readBuffer, "OK", 2) == 0)
{
login = true;
}
}else if (login == false && startsWith("quit", command) == true)
{
strcpy(buffer, "quit\n");
}else if (login == false)
{
printf("\x1b[33mBitte zuerst <login> eingeben. Erst danach können sie auf das Program zugreifen!\x1b[0m\n");
}
if(login == true){
//je nach command wird was audgeführt
if(startsWith("send", command) == true) {
@ -87,16 +129,16 @@ int main (int argc, char **argv) {
strcat(bufferString, "send");
//User Dateneingabe und daten einlesen
printf("<Sender max. 8 Zeichen>\n");
printf("\x1b[35m<Sender max. 8 Zeichen>\x1b[0m\n");
fgets (sender, 8, stdin);
printf("<Empfänger max. 8 Zeichen>\n");
printf("\x1b[35m<Empfänger max. 8 Zeichen>\x1b[0m\n");
fgets (empfaenger, 8, stdin);
printf("<Betreff max. 80 Zeichen>\n");
printf("\x1b[35m<Betreff max. 80 Zeichen>\x1b[0m\n");
fgets (betreff, 80, stdin);
printf("<Nachricht, beliebige Anzahl an Zeilen>\n");
printf("\x1b[35m<Nachricht, beliebige Anzahl an Zeilen>\x1b[0m\n");
fgets (nachricht, 80, stdin);
//Buffer formatieren
@ -114,7 +156,7 @@ int main (int argc, char **argv) {
//Response vom Server (OK oder ERR) empfangen und ausgeben
char readBuffer[BUF] = "";
int valread = read(create_socket , readBuffer, 1024);
read(create_socket , readBuffer, 1024);
printf("\n%s\n", readBuffer);
}
@ -125,9 +167,9 @@ int main (int argc, char **argv) {
char p[20] = "";
int counter = 0;
printf("<Username max. 8 Zeichen>\n");
printf("\x1b[35m<Username max. 8 Zeichen>\x1b[0m\n");
fgets (username, 8, stdin);
printf("<Posteingang oder Postausgang>\n");
printf("\x1b[35m<Posteingang oder Postausgang>\x1b[0m\n");
fgets (p, 20, stdin);
strcat(bufferString, ";");
@ -139,7 +181,7 @@ int main (int argc, char **argv) {
send(create_socket, bufferString, strlen (bufferString), 0);
char readBuffer[BUF] = "";
int valread = read(create_socket , readBuffer, 1024);
read(create_socket , readBuffer, 1024);
char delimiter[] = ";";
char *ptr;
@ -157,7 +199,7 @@ int main (int argc, char **argv) {
}
else if (counter == 0) {
printf("<Anzahl der Nachrichten für den User: %s>\n", ptr);
printf("\x1b[35m<Anzahl der Nachrichten für den User: %s>\x1b[0m\n", ptr);
}
else {
@ -179,11 +221,11 @@ int main (int argc, char **argv) {
char nid[80] = "";
char folder[20] = "";
printf("<Username max. 8 Zeichen>\n");
printf("\x1b[35m<Username max. 8 Zeichen>\x1b[0m\n");
fgets (username, 8, stdin);
printf("<posteingang oder postausgang>\n");
printf("\x1b[35m<posteingang oder postausgang>\x1b[0m\n");
fgets (folder, 20, stdin);
printf("<Nachrichten-Nummer>\n");
printf("\x1b[35m<Nachrichten-Nummer>\x1b[0m\n");
fgets (nid, 80, stdin);
strcat(bufferString, ";");
@ -201,7 +243,7 @@ int main (int argc, char **argv) {
//strcpy(buffer, "");
//buffer[size]= '\0';
char readBuffer[BUF] = "";
int valread = read(create_socket , readBuffer, 1000);
read(create_socket , readBuffer, 1000);
printf("\n%s\n", readBuffer );
}
@ -214,11 +256,11 @@ int main (int argc, char **argv) {
char bufferString[BUF] = "del";
char p[20] = "";
printf("<Username max. 8 Zeichen>\n");
printf("\x1b[35m<Username max. 8 Zeichen>\x1b[0m\n");
fgets (username, 8, stdin);
printf("<Posteingang oder Postausgang>\n");
printf("\x1b[35m<Posteingang oder Postausgang>\x1b[0m\n");
fgets (p, 20, stdin);
printf("<Nachrichten-Nummer>\n");
printf("\x1b[35m<Nachrichten-Nummer>\x1b[0m\n");
fgets (nachrichtennummer, 80, stdin);
strcat(bufferString, ";");
@ -232,7 +274,7 @@ int main (int argc, char **argv) {
send(create_socket, bufferString, strlen (bufferString), 0);
char readBuffer[BUF] = "";
int valread = read(create_socket , readBuffer, 1024);
read(create_socket , readBuffer, 1024);
printf("\n%s\n", readBuffer );
}
@ -244,6 +286,7 @@ int main (int argc, char **argv) {
else {
printf("DAS IST KEIN COMMAND!!!!!");
}
}

View File

@ -1,7 +1,8 @@
#Client und Server kompilieren
all: server.c client.c
gcc server.c -o server -lpthread
gcc client.c -o client -lpthread
gcc -Wall -o server server.c -lldap -llber -lpthread
gcc -Wall -o client client.c -lldap -llber -lpthread
#Kompilierten Client und Server löschen
clean: client server
@ -9,11 +10,11 @@ clean: client server
#Nur den Client kompilieren:
client: client.c
gcc client.c -o client -lpthread
gcc -Wall -o client client.c -lldap -llber -lpthread
#Nur den Server kompilieren:
server: server.c
gcc server.c -o server -lpthread
gcc -Wall -o server server.c -lldap -llber -lpthread
#Kompilierten Server löschen
cleanS: server

View File

@ -2,6 +2,7 @@
# Protokoll 🔧
```
LOGIN: login;username;passwort
SEND: send;sender;empänger;betreff;nachricht
LIST: list:username;postEinAusgang
READ: read;username;postEinAusgang;nid

BIN
server

Binary file not shown.

291
server.c
View File

@ -14,6 +14,9 @@
#include <dirent.h>
#include <time.h>
#include <pthread.h>
#include <ldap.h>
#include <termios.h>
#define MAXCHAR 1000
#define BUF 1024
@ -51,22 +54,298 @@ int countFiles(char path[]) {
return file_count;
}
int login_user(char username[8], char pw[50])
{
////////////////////////////////////////////////////////////////////////////
// LDAP config
// anonymous bind with user and pw empty
const char *ldapUri = "ldap://ldap.technikum-wien.at:389";
const int ldapVersion = LDAP_VERSION3;
// read username (bash: export ldapuser=<yourUsername>)
char ldapBindUser[256];
char rawLdapUser[128];
strcpy(rawLdapUser, username);
sprintf(ldapBindUser, "uid=%s,ou=people,dc=technikum-wien,dc=at", rawLdapUser);
printf("user set to: %s\n", ldapBindUser);
// read password (bash: export ldappw=<yourPW>)
char ldapBindPassword[256];
strcpy(ldapBindPassword, pw);
printf("pw taken over from commandline: %s\n", pw);
// search settings
const char *ldapSearchBaseDomainComponent = "dc=technikum-wien,dc=at";
const char *ldapSearchFilter = "(uid=if20b20*)";
ber_int_t ldapSearchScope = LDAP_SCOPE_SUBTREE;
const char *ldapSearchResultAttributes[] = {"uid", "cn", NULL};
// general
int rc = 0; // return code
////////////////////////////////////////////////////////////////////////////
// setup LDAP connection
// https://linux.die.net/man/3/ldap_initialize
LDAP *ldapHandle;
rc = ldap_initialize(&ldapHandle, ldapUri);
if (rc != LDAP_SUCCESS)
{
fprintf(stderr, "ldap_init failed\n");
return 0;
}
printf("connected to LDAP server %s\n", ldapUri);
////////////////////////////////////////////////////////////////////////////
// set verison options
// https://linux.die.net/man/3/ldap_set_option
rc = ldap_set_option(
ldapHandle,
LDAP_OPT_PROTOCOL_VERSION, // OPTION
&ldapVersion); // IN-Value
if (rc != LDAP_OPT_SUCCESS)
{
// https://www.openldap.org/software/man.cgi?query=ldap_err2string&sektion=3&apropos=0&manpath=OpenLDAP+2.4-Release
fprintf(stderr, "ldap_set_option(PROTOCOL_VERSION): %s\n", ldap_err2string(rc));
ldap_unbind_ext_s(ldapHandle, NULL, NULL);
return 0;
}
////////////////////////////////////////////////////////////////////////////
// start connection secure (initialize TLS)
// https://linux.die.net/man/3/ldap_start_tls_s
// int ldap_start_tls_s(LDAP *ld,
// LDAPControl **serverctrls,
// LDAPControl **clientctrls);
// https://linux.die.net/man/3/ldap
// https://docs.oracle.com/cd/E19957-01/817-6707/controls.html
// The LDAPv3, as documented in RFC 2251 - Lightweight Directory Access
// Protocol (v3) (http://www.faqs.org/rfcs/rfc2251.html), allows clients
// and servers to use controls as a mechanism for extending an LDAP
// operation. A control is a way to specify additional information as
// part of a request and a response. For example, a client can send a
// control to a server as part of a search request to indicate that the
// server should sort the search results before sending the results back
// to the client.
rc = ldap_start_tls_s(
ldapHandle,
NULL,
NULL);
if (rc != LDAP_SUCCESS)
{
fprintf(stderr, "ldap_start_tls_s(): %s\n", ldap_err2string(rc));
ldap_unbind_ext_s(ldapHandle, NULL, NULL);
return 0;
}
////////////////////////////////////////////////////////////////////////////
// bind credentials
// https://linux.die.net/man/3/lber-types
// SASL (Simple Authentication and Security Layer)
// https://linux.die.net/man/3/ldap_sasl_bind_s
// int ldap_sasl_bind_s(
// LDAP *ld,
// const char *dn,
// const char *mechanism,
// struct berval *cred,
// LDAPControl *sctrls[],
// LDAPControl *cctrls[],
// struct berval **servercredp);
BerValue bindCredentials;
bindCredentials.bv_val = (char *)ldapBindPassword;
bindCredentials.bv_len = strlen(ldapBindPassword);
BerValue *servercredp; // server's credentials
rc = ldap_sasl_bind_s(
ldapHandle,
ldapBindUser,
LDAP_SASL_SIMPLE,
&bindCredentials,
NULL,
NULL,
&servercredp);
if (rc != LDAP_SUCCESS)
{
fprintf(stderr, "LDAP bind error: %s\n", ldap_err2string(rc));
ldap_unbind_ext_s(ldapHandle, NULL, NULL);
return 0;
}
////////////////////////////////////////////////////////////////////////////
// perform ldap search
// https://linux.die.net/man/3/ldap_search_ext_s
// _s : synchronous
// int ldap_search_ext_s(
// LDAP *ld,
// char *base,
// int scope,
// char *filter,
// char *attrs[],
// int attrsonly,
// LDAPControl **serverctrls,
// LDAPControl **clientctrls,
// struct timeval *timeout,
// int sizelimit,
// LDAPMessage **res );
LDAPMessage *searchResult;
rc = ldap_search_ext_s(
ldapHandle,
ldapSearchBaseDomainComponent,
ldapSearchScope,
ldapSearchFilter,
(char **)ldapSearchResultAttributes,
0,
NULL,
NULL,
NULL,
500,
&searchResult);
if (rc != LDAP_SUCCESS)
{
fprintf(stderr, "LDAP search error: %s\n", ldap_err2string(rc));
ldap_unbind_ext_s(ldapHandle, NULL, NULL);
return 0;
}
// https://linux.die.net/man/3/ldap_count_entries
printf("Total results: %d\n", ldap_count_entries(ldapHandle, searchResult));
////////////////////////////////////////////////////////////////////////////
// get result of search
// https://linux.die.net/man/3/ldap_first_entry
// https://linux.die.net/man/3/ldap_next_entry
LDAPMessage *searchResultEntry;
for (searchResultEntry = ldap_first_entry(ldapHandle, searchResult);
searchResultEntry != NULL;
searchResultEntry = ldap_next_entry(ldapHandle, searchResultEntry))
{
/////////////////////////////////////////////////////////////////////////
// Base Information of the search result entry
// https://linux.die.net/man/3/ldap_get_dn
printf("DN: %s\n", ldap_get_dn(ldapHandle, searchResultEntry));
/////////////////////////////////////////////////////////////////////////
// Attributes
// https://linux.die.net/man/3/ldap_first_attribute
// https://linux.die.net/man/3/ldap_next_attribute
//
// berptr: berptr, a pointer to a BerElement it has allocated to keep
// track of its current position. This pointer should be passed
// to subsequent calls to ldap_next_attribute() and is used to
// effectively step through the entry's attributes.
BerElement *ber;
char *searchResultEntryAttribute;
for (searchResultEntryAttribute = ldap_first_attribute(ldapHandle, searchResultEntry, &ber);
searchResultEntryAttribute != NULL;
searchResultEntryAttribute = ldap_next_attribute(ldapHandle, searchResultEntry, ber))
{
BerValue **vals;
if ((vals = ldap_get_values_len(ldapHandle, searchResultEntry, searchResultEntryAttribute)) != NULL)
{
for (int i = 0; i < ldap_count_values_len(vals); i++)
{
printf("\t%s: %s\n", searchResultEntryAttribute, vals[i]->bv_val);
if(strcmp(searchResultEntryAttribute,"uid") == 0){
if(strcmp(vals[i]->bv_val,rawLdapUser) == 0){
printf("\n\nGEFUNDEN!!!!!!!!!!!!!!!!!\n\n");
// Free Memory
ldap_value_free_len(vals);
ldap_memfree(searchResultEntryAttribute);
if (ber != NULL){
ber_free(ber, 0);
}
printf("\n");
ldap_msgfree(searchResult);
ldap_unbind_ext_s(ldapHandle, NULL, NULL);
return 1;
}
}
}
ldap_value_free_len(vals);
}
// free memory
ldap_memfree(searchResultEntryAttribute);
}
// free memory
if (ber != NULL)
{
ber_free(ber, 0);
}
printf("\n");
}
// free memory
ldap_msgfree(searchResult);
////////////////////////////////////////////////////////////////////////////
// https://linux.die.net/man/3/ldap_unbind_ext_s
// int ldap_unbind_ext_s(
// LDAP *ld,
// LDAPControl *sctrls[],
// LDAPControl *cctrls[]);
ldap_unbind_ext_s(ldapHandle, NULL, NULL);
return 0;
}
void *threadFun(void *arg){
int new_socket = *((int *)arg);
char buffer[BUF];
pthread_detach(pthread_self());
if(new_socket > 0){
strcpy(buffer, "Welcome to myserver, Please enter your command:\n");
strcpy(buffer, "Welcome to Lukas & Georgs Server, Please type <login> to login:\n");
send(new_socket, buffer, strlen(buffer),0);
}
bool login = false;
do {
int size = recv (new_socket, buffer, BUF-1, 0);
if( size > 0)
{
buffer[size] = '\0';
if (login == false)
{
// Do login
if (strncmp("login", buffer, 5) == 0)
{
char delimiter[] = ";";
char *ptr;
//den buffer mit dem seperator splitten
ptr = strtok(buffer, delimiter);
int counter = 0;
char username[9];
char pw[50];
while(ptr != NULL) {
if (counter == 1) {
strcpy(username, ptr);
}else if(counter == 2)
{
strcpy(pw, ptr);
}
counter = counter + 1;
// naechsten Abschnitt erstellen
ptr = strtok(NULL, delimiter);
}
if(login_user(username, pw) == 1){
login = true;
printf("Login geschafft!!");
//OK an den client zurücksenden
char suc[] = "OK";
send(new_socket , suc , strlen(suc) , 0 );
}else
{
printf("Login error!!!");
//OK an den client zurücksenden
char err[] = "ERR";
send(new_socket , err , strlen(err) , 0 );
}
//Überprüfen welchen command der client eingegeben hat,
}
}else{// Is logedin
// Überprüfen welchen command der client eingegeben hat,
// wenn command nicht zutreffend error zurücksenden
if(startsWith("send", buffer) == true) {
@ -76,13 +355,9 @@ void *threadFun(void *arg){
ptr = strtok(buffer, delimiter);
int counter = 0;
char filename1[] = "";
char filename2[] = "";
char sender[8] = "";
char content[] = "";
char empfaenger[8] = "";
char betreff[80] = "";
char nid[100] = "";
//timestamp als ersten teil der id erstellen
char ts[20];
@ -419,6 +694,7 @@ void *threadFun(void *arg){
send(new_socket , err , strlen(err) , 0 );
}
}
//printf ("\n content: \n %s", buffer);
@ -445,8 +721,6 @@ void *threadFun(void *arg){
int main (int argc, char **argv) {
int create_socket, new_socket;
socklen_t addrlen;
char buffer[BUF];
int size;
struct sockaddr_in address, cliaddress;
if( argc < 3 ){
@ -473,7 +747,6 @@ int main (int argc, char **argv) {
mkdir(argv[2], 0711);
pthread_t tid;
int i = 0;
while (1) {
printf("Waiting for connections...\n");
new_socket = accept ( create_socket, (struct sockaddr *) &cliaddress, &addrlen );