From b643743c9c97c55e76a798503772052f1cda3f71 Mon Sep 17 00:00:00 2001 From: Peter Popovec Date: Mon, 31 Jan 2005 09:02:00 +0100 Subject: [PATCH 1/1] Initial commit --- Makefile | 31 ++ debian/README | 6 + debian/changelog | 6 + debian/control | 13 + debian/copyright | 26 ++ debian/dirs | 1 + debian/docs | 0 debian/ex.package.doc-base | 22 ++ debian/rules | 94 ++++++ ldapadd.c | 211 +++++++++++++ ldaplogin.c | 197 ++++++++++++ ldaplogin.h | 4 + ldappass.c | 102 ++++++ ldappass.h | 2 + vmail.c | 624 +++++++++++++++++++++++++++++++++++++ vmailHelper.c | 29 ++ vmailHelper.h | 3 + vmailsetup.c | 148 +++++++++ vmailsetup.h | 5 + 19 files changed, 1524 insertions(+) create mode 100644 Makefile create mode 100644 debian/README create mode 100644 debian/changelog create mode 100644 debian/control create mode 100644 debian/copyright create mode 100644 debian/dirs create mode 100644 debian/docs create mode 100644 debian/ex.package.doc-base create mode 100755 debian/rules create mode 100644 ldapadd.c create mode 100644 ldaplogin.c create mode 100644 ldaplogin.h create mode 100644 ldappass.c create mode 100644 ldappass.h create mode 100644 vmail.c create mode 100644 vmailHelper.c create mode 100644 vmailHelper.h create mode 100644 vmailsetup.c create mode 100644 vmailsetup.h 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); + + -- 2.47.3