dot

packages and services management
Log | Files | Refs | README

commit 0cfc1197059079e7ae3de155d26c50f853311d36
parent cb5fef51a8a76a2a44525c35ae84e6bac477d090
Author: Josuah Demangeon <mail@josuah.net>
Date:   Sat, 21 Jul 2018 20:41:36 +0200

pack/tinyldap: added from fefe.de

Diffstat:
Mdot/ssh/config | 26+++++++++++++-------------
Mpack/tinyldap/build | 10++++++++--
Apack/tinyldap/checkpassword.c | 339+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 360 insertions(+), 15 deletions(-)

diff --git a/dot/ssh/config b/dot/ssh/config @@ -2,41 +2,41 @@ AddKeysToAgent yes ServerAliveInterval 30 host ::1 - IdentityFile /mnt/key/josuah.key + IdentityFile /mnt/key/ssh/josuah.key host localhost - IdentityFile /mnt/key/josuah.key + IdentityFile /mnt/key/ssh/josuah.key host 127.0.0.1 - IdentityFile /mnt/key/josuah.key + IdentityFile /mnt/key/ssh/josuah.key host 192.168.* - IdentityFile /mnt/key/josuah.key + IdentityFile /mnt/key/ssh/josuah.key host 192.168.0.11 - IdentityFile /mnt/key/josuah.key + IdentityFile /mnt/key/ssh/josuah.key host 199.247.28.162 - IdentityFile /mnt/key/josuah.key + IdentityFile /mnt/key/ssh/josuah.key host bitreich.org - IdentityFile /mnt/key/josuah.key + IdentityFile /mnt/key/ssh/josuah.key host josuah.net - IdentityFile /mnt/key/josuah.key + IdentityFile /mnt/key/ssh/josuah.key host *.josuah.net - IdentityFile /mnt/key/josuah.key + IdentityFile /mnt/key/ssh/josuah.key host git.nixers.net - IdentityFile /mnt/key/git.nixers.net.key + IdentityFile /mnt/key/ssh/git.nixers.net.key host repo.or.cz - IdentityFile /mnt/key/repo.or.cz.key + IdentityFile /mnt/key/ssh/repo.or.cz.key host github.com - IdentityFile /mnt/key/github.com.key + IdentityFile /mnt/key/ssh/github.com.key host git.epitech.eu - IdentityFile /mnt/key/epitech.eu.key + IdentityFile /mnt/key/ssh/epitech.eu.key ConnectTimeout 3 diff --git a/pack/tinyldap/build b/pack/tinyldap/build @@ -1,5 +1,11 @@ #!/bin/sh -ex -rm tinyldap/.cvsignore -rmdir tinyldap +rm -rf tinyldap/ make DIET='sh -cx "cc -I${DEST}/include/ -L${DEST}/lib/ \$$@"' + +mkdir -p "$PREFIX/bin/" +cp addindex bindrequest dumpidx ldapclient ldapclient_str parse tinyldap \ +tinyldap_debug tinyldap_standalone \ +"$PREFIX/bin/" + +#cc -L"$DEST/lib/" -L./ -I"$DEST/include/" -I./ -pipe "$PACK/checkpassword.c" -lowfat diff --git a/pack/tinyldap/checkpassword.c b/pack/tinyldap/checkpassword.c @@ -0,0 +1,339 @@ +/* This is a checkpassword using LDAP for use with the qmail pop3d. + * It can also be used as authentication module for courier imapd. + * It assumes that all users have the same UID and GID and it is already + * running as this user. It will contact the LDAP server using + * the given username and password as simple authentication credentials. + * If the bind works, it will take the "homeDirectory" field from LDAP + * and use that as home directory. If the field is not there, it will + * try to construct the home directory like this: take the "uid" field + * and append it to HOME as #defined below to construct the home + * directory. If SUBDIRS is #defined, uid "leitner" will yield + * HOME/l/leitner instead of HOME/leitner. HOME has to end with a slash + * in any case. */ +#include <unistd.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <string.h> +#include <signal.h> +#include <errno.h> +#include "byte.h" +#include "buffer.h" +#include "asn1.h" +#include "ldap.h" +#include "socket.h" +#include "ip4.h" +#include "str.h" +#include "scan.h" + +#include <sys/types.h> +#include <sys/wait.h> + +#include <fcntl.h> + +#define BUFSIZE 8192 + +// #define HOME "/tmp/" +#define HOME "/data/maildirs/" +/* uncomment the following #define if you want mail for leitner to go to + * HOME/l/leitner instead of HOME/leitner */ +#define SUBDIRS +#define SHELL "/bin/sh" + +char* authenticated; /* getenv("AUTHENTICATED"); if this is not NULL, we + are running as courier authentication module and + not as checkpassword */ +static long messageid=1; /* LDAP message ID */ + +static int ldapbind(int sock,char* user,char* passwd) { + char outbuf[1024]; + int s=100; + int len=fmt_ldapbindrequest(outbuf+s,3,user,passwd); + int hlen=fmt_ldapmessage(0,messageid,BindRequest,len); + int res; + long op,Len,result; + struct string matcheddn,errormessage,referral; + fmt_ldapmessage(outbuf+s-hlen,messageid,BindRequest,len); + if (write(sock,outbuf+s-hlen,len+hlen)!=len+hlen) return 0; + len=read(sock,outbuf,1024); + res=scan_ldapmessage(outbuf,outbuf+len,&messageid,&op,&Len); + if (!res) return 0; + if (op!=BindResponse) return 0; + res=scan_ldapbindresponse(outbuf+res,outbuf+res+Len,&result,&matcheddn,&errormessage,&referral); + if (!res) return 0; + if (result) return 0; + return 1; +} + +static void maildirmake(const char* home) { + int mask=umask(077); + int fd=open(".",O_RDONLY); + /* make sure the home and a maildir exist */ + if (chdir(home)==-1) { + char* c=alloca(strlen(home)+1); + char* d; + /* not even the home exists! */ + strcpy(c,home); + while ((d=strrchr(c,'/'))) { + if (!d[1]) { *d=0; continue; } + break; + } + *d=0; mkdir(c,0700); + *d='/'; mkdir(c,0700); + chdir(home); + } + if (mkdir("Maildir",0700)!=-1 || errno!=EEXIST) { + chdir("Maildir"); + mkdir("tmp",0700); + mkdir("new",0700); + mkdir("cur",0700); + } + umask(mask); + fchdir(fd); + close(fd); +} + +static struct string uid; + +static void doit(const char* login, const char** argv, char* homedir) { + int len; + char **env,**ep; + char buf[100]; + char* home; + char* mylogin; + + if (uid.l) { /* must have non-zero uid as we queried by uid */ + mylogin=alloca(uid.l+1); + memmove(mylogin,uid.s,uid.l); + mylogin[uid.l]=0; + login=mylogin; + } + if (homedir) + home=homedir; + else { + home=malloc(strlen(HOME)+strlen(login)+10); + strcpy(home,HOME); +#ifdef SUBDIRS + buf[0]=login[0]; buf[1]='/'; buf[2]=0; + strcat(home,buf); +#endif + strcat(home,login); + } + for (len=0; environ[len]; ++len) ; + env=alloca((len+8)*sizeof(char*)); + ep=env; + for (len=0; environ[len]; ++len) { + if (str_start(environ[len],"USER=")) continue; + if (str_start(environ[len],"HOME=")) continue; + if (str_start(environ[len],"SHELL=")) continue; + if (str_start(environ[len],"UID=")) continue; + if (str_start(environ[len],"AUTHENTICATED=")) continue; + *ep=environ[len]; ++ep; + } + *ep=alloca(strlen(SHELL)+7); strcat(strcpy(*ep,"SHELL="),SHELL); ++ep; + *ep=alloca(strlen(login)+6); strcat(strcpy(*ep,"USER="),login); ++ep; + *ep=alloca(strlen(home)+7); strcat(strcpy(*ep,"HOME="),home); ++ep; + strcpy(buf,"UID="); + buf[4+fmt_ulong(buf+4,geteuid())]=0; + *ep=buf; ++ep; + if (authenticated) { + *ep=alloca(strlen(login)+20); + strcat(strcpy(*ep,"AUTHENTICATED="),login); ++ep; + + *ep="MAILDIR="; ++ep; + *ep="MAILDIRQUOTA="; ++ep; + + *ep=alloca(strlen(login)+20); + strcat(strcpy(*ep,"AUTHADDR="),login); ++ep; +#if 0 + *ep=alloca(strlen(fullname)+20); + strcat(strcpy(*ep,"AUTHFULLNAME="),fullname); ++ep; +#endif + } + *ep=0; + + maildirmake(home); + if (chdir(home)==-1) { + if (authenticated) { + buffer_puts(buffer_2,"checkpassword: chdir("); + buffer_puts(buffer_2,home); + buffer_putsflush(buffer_2,") failed!\n"); + execve(argv[0],(char* const*)argv,environ); + } + exit(111); + } + execve(argv[0],(char* const*)argv,env); + exit(111); +} + +int main(int argc,char* argv[]) { + int sock; + char buf[BUFSIZE]; + int len=0; + char cbuf[512]; + char* login,* password,* comment,* last; + + if ((authenticated=getenv("AUTHENTICATED"))) { + /* courier mode */ + if (authenticated[0]) { + /* already authenticated. */ + execve(argv[1],argv+1,environ); + exit(111); + } + } + if (!argv[1]) return 2; + for (len=0; len<512; ) { + int tmp; + tmp=read(3,buf+len,512-len); + if (tmp==-1) return 111; + if (tmp==0) break; + len+=tmp; + } + close(3); + buf[len]=0; last=buf+len; + + login=buf; + if (authenticated) { + if (!str_start(login,"imap\nlogin\n") && + !str_start(login,"pop3\nlogin\n")) { + buffer_puts(buffer_2,"checkpassword: invalid check method: "); + buffer_puts(buffer_2,login); + buffer_putsflush(buffer_2,".\n"); + exit(111); + } + login+=11; + password=strchr(login,'\n'); + if (!password) exit(111); *password=0; ++password; + comment=strchr(password,'\n'); + if (!comment) exit(111); *comment=0; ++comment; + } else { + password=login+strlen(login)+1; + comment=password+strlen(password)+1; + } + if (comment>last || (comment+strlen(comment)>last)) comment=""; + + sock=socket_tcp4(); + { + char ip[4]; + char *server=getenv("LDAPIP"); + if (!server) server="127.0.0.1"; + if (server[scan_ip4(server,ip)]) { + buffer_putsflush(buffer_2,"invalid $LDAPIP\n"); + goto fail; + } + if (socket_connect4(sock,ip,389)) { + buffer_putsflush(buffer_2,"could not connect to ldap server!\n"); + goto fail; + } + } + if (ldapbind(sock,"","")) { + char* founddn=0,*homedir=0; + char* basedn; + struct Filter f; + struct AttributeDescriptionList adl,adl2; + struct SearchRequest sr; + int i; + f.x=f.next=0; + f.type=EQUAL; + f.ava.desc.s="uid"; f.ava.desc.l=3; + f.ava.value.s=login; f.ava.value.l=strlen(f.ava.value.s); + f.a=0; + adl.a.s="homeDirectory"; adl.a.l=strlen(adl.a.s); + adl.next=&adl2; + adl2.a.s="uid"; adl2.a.l=strlen(adl2.a.s); + adl2.next=0; + sr.baseObject.s=getenv("BASEOBJECT"); + if (!sr.baseObject.s) { + buffer_putsflush(buffer_2,"$BASEOBJECT not set!\n"); + goto fail; + } + sr.baseObject.l=strlen(sr.baseObject.s); + sr.scope=wholeSubtree; sr.derefAliases=neverDerefAliases; + sr.sizeLimit=sr.timeLimit=sr.typesOnly=0; + sr.filter=&f; + sr.attributes=&adl; + len=fmt_ldapsearchrequest(buf+100,&sr); + { + int tmp=fmt_ldapmessage(0,++messageid,SearchRequest,len); + fmt_ldapmessage(buf+100-tmp,messageid,SearchRequest,len); + write(sock,buf+100-tmp,len+tmp); + } + { + char buf[8192]; /* arbitrary limit, bad! */ + int len=0,tmp,tmp2; + char* max; + struct SearchResultEntry sre; + for (;;) { + long slen,mid,op; + len=0; + tmp=read(sock,buf+len,sizeof(buf)-len); + if (tmp<=0) { + if (authenticated) + buffer_putsflush(buffer_2,"checkpassword: error reading from socket to ldap server.\n"); + goto fail; + } + len+=tmp; +nextmessage: + if ((tmp2=scan_ldapmessage(buf,buf+len,&mid,&op,&slen))) { + max=buf+slen+tmp2; + if (op==SearchResultEntry) { + if ((tmp=scan_ldapsearchresultentry(buf+tmp2,max,&sre))) { + if (!founddn) { + struct PartialAttributeList* pal=sre.attributes; + founddn=alloca(sre.objectName.l+1); + memcpy(founddn,sre.objectName.s,sre.objectName.l); + founddn[sre.objectName.l]=0; + while (pal) { + struct AttributeDescriptionList* adl=pal->values; + if (adl) { + if (!matchstring(&pal->type,"homeDirectory")) { + homedir=alloca(adl->a.l+1); + memcpy(homedir,adl->a.s,adl->a.l); + homedir[adl->a.l]=0; + } else if (!matchstring(&pal->type,"uid")) + uid=adl->a; + } + pal=pal->next; + } + } + } else { + if (authenticated) + buffer_putsflush(buffer_2,"checkpassword: LDAP result parse error!\n"); + goto fail; + } + } else if (op==SearchResultDone) { + if (!founddn) { + if (authenticated) + buffer_putsflush(buffer_2,"checkpassword: no such uid in LDAP.\n"); + goto fail; + } + break; + } else { + if (authenticated) + buffer_putsflush(buffer_2,"checkpassword: unexpected LDAP response.\n"); + goto fail; + } + if (max<buf+len) { + byte_copy(buf,buf+len-max,max); + tmp-=(max-(buf+len)); + len-=(max-(buf+len)); + goto nextmessage; + } + } + } + } + if (founddn) { + if (ldapbind(sock,founddn,password)) { + close(sock); + doit(login,(const char**)argv+1,homedir); +// buffer_putsflush(buffer_1,"OK!\n"); + return 0; + } else + buffer_putsflush(buffer_1,"auth failure!\n"); + } + } /* else authentication failed */ +fail: + if (authenticated) + execve(argv[1],argv+1,environ); + return 111; +}