From: Peter Popovec Date: Mon, 31 Jan 2005 08:02:00 +0000 (+0100) Subject: Initial commit X-Git-Tag: 0.1-1^0 X-Git-Url: http://zub.fei.tuke.sk/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b643743c9c97c55e76a798503772052f1cda3f71;p=ldapvmail Initial commit --- b643743c9c97c55e76a798503772052f1cda3f71 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..8497727 --- /dev/null +++ b/Makefile @@ -0,0 +1,31 @@ +CFLAGS= -g -O2 -Wshadow -Wstrict-prototypes -Wcast-align -Wall + +vmail: vmail.o ldaplogin.o ldappass.o vmailsetup.o vmailHelper.o ldapadd.o + cc ${CFLAGS} -Wall -lnewt -lldap vmailHelper.o ldapadd.o vmailsetup.o vmail.o ldappass.o ldaplogin.o -o vmail + +vmail.o: vmail.c + cc ${CFLAGS} -Wall -c vmail.c -o vmail.o + +vmailHelper.o: vmailHelper.c + cc ${CFLAGS} -Wall -c vmailHelper.c -o vmailHelper.o + +ldaplogin.o: ldaplogin.c + cc ${CFLAGS} -Wall -c ldaplogin.c -o ldaplogin.o + +ldappass.o: ldappass.c + cc ${CFLAGS} -Wall -c ldappass.c -o ldappass.o + +vmailsetup.o: vmailsetup.c + cc ${CFLAGS} -Wall -c vmailsetup.c -o vmailsetup.o + +ldapadd.o: ldapadd.c + cc ${CFLAGS} -Wall -c ldapadd.c -o ldapadd.o + +clean: + rm -f *.o + rm -f *~ + rm -f vmail + +install: vmail + cp vmail ${DESTDIR}/usr/bin/ldapVmail + \ No newline at end of file diff --git a/debian/README b/debian/README new file mode 100644 index 0000000..639a061 --- /dev/null +++ b/debian/README @@ -0,0 +1,6 @@ +The Debian Package ldapvmail +---------------------------- + +NEWT based TUI for virtual mail system based on postfix, courier and ldap + +Peter Popovec , Sun, 30 Jan 2005 12:15:51 +0100 diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..97a6e0d --- /dev/null +++ b/debian/changelog @@ -0,0 +1,6 @@ +ldapvmail (0.1-1) unstable; urgency=low + + * Initial Release. + + -- Sun, 30 Jan 2005 12:27:01 +0100 + diff --git a/debian/control b/debian/control new file mode 100644 index 0000000..efb3558 --- /dev/null +++ b/debian/control @@ -0,0 +1,13 @@ +Source: ldapvmail +Section: unknown +Priority: optional +Maintainer: Peter Popovec +Build-Depends: debhelper (>> 3.0.0) +Standards-Version: 3.5.2 + +Package: ldapvmail +Architecture: any +Depends: ${shlibs:Depends} +Description: TUI for virtual mail system based on postfix, courier and ldap + NEWT based TUI for virtual mail system based on postfix, courier and ldap + Warning, this is alpha release ! \ No newline at end of file diff --git a/debian/copyright b/debian/copyright new file mode 100644 index 0000000..57658b9 --- /dev/null +++ b/debian/copyright @@ -0,0 +1,26 @@ +This package was debianized by Peter Popovec on +Sun, 30 Jan 2005 12:15:51 +0100. + +It was downloaded from http://zub.fei.tuke.sk/local.packages + +Upstream Author(s): Peter Popovec + +Copyright: + + This package is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 dated June, 1991. + + This package is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this package; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + 02111-1307, USA. + +On Debian GNU/Linux systems, the complete text of the GNU General +Public License can be found in `/usr/share/common-licenses/GPL'. + diff --git a/debian/dirs b/debian/dirs new file mode 100644 index 0000000..e772481 --- /dev/null +++ b/debian/dirs @@ -0,0 +1 @@ +usr/bin diff --git a/debian/docs b/debian/docs new file mode 100644 index 0000000..e69de29 diff --git a/debian/ex.package.doc-base b/debian/ex.package.doc-base new file mode 100644 index 0000000..a878f0b --- /dev/null +++ b/debian/ex.package.doc-base @@ -0,0 +1,22 @@ +Document: ldapvmail +Title: Debian ldapvmail Manual +Author: +Abstract: This manual describes what ldapvmail is + and how it can be used to + manage online manuals on Debian systems. +Section: unknown + +Format: debiandoc-sgml +Files: /usr/share/doc/ldapvmail/ldapvmail.sgml.gz + +Format: postscript +Files: /usr/share/doc/ldapvmail/ldapvmail.ps.gz + +Format: text +Files: /usr/share/doc/ldapvmail/ldapvmail.text.gz + +Format: HTML +Index: /usr/share/doc/ldapvmail/html/index.html +Files: /usr/share/doc/ldapvmail/html/*.html + + diff --git a/debian/rules b/debian/rules new file mode 100755 index 0000000..b00cd12 --- /dev/null +++ b/debian/rules @@ -0,0 +1,94 @@ +#!/usr/bin/make -f +# Sample debian/rules that uses debhelper. +# GNU copyright 1997 to 1999 by Joey Hess. + +# Uncomment this to turn on verbose mode. +#export DH_VERBOSE=1 + +# This is the debhelper compatibility version to use. +export DH_COMPAT=3 + + + +ifneq (,$(findstring debug,$(DEB_BUILD_OPTIONS))) + CFLAGS += -g +endif +ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) + INSTALL_PROGRAM += -s +endif + +configure: configure-stamp +configure-stamp: + dh_testdir + # Add here commands to configure the package. + + touch configure-stamp + + +build: build-stamp + +build-stamp: configure-stamp + dh_testdir + + # Add here commands to compile the package. + $(MAKE) + #/usr/bin/docbook-to-man debian/ldapvmail.sgml > ldapvmail.1 + + touch build-stamp + +clean: + dh_testdir + dh_testroot + rm -f build-stamp configure-stamp + + # Add here commands to clean up after the build process. + -$(MAKE) clean + + dh_clean + +install: build + dh_testdir + dh_testroot + dh_clean -k + dh_installdirs + + # Add here commands to install the package into debian/ldapvmail. + $(MAKE) install DESTDIR=$(CURDIR)/debian/ldapvmail + + +# Build architecture-independent files here. +binary-indep: build install +# We have nothing to do by default. + +# Build architecture-dependent files here. +binary-arch: build install + dh_testdir + dh_testroot +# dh_installdebconf + dh_installdocs + dh_installexamples + dh_installmenu +# dh_installlogrotate +# dh_installemacsen +# dh_installpam +# dh_installmime +# dh_installinit + dh_installcron + dh_installman + dh_installinfo +# dh_undocumented + dh_installchangelogs + dh_link + dh_strip + dh_compress + dh_fixperms +# dh_makeshlibs + dh_installdeb +# dh_perl + dh_shlibdeps + dh_gencontrol + dh_md5sums + dh_builddeb + +binary: binary-indep binary-arch +.PHONY: build clean binary-indep binary-arch binary install configure diff --git a/ldapadd.c b/ldapadd.c new file mode 100644 index 0000000..e000cdf --- /dev/null +++ b/ldapadd.c @@ -0,0 +1,211 @@ +#define _XOPEN_SOURCE +#define _GNU_SOURCE +#include +#include + +#include +#include +#include +#include +#include "ldaplogin.h" +#include "vmailHelper.h" +#include "vmailsetup.h" + +/* return value -1 if cancelled, 0 if ok */ +int +newAccount () +{ + newtComponent form, label, Bok, Bcancel, PWentry, DNentry, answer; + struct newtExitStruct es; + char *DN, *PW, *GN, *SN; + LDAP *ld; + char *addAttrxValue[8]; + + +/* form 1 POP3 ACCOUNT */ + + newtCenteredWindow (65, 12, "New Account"); + do + { + form = newtForm (NULL, NULL, 0); + label = newtLabel (0, 2, "POP3 login:"); + newtFormAddComponent (form, label); + label = newtLabel (0, 3, "POP3 passwd:"); + newtFormAddComponent (form, label); + Bok = newtButton (13, 6, "Next"); + Bcancel = newtButton (41, 6, "Cancel"); + DNentry = newtEntry (12, 2, NULL, 50, &DN, NEWT_FLAG_SCROLL); + PWentry = + newtEntry (12, 3, NULL, 50, &PW, + NEWT_FLAG_PASSWORD | NEWT_FLAG_RETURNEXIT); + newtFormAddComponents (form, DNentry, PWentry, Bok, Bcancel, NULL); + //newtFormAddHotKey (form, NEWT_KEY_BKSPC); + do + { + newtFormRun (form, &es); + if (es.reason == NEWT_EXIT_HOTKEY && es.u.key == NEWT_KEY_BKSPC) + { + newtFormDestroy (form); + newtPopWindow (); + return (-1); + } + } + while (es.reason != NEWT_EXIT_COMPONENT); + answer = es.u.co; + if (answer == Bcancel) + { + newtFormDestroy (form); + newtPopWindow (); + + return (-1); + } + if (answer != PWentry && answer != Bok) + { + newtFormDestroy (form); + newtPopWindow (); + return (-1); + } + addAttrxValue[0] = strdup (DN); + //TODO better random salt + asprintf (&addAttrxValue[1], "{crypt}%s", crypt (PW, "$!$pemasksk")); + newtFormDestroy (form); + } + while (strlen (addAttrxValue[0]) == 0 || strlen (addAttrxValue[1]) == 0); + //newtPopWindow (); + //newtCenteredWindow (65, 12, "New Account"); + +//form 2 mail & mailbox & sn givenname + do + { + form = newtForm (NULL, NULL, 0); + label = newtLabel (0, 2, "mail adresa:"); + newtFormAddComponent (form, label); + label = newtLabel (0, 3, "mbox:"); + newtFormAddComponent (form, label); + label = newtLabel (0, 4, "Meno/nazov konta:"); + newtFormAddComponent (form, label); + label = newtLabel (0, 5, "Priezvisko/firma:"); + newtFormAddComponent (form, label); + Bok = newtButton (13, 8, "Next"); + Bcancel = newtButton (41, 8, "Cancel"); + char *c1; + DNentry = + newtEntry (18, 2, addAttrxValue[0], 40, &DN, NEWT_FLAG_SCROLL); + newtFormAddComponent (form, DNentry); + asprintf (&c1, "%s%s", GetDefaultVmailPath (), addAttrxValue[0]); + DNentry = newtEntry (18, 3, c1, 40, &PW, NEWT_FLAG_SCROLL); + newtFormAddComponent (form, DNentry); + DNentry = newtEntry (18, 4, NULL, 40, &GN, NEWT_FLAG_SCROLL); + newtFormAddComponent (form, DNentry); + PWentry = + newtEntry (18, 5, NULL, 40, &SN, + NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT); + newtFormAddComponent (form, PWentry); + newtFormAddComponents (form, Bok, Bcancel, NULL); + //newtFormAddHotKey (form, NEWT_KEY_BKSPC); + do + { + newtFormRun (form, &es); + if (es.reason == NEWT_EXIT_HOTKEY && es.u.key == NEWT_KEY_BKSPC) + { + newtFormDestroy (form); + newtPopWindow (); + return (-1); + } + } + while (es.reason != NEWT_EXIT_COMPONENT); + answer = es.u.co; + if (answer == Bcancel) + { + newtFormDestroy (form); + newtPopWindow (); + return (-1); + } + + if (answer != PWentry && answer != Bok) + { + newtFormDestroy (form); + newtPopWindow (); + return (-1); + } + + free (c1); + addAttrxValue[2] = strdup (DN); + addAttrxValue[3] = strdup (PW); + addAttrxValue[4] = strdup (GN); + addAttrxValue[5] = strdup (SN); + + asprintf (&(addAttrxValue[6]), "%s %s", GN, SN); + addAttrxValue[7] = strdup ("active"); + addAttrxValue[8] = strdup ("top"); + newtFormDestroy (form); + } + while (strlen (addAttrxValue[2]) == 0 || strlen (addAttrxValue[3]) == 0 + || strlen (addAttrxValue[3]) == 0 || strlen (addAttrxValue[4]) == 0); + newtPopWindow (); + + +//uid,userPassword,mail,mailMessageStore,sn,cn,givenName + char *addAttrx[] = { + "uid", + "userPassword", + "mail", + "mailMessageStore", + "givenName", + "sn", + "cn", + "accountStatus", + "objectClass", + NULL + }; + + LDAPMod *addAttr0[10]; + + int i; + for (i = 0; addAttrx[i] != NULL; i++) + { + addAttr0[i] = malloc (sizeof (LDAPMod)); + addAttr0[i + 1] = NULL; + addAttr0[i]->mod_op = LDAP_MOD_ADD; + addAttr0[i]->mod_values = malloc (2 * sizeof (char *)); + addAttr0[i]->mod_type = strdup (addAttrx[i]); + addAttr0[i]->mod_values[0] = strdup (addAttrxValue[i]); + addAttr0[i]->mod_values[1] = NULL; + } + i--; + addAttr0[i]->mod_values = + realloc (addAttr0[i]->mod_values, 6 * sizeof (char *)); + addAttr0[i]->mod_values[1] = strdup ("person"); + addAttr0[i]->mod_values[2] = strdup ("organizationalPerson"); + addAttr0[i]->mod_values[3] = strdup ("inetOrgPerson"); + addAttr0[i]->mod_values[4] = strdup ("qmailUser"); + addAttr0[i]->mod_values[5] = NULL; + asprintf (&DN, "uid=%s,%s", addAttrxValue[0], GetDefaultVmailSubtree ()); + + switch (ldapLogin (&ld, WRITE_OP)) + { + case (0): + break; + case (-1): + infoWindow ("VMAIL account add...", "LDAP init error", 1); + return (1); + case (-3): + infoWindow ("VMAIL account add...", + "Couldn't bind to server, operation canceled", 1); + return 1; + default: + infoWindow ("VMAIL account add...", + "Couldn't bind to server, invalid credencial or other error", + 1); + return 1; + } + int ecode; + if (0 == (ecode = ldap_add_s (ld, DN, addAttr0))) + { + infoWindow ("VMAIL account add", "User ok", 100); + return (0); + } + else + infoWindow ("VMAIL account add", ldap_err2string (ecode), 1); + return (1); +} diff --git a/ldaplogin.c b/ldaplogin.c new file mode 100644 index 0000000..4eaae50 --- /dev/null +++ b/ldaplogin.c @@ -0,0 +1,197 @@ +//TODO EXTIME from setup +//TODO bindCredencial structure is not initialized before is used. +// (but only type and expire value is significant for init) + +#define _GNU_SOURCE +#define EXTIME 300 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ldaplogin.h" + +typedef struct bindCredencial0 +{ + char *server; + int port; + char *binddn; + char *bindpw; + struct timeval expire; + char type; //0 anonymous !0 real login + char ReadOnly; //1 if no modyfy operation on ldap +} bindCredencial; + +static int get_ldap_login (bindCredencial * ldata); +static bindCredencial logindata; + +/************************************************************************** +Call this to get LDAP ld structure associated with opened ldap connection +second arg is only indication for credencial cache .. and must be set up to +READ_OP or WRITE_OP. For WRITE_OP credencial must be rereaded. For READ_OP +can be used old credencial only if is not expirred or old credencial is not +escaped with annonymous bind. + +posible TODO .. cache can be turned on for WRITE_OP too in setup ? + +return value: +0 if success, -1 init error, -3 no homedir, -4 invalid credencial or other +ld structure is walid only if zero is returned + +*************************************************************************/ +int +ldapLogin (LDAP ** ld, int nomod) +{ + int version; + logindata.server = "localhost"; + logindata.port = 389; + logindata.ReadOnly = nomod; + + struct timeval current; + if (!(*ld = ldap_init (logindata.server, (long) logindata.port))) + return (-1); + + version = LDAP_VERSION3; + ldap_set_option (*ld, LDAP_OPT_PROTOCOL_VERSION, &version); + gettimeofday (¤t, NULL); + //if we have anonymous credencial or operation is write or timeout exided + //we need to get new credencial + if (nomod == WRITE_OP || logindata.type == 0 + || current.tv_sec > logindata.expire.tv_sec + EXTIME) + { + if (0 != get_ldap_login (&logindata)) + { + ldap_unbind (*ld); //free ldap structure + return (-3); + } + } + if (ldap_simple_bind_s (*ld, logindata.binddn, logindata.bindpw)) + { + ldap_unbind (*ld); //free ldap structure + return (-4); + } + + gettimeofday (¤t, NULL); + logindata.expire.tv_sec = current.tv_sec; //set timeout + return (0); +} + +//user dialog for credencial + +int +get_ldap_login (bindCredencial * ldata) +{ +#define progConfigDir "/.vmaiL/" +#define progConfigLdata "ldap_login" + + char *home, *ssh, *confdir; + FILE *default_admin; + char *defaultAdminFile; + char *defaultDN = NULL; + char *PW, *DN; + newtComponent form, Bok, Bcancel, Banon, label, answer, DNentry, PWentry; + + home = strdup (getenv ("HOME")); + if (home == NULL) + return (-1); + asprintf (&confdir, "%s%s", home, progConfigDir); + //confdir = malloc ((strlen (home) + strlen (progConfigDir)) * sizeof (char)); + //strcpy (confdir, home); + //strcat (confdir, progConfigDir); + free (home); + mkdir (confdir, 0700); + + ssh = NULL; + home = getenv ("SSH_CLIENT"); + if (home != NULL) + { + int i; + asprintf (&ssh, "%s%s", confdir, home); + //ssh = malloc ((strlen (home) + strlen (confdir)) * sizeof (char)); + //strcpy (ssh, confdir); //configdir + //strcat (ssh, home); //and ssh dir + //cut ssh_client after space + for (i = strlen (confdir); *home != ' '; home++, i++); + *(ssh + i) = '/'; + *(ssh + i + 1) = 0; + + if (0 == mkdir (ssh, 0700)) //new ssh .. do copy of base config + { + //TODO copy from confdir to ssh + // cp $confdir $ss + } + //TODO only default config is used .. + //confdir=ssh; + } + asprintf (&defaultAdminFile, "%s%s", confdir, progConfigLdata); + if (NULL != defaultAdminFile) + { + default_admin = fopen (defaultAdminFile, "r"); + if (default_admin != NULL) + { + defaultDN = malloc (100 * sizeof (char)); + if (defaultDN != NULL) + fgets (defaultDN, 99, default_admin); + fclose (default_admin); + } + else + defaultDN = NULL; + } + newtCenteredWindow (65, 10, "LDAP login"); + form = newtForm (NULL, NULL, 0); + label = newtLabel (0, 2, "Admin DN:"); + newtFormAddComponent (form, label); + label = newtLabel (0, 3, "Password:"); + newtFormAddComponent (form, label); + DNentry = newtEntry (10, 2, defaultDN, 50, &DN, NEWT_FLAG_SCROLL); + newtFormAddComponent (form, DNentry); + PWentry = + newtEntry (10, 3, NULL, 50, &PW, + NEWT_FLAG_PASSWORD | NEWT_FLAG_RETURNEXIT); + newtFormAddComponent (form, PWentry); + if (ldata->ReadOnly == WRITE_OP) //write operation + { + label = newtLabel (10, 4, "!!!!! Warning, write operation !!!!!"); + newtFormAddComponent (form, label); + } + Bok = newtButton (6, 6, "Login"); + Banon = newtButton (21, 6, "Anonymous login"); + Bcancel = newtButton (47, 6, "Cancel"); + newtFormAddComponents (form, Bok, Banon, Bcancel, NULL); + answer = newtRunForm (form); + if (answer == Bcancel) + { + newtFormDestroy (form); + newtPopWindow (); + return (-1); + } + if (answer == Banon) + { + newtFormDestroy (form); + newtPopWindow (); + ldata->binddn = NULL; + ldata->bindpw = NULL; + ldata->type = 0; //anonymous + return (0); + } + ldata->binddn = strdup (DN); + ldata->bindpw = strdup (PW); + ldata->type = 1; //not anonymous + newtFormDestroy (form); + newtPopWindow (); + if (NULL != defaultAdminFile) + { + default_admin = fopen (defaultAdminFile, "w"); + if (default_admin != NULL) + { + fprintf (default_admin, "%s", ldata->binddn); + fclose (default_admin); + } + } + return (0); +} diff --git a/ldaplogin.h b/ldaplogin.h new file mode 100644 index 0000000..e223da8 --- /dev/null +++ b/ldaplogin.h @@ -0,0 +1,4 @@ +#define READ_OP 1 +#define WRITE_OP 0 +int ldapLogin (LDAP ** ld,int type); + diff --git a/ldappass.c b/ldappass.c new file mode 100644 index 0000000..efb9c60 --- /dev/null +++ b/ldappass.c @@ -0,0 +1,102 @@ +#define _GNU_SOURCE +#define _XOPEN_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include "ldappass.h" +#include "ldaplogin.h" +#include "vmailHelper.h" + +int +passBox (char *dn) +{ + newtComponent form, Label, entry1, entry2, button, cancel, answer; + char *pass1, *pass2; + + newtOpenWindow (4, 8, 74, 10, "Change password for DN:"); + form = newtForm (NULL, NULL, 0); + entry1 = newtEntry (11, 3, NULL, 32, &pass1, NEWT_FLAG_PASSWORD); + newtFormAddComponent (form, entry1); + entry2 = + newtEntry (11, 4, NULL, 32, &pass2, + NEWT_FLAG_PASSWORD | NEWT_FLAG_RETURNEXIT); + newtFormAddComponent (form, entry2); + button = newtButton (1, 6, "OK"); + newtFormAddComponent (form, button); + cancel = newtButton (11, 6, "Cancel"); + newtFormAddComponent (form, cancel); + Label = newtLabel (1, 3, "Password: "); + newtFormAddComponent (form, Label); + Label = newtLabel (1, 4, "Verify: "); + newtFormAddComponent (form, Label); + Label = newtTextbox (1, 0, 71, 3, NEWT_FLAG_WRAP); + newtTextboxSetText (Label, dn); + newtFormAddComponent (form, Label); + for (;;) + { + answer = newtRunForm (form); + if (answer == cancel) + break; + else + { + if (0 != strcmp (pass1, pass2)) + { + infoWindow ("Password change", + "Sorry, passwords do not match", 1); + continue; + } + ldapPass (dn, pass1); + break; + } + } + newtFormDestroy (form); + newtPopWindow (); + return (0); +} + +int +ldapPass (char *dn, char *pass) +{ + LDAP *ld; + LDAPMod *addAttr0[2]; + addAttr0[0] = malloc (sizeof (LDAPMod)); + addAttr0[1] = NULL; + addAttr0[0]->mod_op = LDAP_MOD_REPLACE; + addAttr0[0]->mod_type = "userPassword"; + addAttr0[0]->mod_values = malloc (2 * sizeof (char *)); + asprintf (&addAttr0[0]->mod_values[0], "{crypt}%s", + crypt (pass, "$!$pemasksk")); + addAttr0[0]->mod_values[1] = NULL; + + switch (ldapLogin (&ld, WRITE_OP)) + { + case (0): + break; + case (-1): + infoWindow ("VMAIL password", "LDAP init error", 1); + return (1); + case (-3): + infoWindow ("VMAIL password", + "Couldn't bind to server, operation canceled", 1); + return 1; + default: + infoWindow ("VMAIL password", + "Couldn't bind to server, invalid credencial or other error", + 1); + return 1; + } + int ecode; + if (0 == (ecode = ldap_modify_s (ld, dn, addAttr0))) + { + infoWindow ("VMAIL password", "Password ok", 100); + return (0); + } + else + infoWindow ("VMAIL password", ldap_err2string (ecode), 1); + return (1); + +} diff --git a/ldappass.h b/ldappass.h new file mode 100644 index 0000000..e186e8e --- /dev/null +++ b/ldappass.h @@ -0,0 +1,2 @@ +int ldapPass (char *dn, char *pass); +int passBox (char *dn); diff --git a/vmail.c b/vmail.c new file mode 100644 index 0000000..c67f81d --- /dev/null +++ b/vmail.c @@ -0,0 +1,624 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "ldaplogin.h" +#include "vmailHelper.h" +#include "vmailsetup.h" + + +typedef struct vmailEntry0 +{ + char *dn; + char *uid; + char *sn; + char *givenName; + char *mailMessageStore; + char *mail; + char **forwardValues; + char **aliasValues; +} vmailEntry; + +int ldapEdit (vmailEntry * vmail); +int doEdit0 (vmailEntry * vmail); +int ldapPass (char *dn, char *pass); +int passBox (char *dn); +int ChangeEntry0 (char *wname, char *olddata, char **data, int type); +char *ChangeEntry (char *wname, char **data, int type); +char *getSearchFilter (void); +int doEdit (void); + +int +main () +{ + int rc, textWidth; + + GetSetup (); + newtInit (); + newtCls (); + for (;;) + { + char *menuContents[] = { "Add new mail account", + "Search & Edit account", + "*Admin password change ", + "*Setup", + "End", NULL + }; + textWidth = 0; + rc = + newtWinMenu ("Main Menu", "Select function for VMAIL system", 50, 2, + 12, 6, menuContents, &textWidth, "Ok", "Cancel", NULL); + + if (rc == 2) + break; + if (textWidth == 4) + break; + switch (textWidth) + { + case (0): + newAccount (); + break; + case (1): + doEdit (); + break; + } + } + newtFinished (); + + return (0); +} + + + +int +doLdapSearch (char *base, char *filter, LDAP ** ld, LDAPMessage ** result) +{ + struct timeval timeout; + + *ld = NULL; + + infoWindow ("VMAIL account search...", "Running search", 0); + switch (ldapLogin (ld, READ_OP)) + { + case (0): + break; + case (-1): + infoWindow ("VMAIL account search...", "LDAP init error", 1); + newtPopWindow (); + return (1); + case (-3): + infoWindow ("VMAIL account search...", + "Couldn't bind to server, operation canceled", 1); + newtPopWindow (); + return 1; + default: + infoWindow ("VMAIL account search...", + "Couldn't bind to server, invalid credencial or other error", + 1); + newtPopWindow (); + return 1; + } + + timeout.tv_sec = 10; + timeout.tv_usec = 0; + if (ldap_search_st + (*ld, base, LDAP_SCOPE_ONELEVEL, filter, NULL, 0, &timeout, result)) + { + infoWindow ("VMAIL account search...", "Search failed", 1); + ldap_unbind_s (*ld); + newtPopWindow (); //search + return 1; + } + newtPopWindow (); + return (0); +} + +int +doEdit () +{ + LDAP *ld; + LDAPMessage *result, *ldentry; + char **values; + char *searchFilter; + vmailEntry vmail; + + searchFilter = getSearchFilter (); + if (searchFilter == NULL) + { + return (0); + } + + if (0 == + doLdapSearch (GetDefaultVmailSubtree (), searchFilter, &ld, &result)) + { + + for (ldentry = ldap_first_entry (ld, result); NULL != ldentry; + ldentry = ldap_next_entry (ld, ldentry)) + { + vmail.dn = ldap_get_dn (ld, ldentry); + //TODO if uid mail and mailMessageStore count !=1 ?? + values = ldap_get_values (ld, ldentry, "uid"); + vmail.uid = values[0]; + values = ldap_get_values (ld, ldentry, "mailMessageStore"); + vmail.mailMessageStore = values[0]; + values = ldap_get_values (ld, ldentry, "mail"); + vmail.mail = values[0]; + values = ldap_get_values (ld, ldentry, "givenName"); + vmail.givenName = values[0]; + values = ldap_get_values (ld, ldentry, "sn"); + vmail.sn = values[0]; + vmail.forwardValues = + ldap_get_values (ld, ldentry, "mailForwardingAddress"); + vmail.aliasValues = + ldap_get_values (ld, ldentry, "mailAlternateAddress"); + switch (doEdit0 (&vmail)) + { + case (1): + ldapEdit (&vmail); + break; + case (-1): + ldap_msgfree (result); + ldap_unbind_s (ld); + return (0); + } + } + ldap_msgfree (result); + ldap_unbind_s (ld); + } + return (0); +} + + +int +doEdit0 (vmailEntry * vmail) +{ + char *value; + int count; + int realedit = 0; + newtComponent form, Bnext, Bcancel, Bpass, Bforward = NULL, Balias = + NULL, Label0, List0, List1 = NULL, List2 = NULL, answer; + + newtOpenWindow (2, 2, 75, 20, "VMAIL user"); +renewEdit: + form = newtForm (NULL, NULL, 0); + Bnext = newtButton (1, 16, "Next"); + newtFormAddComponent (form, Bnext); + Bcancel = newtButton (11, 16, "Cancel"); + newtFormAddComponent (form, Bcancel); + Bpass = newtButton (24, 16, "Password"); + newtFormAddComponent (form, Bpass); + + Label0 = newtLabel (1, 0, "POP3: "); + newtFormAddComponent (form, Label0); + Label0 = newtLabel (19, 0, vmail->uid); + newtFormAddComponent (form, Label0); + Label0 = newtLabel (1, 1, "sn: "); + newtFormAddComponent (form, Label0); + Label0 = newtLabel (1, 2, "givenName:"); + newtFormAddComponent (form, Label0); + Label0 = newtLabel (1, 3, "mail: "); + newtFormAddComponent (form, Label0); + Label0 = newtLabel (1, 4, "mailMessageStore: "); + newtFormAddComponent (form, Label0); + + List0 = newtListbox (19, 1, 4, NEWT_FLAG_RETURNEXIT); + newtListboxSetWidth (List0, 53); + newtListboxAppendEntry (List0, vmail->sn, (void *) 0); + newtListboxAppendEntry (List0, vmail->givenName, (void *) 1); + newtListboxAppendEntry (List0, vmail->mail, (void *) 2); + newtListboxAppendEntry (List0, vmail->mailMessageStore, (void *) 3); + newtFormAddComponent (form, List0); + + if (vmail->forwardValues != NULL) + { + Label0 = newtLabel (1, 6, "Forwarded to:"); + newtFormAddComponent (form, Label0); + List1 = + newtListbox (19, 5, 4, + NEWT_FLAG_RETURNEXIT | NEWT_FLAG_BORDER | + NEWT_FLAG_SCROLL); + newtListboxSetWidth (List1, 53); + for (count = 0, value = vmail->forwardValues[0]; value; + count++, value = vmail->forwardValues[count]) + + newtListboxAppendEntry (List1, value, (void *) count); + newtFormAddComponent (form, List1); + } + else + { + Bforward = newtButton (41, 16, "Forward"); + newtFormAddComponent (form, Bforward); + + } + if (vmail->aliasValues != NULL) + { + Label0 = newtLabel (1, 9, "Aliases:"); + newtFormAddComponent (form, Label0); + List2 = + newtListbox (19, 9, 7, + NEWT_FLAG_RETURNEXIT | NEWT_FLAG_BORDER | + NEWT_FLAG_SCROLL); + newtListboxSetWidth (List2, 53); + + for (count = 0, value = vmail->aliasValues[0]; value; + count++, value = vmail->aliasValues[count]) + + newtListboxAppendEntry (List2, value, (void *) count); + newtFormAddComponent (form, List2); + } + else + { + Balias = newtButton (55, 16, "Alias"); + newtFormAddComponent (form, Balias); + } + for (;;) + { + newtRefresh (); + answer = newtRunForm (form); + if (answer == List0) + { + int co; + char *data = NULL; + realedit = 1; + co = (int) newtListboxGetCurrent (List0); + cycle1: + { + switch (co) + { + case (0): + data = ChangeEntry ("Nove SN:", &(vmail->sn), 0); + break; + case (1): + data = + ChangeEntry ("Nove givenName:", &(vmail->givenName), 0); + break; + case (2): + data = ChangeEntry ("Novy Mail:", &(vmail->mail), 0); + break; + case (3): + data = + ChangeEntry ("Novy mailbox :", &(vmail->mailMessageStore), + 0); + break; + } + } + if (data != NULL) + { + if (strlen (data) == 0) + goto cycle1; + newtListboxSetEntry (List0, co, data); + } + } + if (answer == List1) + { + int co; + char *data = NULL; + realedit = 1; + co = (int) newtListboxGetCurrent (List1); + data = + ChangeEntry ("Novy forward:", &(vmail->forwardValues[co]), 1); + if (strlen (data) == 0) //null length forward to the end of list + { + for (count = co; vmail->forwardValues[count] != NULL; count++) + vmail->forwardValues[count] = vmail->forwardValues[count + 1]; + vmail->forwardValues[count - 1] = data; + } + if (data != vmail->forwardValues[co]) + { + if (data != NULL && strlen (data) > 0) + { + char **newdata; + for (count = 0; vmail->forwardValues[count] != NULL; + count++); + if (NULL == (newdata = calloc (count + 2, sizeof (char *)))) + infoWindow ("add forward", "out of mem", 1); + else + { + memcpy (newdata, vmail->forwardValues, + (count + 1) * sizeof (char *)); + newdata[count] = data; + vmail->forwardValues = newdata; + } + } + } + newtListboxClear (List1); + for (count = 0, value = vmail->forwardValues[0]; value; + count++, value = vmail->forwardValues[count]) + newtListboxAppendEntry (List1, value, (void *) count); + } + if (answer == List2) + { + int co; + char *data = NULL; + realedit = 1; + co = (int) newtListboxGetCurrent (List2); + data = ChangeEntry ("Novy alias:", &(vmail->aliasValues[co]), 1); + if (strlen (data) == 0) //null length forward to the end of list + { + for (count = co; vmail->aliasValues[count] != NULL; count++) + vmail->aliasValues[count] = vmail->aliasValues[count + 1]; + vmail->aliasValues[count - 1] = data; + } + if (data != vmail->aliasValues[co]) + { + if (data != NULL && strlen (data) > 0) + { + char **newdata; + for (count = 0; vmail->aliasValues[count] != NULL; count++); + if (NULL == (newdata = calloc (count + 2, sizeof (char *)))) + infoWindow ("add alias", "out of mem", 1); + else + { + memcpy (newdata, vmail->aliasValues, + (count + 1) * sizeof (char *)); + newdata[count] = data; + vmail->aliasValues = newdata; + } + } + } + newtListboxClear (List2); + for (count = 0, value = vmail->aliasValues[0]; value; + count++, value = vmail->aliasValues[count]) + newtListboxAppendEntry (List2, value, (void *) count); + } + + if (answer == Bpass) + passBox (vmail->dn); + if (answer == Bforward) + { + char **newdata; + if (NULL == (newdata = calloc (2, sizeof (char *)))) + infoWindow ("add forward", "out of mem", 1); + else + { + ChangeEntry ("Novy forward:", newdata, 0); + if (strlen (*newdata) > 0) + { + vmail->forwardValues = newdata; + newtFormDestroy (form); + realedit = 1; + goto renewEdit; + } + } + break; + } + if (answer == Balias) + { + char **newdata; + if (NULL == (newdata = calloc (2, sizeof (char *)))) + infoWindow ("add alias", "out of mem", 1); + else + { + ChangeEntry ("Novy alias:", newdata, 0); + if (strlen (*newdata) > 0) + { + vmail->aliasValues = newdata; + newtFormDestroy (form); + realedit = 1; + goto renewEdit; + } + } + break; + } + if (answer == Bnext) + break; + if (answer == Bcancel) + { + newtFormDestroy (form); + newtPopWindow (); + return (-1); + } + } + newtFormDestroy (form); + newtPopWindow (); + return (realedit); +} + +int +ChangeEntry0 (char *wname, char *olddata, char **data, int type) +{ + newtComponent form, entry, cancel, button, answer, add = NULL; + char *entryValue; + newtOpenWindow (4, 8, 74, 10, wname); + form = newtForm (NULL, NULL, 0); + entry = newtEntry (16, 1, olddata, 40, &entryValue, + NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT); + button = newtButton (19, 6, "Ok"); + newtFormAddComponent (form, entry); + newtFormAddComponent (form, button); + if (type == 1) + { + add = newtButton (27, 6, "Add new"); + newtFormAddComponent (form, add); + } + cancel = newtButton (40, 6, "Cancel"); + newtFormAddComponent (form, cancel); + newtRefresh (); + answer = newtRunForm (form); + *data = strdup (entryValue); + newtFormDestroy (form); + newtPopWindow (); + if (answer == button) + return (0); + if (type == 1 && answer == add) + return (1); + if (answer == entry) + return (0); + free (*data); + return (-1); +} + + +char * +ChangeEntry (char *wname, char **data, int type) +{ + char *newdata = NULL; + int what; + what = ChangeEntry0 (wname, *data, &newdata, type); + if (0 == what) + { + free (*data); + *data = newdata; + } + return (newdata); +} + +char * +getSearchFilter () +{ + newtComponent form, label, Bcancel, Bok, POPentry, MAILentry, answer; + char *DN, *PW, *filter; + + newtCenteredWindow (65, 12, "Search account"); + form = newtForm (NULL, NULL, 0); + label = newtLabel (0, 2, "POP3:"); + newtFormAddComponent (form, label); + label = newtLabel (0, 3, "MAIL:"); + newtFormAddComponent (form, label); + Bok = newtButton (13, 6, "Search"); + Bcancel = newtButton (25, 6, "Cancel"); + POPentry = + newtEntry (12, 2, "*", 50, &DN, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT); + MAILentry = + newtEntry (12, 3, "*", 50, &PW, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT); + newtFormAddComponents (form, POPentry, MAILentry, Bok, Bcancel, NULL); + answer = newtRunForm (form); + if (answer == Bcancel) + { + newtFormDestroy (form); + newtPopWindow (); + return (NULL); + } + asprintf (&filter, "(&(uid=%s)(|(mail=%s)(mailAlternateAddress=%s)))", DN, + PW, PW); + newtFormDestroy (form); + newtPopWindow (); + return (filter); + +} + +int +ldapEdit (vmailEntry * vmail) +{ + LDAP *ld; + char *addAttrx[] = { + "mail", + "mailMessageStore", + "givenName", + "sn", + "cn", + "mailAlternateAddress", + "mailForwardingAddress", + NULL + }; + LDAPMod *addAttr0[10]; + + int i; + for (i = 0; addAttrx[i] != NULL; i++) + { + addAttr0[i] = malloc (sizeof (LDAPMod)); + addAttr0[i + 1] = NULL; + addAttr0[i]->mod_op = LDAP_MOD_REPLACE; + addAttr0[i]->mod_type = addAttrx[i]; + if (addAttrx[i] == "mail") + { + addAttr0[i]->mod_values = malloc (2 * sizeof (char *)); + addAttr0[i]->mod_values[0] = vmail->mail; + addAttr0[i]->mod_values[1] = NULL; + } + if (addAttrx[i] == "mailMessageStore") + { + addAttr0[i]->mod_values = malloc (2 * sizeof (char *)); + addAttr0[i]->mod_values[0] = vmail->mailMessageStore; + addAttr0[i]->mod_values[1] = NULL; + } + if (addAttrx[i] == "mailMessageStore") + { + addAttr0[i]->mod_values = malloc (2 * sizeof (char *)); + addAttr0[i]->mod_values[0] = vmail->mailMessageStore; + addAttr0[i]->mod_values[1] = NULL; + } + if (addAttrx[i] == "givenName") + { + addAttr0[i]->mod_values = malloc (2 * sizeof (char *)); + addAttr0[i]->mod_values[0] = vmail->givenName; + addAttr0[i]->mod_values[1] = NULL; + } + if (addAttrx[i] == "sn") + { + addAttr0[i]->mod_values = malloc (2 * sizeof (char *)); + addAttr0[i]->mod_values[0] = vmail->sn; + addAttr0[i]->mod_values[1] = NULL; + } + if (addAttrx[i] == "cn") + { + addAttr0[i]->mod_values = malloc (2 * sizeof (char *)); + asprintf (& + (addAttr0[i]->mod_values[0]), "%s %s", vmail->givenName, + vmail->sn); + addAttr0[i]->mod_values[1] = NULL; + } + + if (addAttrx[i] == "mailAlternateAddress") + { + addAttr0[i]->mod_values = vmail->aliasValues; + if(vmail->aliasValues!=NULL) + while (*vmail->aliasValues != NULL) + { + if (strlen (*vmail->aliasValues) == 0) + { + *vmail->aliasValues = NULL; + break; + } + (vmail->aliasValues)++; + } + } + if (addAttrx[i] == "mailForwardingAddress") + { + addAttr0[i]->mod_values = vmail->forwardValues; + if(vmail->forwardValues!=NULL) + while (*vmail->forwardValues != NULL) + { + if (strlen (*vmail->forwardValues) == 0) + { + *vmail->forwardValues = NULL; + break; + } + (vmail->forwardValues)++; + } + } + + } + switch (ldapLogin (&ld, WRITE_OP)) + { + case (0): + break; + case (-1): + infoWindow ("VMAIL account edit...", "LDAP init error", 1); + return (1); + case (-3): + infoWindow ("VMAIL account edit...", + "Couldn't bind to server, operation canceled", 1); + return 1; + default: + infoWindow ("VMAIL account edit...", + "Couldn't bind to server, invalid credencial or other error", + 1); + return 1; + } + int ecode; + if (0 == (ecode = ldap_modify_s (ld, vmail->dn, addAttr0))) + { + infoWindow ("VMAIL account edit...", "User ok", 100); + return (0); + } + else + infoWindow ("VMAIL account edit...", ldap_err2string (ecode), 1); + return (1); +} diff --git a/vmailHelper.c b/vmailHelper.c new file mode 100644 index 0000000..23acdf1 --- /dev/null +++ b/vmailHelper.c @@ -0,0 +1,29 @@ +#include +#include +#include "vmailHelper.h" +int +infoWindow (char *wname, char *wmesg, int type) +{ + newtComponent form, label, button; + newtCenteredWindow (35, 10, wname); + form = newtForm (NULL, NULL, 0); + label = newtTextbox (1, 0, 30, 3, NEWT_FLAG_WRAP); + newtTextboxSetText (label, wmesg); + newtFormAddComponent (form, label); + if (type) + { + button = newtButton (15, 6, "OK"); + newtFormAddComponent (form, button); + if (type > 1) + newtFormSetTimer (form, 10 * type); + newtRunForm (form); + newtPopWindow (); + } + else + { + newtDrawForm (form); + newtRefresh (); + } + newtFormDestroy (form); + return (0); +} diff --git a/vmailHelper.h b/vmailHelper.h new file mode 100644 index 0000000..a862c93 --- /dev/null +++ b/vmailHelper.h @@ -0,0 +1,3 @@ +int newAccount (void); +int infoWindow (char *wname, char *wmesg, int type); + diff --git a/vmailsetup.c b/vmailsetup.c new file mode 100644 index 0000000..2dfe6b3 --- /dev/null +++ b/vmailsetup.c @@ -0,0 +1,148 @@ +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include "vmailsetup.h" + + + +//directory in $HOME for config +#define progConfigDir "/.vmaiL/" +//default DN of administrator for read/write in ldap +#define progConfigLdata "ldap_login" +#define progConfigVPath "vmail_path" +#define VmailPath "/home/vmail/" +#define progConfigVtree "vmail_tree" +#define VmailTree "ou=vmail,ou=internet,dc=MYDOMAYN,dc=sk" + +typedef struct setupData0 +{ + char *home; //homedir + char *confdir; //path to config dir + char *ssh_client; //ssh client IP (host) + + char *defaultAdminFile; //path to file with default admin + char *defaultAdminString; + + char *defaultVmailPathFile; //path to file with path for mailboxes + char *defaultVmailPathString; + + char *defaultVmailTreeFile; + char *defaultVmailTreeString; + +} setupData; + +char *getFromFile (char *filename); +int setToFile (char *filename, char *data); +int get_setup (setupData * s); + +setupData SetupDATA; + +int +GetSetup () +{ + return (get_setup (&SetupDATA)); +} + +int +get_setup (setupData * s) +{ + char *ssh; + + s->home = strdup (getenv ("HOME")); + if (s->home == NULL) + return (-1); + asprintf (&(s->confdir), "%s%s", s->home, progConfigDir); + mkdir (s->confdir, 0700); + + ssh = NULL; + s->ssh_client = getenv ("SSH_CLIENT"); + if (s->ssh_client != NULL) + { + int i; + asprintf (&ssh, "%s%s", s->confdir, s->ssh_client); + for (i = strlen (s->confdir); ssh[i] != ' '; i++); + ssh[i] = '/'; + ssh[i + 1] = 0; + + if (0 == mkdir (ssh, 0700)) //new ssh .. do copy of base config + { + //TODO copy from confdir to ssh + // cp $confdir $ssh + } + //TODO only default config is used .. + //confdir=ssh; + } + asprintf (&(s->defaultAdminFile), "%s%s", s->confdir, progConfigLdata); + s->defaultAdminString = getFromFile (s->defaultAdminFile); + + asprintf (&(s->defaultVmailPathFile), "%s%s", s->confdir, progConfigVPath); + s->defaultVmailPathString = getFromFile (s->defaultVmailPathFile); + if (s->defaultVmailPathString == NULL) + { + s->defaultVmailPathString = strdup (VmailPath); + setToFile (s->defaultVmailPathFile, s->defaultVmailPathString); + } + + asprintf (&(s->defaultVmailTreeFile), "%s%s", s->confdir, progConfigVtree); + s->defaultVmailTreeString = getFromFile (s->defaultVmailTreeFile); + if (s->defaultVmailTreeString == NULL) + { + s->defaultVmailTreeString = strdup (VmailTree); + setToFile (s->defaultVmailTreeFile, s->defaultVmailTreeString); + } + return (0); +} + +int +setToFile (char *filename, char *data) +{ + FILE *f; + if (NULL != filename) + { + f = fopen (filename, "w"); + if (NULL != f) + { + fprintf (f, "%s", data); + fclose (f); + return (0); + } + } + return (-1); +} + +char * +getFromFile (char *filename) +{ + FILE *f; + char buf[300]; + if (NULL != filename) + { + f = fopen (filename, "r"); + if (f != NULL) + { + if (NULL != fgets (buf, 299, f)) + { + fclose (f); + return (strdup (buf)); + } + fclose (f); + } + } + return (NULL); +} + + +char * +GetDefaultVmailPath () +{ + return (SetupDATA.defaultVmailPathString); +} + +char * +GetDefaultVmailSubtree () +{ + return (SetupDATA.defaultVmailTreeString); +} diff --git a/vmailsetup.h b/vmailsetup.h new file mode 100644 index 0000000..90bd5da --- /dev/null +++ b/vmailsetup.h @@ -0,0 +1,5 @@ +int GetSetup (void); +char * GetDefaultVmailPath (void); +char * GetDefaultVmailSubtree (void); + +