Register
It is currently Mon Nov 24, 2014 10:20 am

pop3din Bash(run via inetd or tcpsvd)


All times are UTC - 6 hours


Post new topic Reply to topic  [ 16 posts ] 
Author Message
 PostPosted: Tue Mar 29, 2011 11:27 pm   

Joined: Tue Mar 29, 2011 10:14 pm
Posts: 32
The other day I found this really neat pop3 server written in BASH that served out "fortune" emails here:
http://www.sozial-inkompetent.de/blog/p ... r_in_bash/

Well I saved the server script and played with it for awhile.
Then I decided that it'd be a great addition to a project I've mentioned in the smtpd in bash thread.
So I butchered his pop3 server script till it actually acts as a pop3 server.
Again seamonkey mail on another machine on my home network here can retrieve mail from the server, including attachments.
You'll need to add a dot-file in the users mail directory containing the user pop3 password for authentification.

Anyways here's the code

Code:
#!/bin/bash -debug

export LANG=C
echo "+OK POP3 server ready"
LOGFILE=/tmp/pop3.log
SPOOL="/home/users"
while read line; do
   #echo "[$BASHPID] - $line" >> $LOGFILE
   line="$line"
COMMAND="${line:0:4}"
        case "$COMMAND" in
      USER)
       USR=` echo $line | awk '{print $2}'  | dos2unix`
                   if [ -d "/home/users/$USR" ];
               then
                   echo "+OK"
                         else
                          echo "bad username"
                         exit;
                   fi
       ;;
      PASS)
      PASSW=${line:5}
       PSW=` echo $PASSW | dos2unix `
      P=` cat "$SPOOL/$USR/.$USR" `
            if [ "$PSW" = "$P" ];
          then
             a=1
for i in $SPOOL/$USR/*.txt; do
  new=$SPOOL/$USR/$(printf "%01d" ${a})
  mv ${i} ${new}
  let a=a+1
done
          echo "+OK"
          else
          echo "bad password"
          exit;
          fi
      ;;
      RETR)
      ML=`echo ${line:5} | dos2unix `
      OCT=`ls -l $SPOOL/$USR/${line:5} | awk '{print $5}' `
      echo "+OK $OCT octets"
      echo "$(cat $SPOOL/$USR/$ML)" 
      echo ""
      echo "."
      ;;
      STAT)
      N=`ls -1 $SPOOL/$USR | wc -l `
      M=`wc -c $SPOOL/$USR/* | sed -n '/total/p' | awk '{print $1}' `
         echo "+OK $N $M"
      ;;
      LIST)
         echo "+OK Mailbox scan listing follows"
         ls -l $SPOOL/$USR | awk '{print $9, $5}'
         echo "."
      ;;
      DELE)
      DEL=`echo ${line:5} | dos2unix `
      rm "$SPOOL/$USR/$DEL"
         echo "+OK message ${line:5} deleted"
      ;;
      UIDL)
      echo "+OK"
      head -n 1 $SPOOL/$USR/* | sed '/==>/d' | sed '/^$/d' | awk '{print ""NR" "$0}'
      echo "."
      ;;
      QUIT)
         echo "+OK bash POP3 server signing off (maildrop empty)"
         exit 0
      ;;
      *)
         echo "-ERR"
      ;;
   esac
   done




Top
 Profile  
 PostPosted: Wed Mar 30, 2011 2:48 pm   
User avatar

Joined: Sun Jun 27, 2010 12:57 am
Posts: 192
While the idea is nice, I surely hope that you're not running this accessible from the internet.
The authentication can easily be skipped, just send a user name and then start retrieving the users email. Or even worse any file on the system can be deleted. Since you suggest running this from inetd and would need to have access to read and 'rm' any user's email, I assume it would be run with root privileges. A simple 'DELE ../../../../../etc/passwd' (or worse) would then destroy your system.


Top
 Profile  
 PostPosted: Wed Mar 30, 2011 4:51 pm   

Joined: Tue Mar 29, 2011 10:14 pm
Posts: 32
Er uh..........as I said on the other thread...........I'm new to this.
And this is only a first edition of the pop script.
Originally there was no pop3 script, the smtpd script was fed by a CGI formail script from the client side and mail was written and read in a user .htaccess protected directory on a web server. Out going mail (relaying-sh) was handled via telnet with smtpd being the user shell like the old scryptic BBS's and their interconnected messaging systems (uucp-ish) With server to server communications only
Then I found that guys pop3 fortune script and things changed a bit.(funny how that happens, isn't it *grins*)

(Quote)A simple 'DELE ../../../../../etc/passwd' (or worse) would then destroy your system.
(end quote)
I oughta' be able remedy that by wrapping it in more sed and awk duct tape and using a test to only allow a single numerical character as input like the the "head" call is used to mimic UIDL.

(quote)The authentication can easily be skipped, just send a user name and then start retrieving the users email.
(end quote)
I could put the username and password sections in an authent section before entering the transaction loop.

And Thanks for the feedback, as while it might not be what I "wanted" to hear, it is what I "needed" to hear...........and that's always a good thing.


Top
 Profile  
 PostPosted: Wed Mar 30, 2011 6:04 pm   

Joined: Tue Mar 29, 2011 10:14 pm
Posts: 32
Well, I found out I can run these things in a chroot'd mini-environment containing only my statically compiled busybox with it's symlinks and my statically compiled bash, so that's one minor issue gone, even if it's a kludge to say the least.


Top
 Profile  
 PostPosted: Thu Mar 31, 2011 12:26 am   

Joined: Tue Mar 29, 2011 10:14 pm
Posts: 32
Well, I think I fixed the flaws in the script (probably opened some others though)
First things first, I broke it down into functions and one can't get to the next function without passing the function before it.
Second I added another variable in the DELE call to peel all but the first three characters off of any possible input, and exit (with a "yer outta' here") if the passed string is "../" or "./*".

I'd "hope" that nobody gets more than 999 emails when they get around to checking it

Code:
#!/bin/bash -debug

export LANG=C
echo "+OK POP3 server ready"
LOGFILE=/tmp/pop3.log
SPOOL="/home/users"

function pass() {
   read line
      PASSW=${line:5}
    PSW=` echo $PASSW | dos2unix `
   P=` cat "$SPOOL/$USR/.$USR" `
            if [ "$PSW" = "$P" ];
          then
          a=1
for i in $SPOOL/$USR/*.txt; do
  new=$SPOOL/$USR/$(printf "%01d" ${a})
  mv ${i} ${new}
  let a=a+1
done
       echo "+OK"
       #read line
       transaction
          else
          echo "bad password"
          exit;
          fi
}
function who() {
    if [ "$aut"  = "USER" ];
    then
  USR=`echo $first | awk '{print $2}' | dos2unix `
                  if  [ -d "/home/users/$USR" ];
                    then
                 echo "+OK"
                 pass
                 else
                    echo "bad username"
                 exit;
              fi
   fi          
}
function what ()
{
#echo "+OK POP3 server ready"   
read first
aut="${first:0:4}"
if [ "$aut" = "CAPA" -o "$aut" = "AUTH" ];
     then
      echo "-ERR"
     what
     exit;
else
who
fi
#fi               
}                
function transaction()
{
while read line; do
   #echo "[$BASHPID] - $line" >> $LOGFILE
   line="$line"
COMMAND="${line:0:4}"
        case "$COMMAND" in
      RETR)
      ML=`echo ${line:5} | dos2unix `
      OCT=`ls -l $SPOOL/$USR/${line:5} | awk '{print $5}' `
      echo "+OK $OCT octets"
      echo "$(cat $SPOOL/$USR/$ML)" 
      echo ""
      echo "."
      ;;
      STAT)
      N=`ls -1 $SPOOL/$USR | wc -l `
      M=`wc -c $SPOOL/$USR/* | sed -n '/total/p' | awk '{print $1}' `
         echo "+OK $N $M"
      ;;
      LIST)
         echo "+OK Mailbox scan listing follows"
         ls -l $SPOOL/$USR | awk '{print $9, $5}'
         echo "."
      ;;
      DELE)
      DEL=`echo ${line:5} | dos2unix `
      DR=`echo ${DEL:0:3} `
      #echo "$DR"
                 if [ "$DR" = "../" -o "$DR" = "./*" ];
               then
               echo "yer outta here"
               exit;
               else
      rm "$SPOOL/$USR/$DR"
         echo "+OK message $DR deleted"
         fi
      ;;
      UIDL)
      echo "+OK"
      head -n 1 $SPOOL/$USR/* | sed '/==>/d' | sed '/^$/d' | awk '{print ""NR" "$0}'
      echo "."
      ;;
      QUIT)
         echo "+OK bash POP3 server signing off (maildrop empty)"
         exit 0
      ;;
      *)
         echo "-ERR"
      ;;
   esac
   done
}
what




Top
 Profile  
 PostPosted: Thu Mar 31, 2011 11:06 am   
User avatar

Joined: Sun Jun 27, 2010 12:57 am
Posts: 192
While it it definitely better now, it still has quite a few exploitable holes in it if run without any extra precautions. For example, there's a couple of unquoted variables being used, meaning that, if left unchecked, I can fill them with $(command) values and execute anything I want. A good one would be to enter the username $(echo haxor::0:0::/:/bin/sh>/etc/passwd) and create a password-less 'root' account this way.


Top
 Profile  
 PostPosted: Sun Apr 03, 2011 6:06 pm   

Joined: Tue Mar 29, 2011 10:14 pm
Posts: 32
Well I go rid of the unquoted variables.

And like I said before Patsie, I appreciate the constructive criticism.
Anyways here's the third incarnation.

Code:
#!/bin/bash -debug

export LANG=C
echo "+OK POP3 server ready"
LOGFILE=/tmp/pop3.log
SPOOL="/home/users"

function pass() {
   read line
      PASSW=${line:5}
    PSW=` echo "$PASSW" | dos2unix `
   P=` cat "$SPOOL/$USR/.$USR" `
            if [ "$PSW" = "$P" ];
          then
          a=1
for i in $SPOOL/$USR/*.txt; do
  new=$SPOOL/$USR/$(printf "%01d" ${a})
  mv ${i} ${new}
  let a=a+1
done
       echo "+OK"
       #read line
       transaction
          else
          echo "bad password"
          exit;
          fi
}
function who() {
    if [ "$aut"  = "USER" ];
    then
  USR=`echo "$first" | awk '{print $2}' | dos2unix `
                  if  [ -d "/home/users/$USR" ];
                    then
                 echo "+OK"
                 pass
                 else
                    echo "bad username"
                 exit;
              fi
   fi          
}
function what ()
{
#echo "+OK POP3 server ready"   
read first
aut="${first:0:4}"
if [ "$aut" = "CAPA" -o "$aut" = "AUTH" ];
     then
      echo "-ERR"
     what
     exit;
else
who
fi
#fi               
}                
function transaction()
{
while read line; do
   #echo "[$BASHPID] - $line" >> $LOGFILE
   line="$line"
COMMAND="${line:0:4}"
        case "$COMMAND" in
      RETR)
      ML=`echo "${line:5}" | dos2unix `
      OCT=`ls -l "$SPOOL/$USR/${line:5}" | awk '{print $5}' `
      echo "+OK $OCT octets"
      echo "$(cat $SPOOL/$USR/$ML)" 
      echo ""
      echo "."
      ;;
      STAT)
      N=`ls -1 "$SPOOL/$USR" | wc -l `
      M=`wc -c "$SPOOL/$USR/*" | sed -n '/total/p' | awk '{print $1}' `
         echo "+OK $N $M"
      ;;
      LIST)
         echo "+OK Mailbox scan listing follows"
         ls -l "$SPOOL/$USR" | awk '{print $9, $5}'
         echo "."
      ;;
      DELE)
      DEL=`echo "${line:5}" | dos2unix `
      DR=`echo "${DEL:0:3}" `
      #echo "$DR"
                 if [ "$DR" = "../" -o "$DR" = "./*" ];
               then
               echo "yer outta here"
               exit;
               else
      rm "$SPOOL/$USR/$DR"
         echo "+OK message $DR deleted"
         fi
      ;;
      UIDL)
      echo "+OK"
      head -n 1 "$SPOOL/$USR/*" | sed '/==>/d' | sed '/^$/d' | awk '{print ""NR" "$0}'
      echo "."
      ;;
      QUIT)
         echo "+OK bash POP3 server signing off (maildrop empty)"
         exit 0
      ;;
      *)
         echo "-ERR"
      ;;
   esac
   done
}
what


Top
 Profile  
 PostPosted: Sun Apr 03, 2011 6:57 pm   

Joined: Tue Mar 29, 2011 10:14 pm
Posts: 32
Well that broke something, back to square one*chuckles*


Top
 Profile  
 PostPosted: Sun Apr 03, 2011 11:05 pm   
User avatar

Joined: Sun Jun 27, 2010 12:57 am
Posts: 192
I'm glad to help out here.

My guess would be the quoting of wildcards, like in f.e. STATS:
Code:
M=`wc -c "$SPOOL/$USR/*" | sed -n '/total/p' | awk '{print $1}' `

Quoting the variables is good, but a wildcard will also be taken literally and will not expand anymore when quoted. So keep the wildcards out of the quotes, like so:
Code:
M=$(wc -c "$SPOOL/$USR/"* | awk '/total/ {print $1}')


There are some other things that don't make sense to me, like f.e. this line at the beginning of your main 'while read line' loop:
Code:
line="$line"
Why is this line in here, since it doesn't seem to do anything?

Also there are quite few 'dos2unix' lines in there. Why not convert the line when it is being read and get rid of all the others? (the line="$line" would be a good place to dos2unix, so you won't have to do it anymore later in the code)


Top
 Profile  
 PostPosted: Mon Apr 04, 2011 1:51 am   

Joined: Tue Mar 29, 2011 10:14 pm
Posts: 32
Quote:
Also there are quite few 'dos2unix' lines in there. Why not convert the line when it is being read and get rid of all the others? (the line="$line" would be a good place to dos2unix, so you won't have to do it anymore later in the code)


*grinning sheepishly*
Er uh............because I'm a newbie and I really don't know what I'm doing yet?

Or isn't it "that" obvious?


Top
 Profile  
 PostPosted: Mon Apr 04, 2011 5:22 pm   

Joined: Tue Mar 29, 2011 10:14 pm
Posts: 32
I added a test to the RETR section and stripped the read argument input down to three characters after I found that
RETR *
followed by
LIST
did some ugly things to say the least
and while I was at it, part of that test is to also check for a
RETR ../
and other incarnations of the same command, as /etc/passwd while being interesting, isn't an email. *chuckles*

To avoid cluttering up this thread though, I'll wait to post the latest code till I see what other "wrong things" I can make it do and try to fix those too.


Top
 Profile  
 PostPosted: Tue Apr 05, 2011 2:27 pm   
User avatar

Joined: Sun Jun 27, 2010 12:57 am
Posts: 192
ZooT: I was inspired by your pop3 server idea and your tenacity of building this thing :)
Therefor I had my own idea of building this in awk. Please remember this too is in it's infancy since I started working on this only yesterday.
I hope it gives you some (good) ideas for your bash version.
Any user in /etc/passwd can make use of this service, as long as there is an md5 encrypted password for that user in his homedir named .pop3auth
(create with for example: echo -n "mypassword" | md5sum > ~/.pop3auth)
Emails are to be stored in that same users homedir, in a folder called .pop3spool and should be in standard mbox-format. (complete header, single empty line, then body.
I had a few trial runs with Evolution as a reader and it seemed to work quite well for me.

Code:
#!/usr/bin/gawk -f

function dbg(str) { printf("[%s] = %s\n", strftime("%T"), str); }

## send string to client
function send(disp, str) {
  printf("%s\r\n", str) |& pop3d;
  if (disp) printf("[%s] > %s\n", strftime("%T"), str);
}

## receive string from client
function recv() {
  if ((n=(pop3d |& getline)) < 1) {
    printf("[%s] = Connection lost (%d)\n", strftime("%T"), n);
    return(n);
  }
  gsub(/\r$/, "", $0);
  if ($1 == "PASS") printf("[%s] < PASS ********\n", strftime("%T"));
  else printf("[%s] < %s\n", strftime("%T"), $0);

  return(n);
}

function QUIT() {
  delete(_file);
  delete(_size);
  _user = _home = _auth = "";
  _nrfiles = _nrbytes = _last = 0;

  send(1,"+OK POP3 server signing off");
#  exit 0;
}

function USER(uname) {
  delete(_file);
  delete(_size);
  _user = _home = _auth = "";
  _nrfiles = _nrbytes = _last = 0;

  while ( (getline <passwd) > 0) {
    if ( ($0 !~ /^ *(#|;)/) && (split($0, arr, ":") > 6) ) {
      if ( (uname == arr[1]) && !system("test -d \""arr[6]"\"") ) {
        _user = arr[1];
        _home = arr[6];
        break;
      }
    }
  }
  close(passwd);

  if (_user) send(1,"+OK User accepted");
  else send(1,"-ERR Invalid user");
}

function PASS(pass) {
  _auth = "";

  if (_user && _home) {
    fname = _home"/"authfile;
    md5 = "echo -n \""pass"\" | md5sum";

    md5 | getline;
    md5sum = $1;
    close(md5);

    if ((getline < fname) > 0) {
      if (md5sum == $1) {
        _auth = 1;
        system("mkdir -p -m 700 \""_home"/"spooldir"\"");
      }
    }
    close(fname);
  }

  if (_auth) send(1,"+OK Authentication successful");
  else send(1,"-ERR Authentication failed");

  STAT(1);
}

function STAT(quiet) {
  if (_auth) {
    delete(_file);
    delete(_size);
    _nrfiles = _nrbytes = _last = 0;
    cmd = "ls -l \""_home"/"spooldir"/\"*\".mbox\" 2>/dev/null";

    while (cmd | getline) {
      if (split($0, arr) > 4) {
        _nrfiles++;
        _nrbytes += arr[5];
        _size[_nrfiles] = arr[5];
        _file[_nrfiles] = $NF;
      }
    }
    close(cmd);
    if (!quiet) send(1,sprintf("+OK %d %d", _nrfiles, _nrbytes));
  } else if (!quiet) send(1,"-ERR Please log in first");
}

function LIST(msg) {
  if (_auth) {
    if (msg) {
      if (_file[msg] && _size[msg]) send(1,sprintf("+OK %d %d", msg, _size[msg]));
      else send(1,"-ERR No such message");
    } else {
      send(1,sprintf("+OK %d messages, %d octets", _nrfiles, _nrbytes));
      for (i=1; i<=_nrfiles; i++)
        send(0,sprintf("%d %d", i, _size[i]));
      send(0,".");
    }
  } else send(1,"-ERR Please log in first");
}

function TOP(msg, head) {
  if (_auth) {
    if (_file[msg] && _size[msg]) {
      send(1,"+OK");
      while (getline < _file[msg]) {
        if ($0 == "") break;
        send(0,($0==".")?"..":$0);
      }
      if (head > 0) {
        send(0,"");
        while ((getline < _file[msg]) && (head-- > 0))
          send(0,($0==".")?"..":$0);
      }
      close(_file[msg]);
      send(0,".");
    } else send(1,"-ERR No such message");
  } else send(1,"-ERR Please log in first");
}

function RETR(msg) {
  if (_auth) {
    if (_file[msg] && _size[msg]) {
      _last = msg;
      send(1,sprintf("+OK %d octets", _size[msg]));
      while (getline < _file[msg])
        send(0,($0==".")?"..":$0);
      close(_file[msg]);
      send(0,".");
    } else send(1,"-ERR No such message");
  } else send(1,"-ERR Please log in first");
}

function DELE(msg) {
  if (_auth) {
    if (_file[msg] && _size[msg]) {
      _size[msg] = 0;
      send(1,sprintf("+OK Message %d marked for deletion",msg));
    } else send(1,"-ERR No such message");
  } else send(1,"-ERR Please log in first");
}

function NOOP() {
  if (_auth) send(1,"+OK");
  else send(1,"-ERR Please log in first");
}

function LAST() {
  if (_auth) send(1,sprintf("+OK %d", _last));
  else send(1,"-ERR Please log in first");
}

function RSET() {
  if (_auth) {
    _last = 0;
    STAT(1);
    send(1,"+OK");
  }
  else send(1,"-ERR Please log in first");
}

function UIDL() {
  if (_auth) {
    send(1,"-ERR Not implemented");
  } else send(1,"-ERR Please log in first");
}

BEGIN {
  passwd = "/etc/passwd";
  spooldir = ".pop3spool";
  authfile = ".pop3auth";

  pop3d = "/inet/tcp/110/0/0";

  while (1) {
    send(1,"+OK POP3 server ready");

    while (recv() > 0) {
      if ($0 ~ /^QUIT$/)        QUIT();
      else if ($0 ~ /^USER .+/) USER($2);
      else if ($0 ~ /^PASS .+/) PASS($2);
      else if ($0 ~ /^STAT$/)   STAT();
      else if ($0 ~ /^LIST/)    LIST($2);
      else if ($0 ~ /^TOP [0-9]+ [0-9]+$/) TOP($2, $3);
      else if ($0 ~ /^RETR [0-9]+$/) RETR($2);
      else if ($0 ~ /^DELE [0-9]+$/) DELE($2);
      else if ($0 ~ /^NOOP$/)   NOOP();
      else if ($0 ~ /^LAST$/)   LAST();
      else if ($0 ~ /^RSET$/)   RSET();
      else if ($0 ~ /^UIDL$/)   UIDL();
      else send(1,sprintf("-ERR %s command not implemented", $1));
    }
    close(pop3d);
  }
}


Top
 Profile  
 PostPosted: Tue Apr 05, 2011 10:00 pm   

Joined: Tue Mar 29, 2011 10:14 pm
Posts: 32
Quote:
ZooT: I was inspired by your pop3 server idea and your tenacity of building this thing


If it's worth doing in the first place it's worth sticking with till it's done.

(removed a "fixed" issue with mail attachments *grins*)


This bailing wiring, bungee cording, and duct taping the basic linux/un*x tool kit together like an erector set or legos to get it to do things that most folks download or install and configure special packages to do is fun *grin*
Even when I'm pulling my hair out.

Anyways, I think I'm going to have to spend some time learning awk, because while I can identify the sections in the code and the basic flow of the code, I don't really have any idea of what each line of code is doing.............yet.


Top
 Profile  
 PostPosted: Wed Apr 06, 2011 11:36 am   
User avatar

Joined: Sun Jun 27, 2010 12:57 am
Posts: 192
I'd be happy to help out with any questions you might have.


Top
 Profile  
 PostPosted: Wed Apr 13, 2011 5:08 pm   

Joined: Tue Mar 29, 2011 10:14 pm
Posts: 32
Here's the latest.
Changes have been made for the sake of client compatability and the use of a shared client username/password file.
There seems to be a difference between what the mail client generates as a base 64 encoding of the username and password versus what my linux base64 encoding decoding software produces although when decoded the same initial string is produced.
The pop3d client still sends in plain text, but the pop3d now decodes the username/password pair before comparison for authorization.

Code:
#!/bin/bash

export LANG=C
echo "+OK POP3 server ready"
LOGFILE=/tmp/pop3.log
SPOOL="/home/users"

function pass() {
   read line
      PASSW="${line:5}"
    PSW=` echo "$PASSW" | dos2unix | base64 | tr -d '\r' | tr -d '\n' `
   P=`cat $SPOOL/users | sed -n "/$USR/p" | awk '{print $2}' `
            if [ "$PSW" = "$P" ];
          then
          a=1
for i in $SPOOL/$USR/*.txt; do
  new=$SPOOL/$USR/$(printf "%01d" ${a})
  mv ${i} ${new}
  let a=a+1
done
       echo "+OK"
       transaction
          else
          echo "bad password"
          exit;
          fi
}
function who() {
    if [ "$aut"  = "USER" ];
    then
  USR=`echo "$first" | awk '{print $2}' | dos2unix `
                  if  [ -d "/home/users/$USR" ];
                    then
                 echo "+OK"
                 pass
                 else
                    echo "bad username"
                 exit;
              fi
   fi          
}
function what ()
{   
read first
aut=${first:0:4}
if [ "$aut" = "CAPA" -o "$aut" = "AUTH" ];
     then
      echo "-ERR"
     what
     exit;
else
who
fi
#fi               
}                
function transaction()
{
while read line; do
   #echo "[$BASHPID] - $line" >> $LOGFILE
   line="$line"
COMMAND="${line:0:4}"
        case "$COMMAND" in
      RETR)
      ML=`echo "${line:5:3}" | dos2unix `
      OCT=`ls -l "$SPOOL/$USR/${line:5}" | awk '{print $5}' `
      if [ "$ML" = "*" -o "$ML" = "../" -o "$ML" = "./*" ];
      then
      exit;
      else
      echo "+OK $OCT octets"
      echo "$(cat $SPOOL/$USR/$ML)" 
      echo ""
      echo "."
      fi
      ;;
      STAT)
      N=`ls -1 "$SPOOL/$USR" | wc -l `
      M=`wc -c "$SPOOL/$USR/"* | sed -n '/total/p' | awk '{print $1}' `
         echo "+OK $N $M"
      ;;
      LIST)
         echo "+OK Mailbox scan listing follows"
         ls -l "$SPOOL/$USR" | sed '/total/d' | awk '{print $9, $5}'
         echo "."
      ;;
      DELE)
      DEL=`echo "${line:5}" | dos2unix `
      DR=`echo "${DEL:0:3}" `
                 if [ "$DR" = "../" -o "$DR" = "./*" ];
               then
               echo "yer outta here"
               exit;
               else
      rm "$SPOOL/$USR/$DR"
         echo "+OK message $DR deleted"
         fi
      ;;
      UIDL)
      echo "+OK"
      head -n 10 "$SPOOL/$USR/"* | sed -n '/Message/p' | awk '{print ""NR" "$0}'
      #head -n 10 "$SPOOL/$USR/"* | sed -n '/Message/p' | sed 's/Message-ID://g' | sed 's/<//' | sed 's/>//' | sed 's/@//' | sed 's/.//' | awk '{print ""NR" "$0}'
      echo "."
      ;;
      QUIT)
         echo "+OK bash POP3 server signing off (maildrop empty)"
         exit 0
      ;;
      *)
         echo "-ERR"
      ;;
   esac
   done
}
what




Top
 Profile  
 PostPosted: Sun Apr 24, 2011 4:41 am   

Joined: Tue Mar 29, 2011 10:14 pm
Posts: 32
Here's the latest pop3d
As with the smtpd it incorporates a mail directory lockfile added into the pass function.
Down on line 113 there's some commented out code, which I'm still working with to expand mail client compatability.

Code:
#!/bin/bash

export LANG=C
echo "+OK POP3 server ready"
LOGFILE=/tmp/pop3.log
SPOOL="/home/users"

function pass() {
   read line
      PASSW="${line:5}"
    PSW=` echo "$PASSW" | dos2unix | base64 | tr -d '\r' | tr -d '\n' `
   P=`cat $SPOOL/users | sed -n "/$USR/p" | awk '{print $2}' `
            if [ "$PSW" = "$P" ];
          then
          cp "$SPOOL/temp/$USR/"* "$SPOOL/$USR"
          rm "$SPOOL/temp/$USR/"*
          a=1
for i in $SPOOL/$USR/*.txt; do
  new=$SPOOL/$USR/$(printf "%01d" ${a})
  mv ${i} ${new}
  let a=a+1
done
       echo "+OK"
       ufl=`cat $SPOOL/$USR.lock `
          tp=` ps p "$ufl" | sed '/PID/d' | awk '{print $1}' `
              if [ -z "$tp" ];
               then
            echo "$$" > "$SPOOL/$USR".lock
              transaction
              else
              echo "-ERR mailbox locked"
           exit;
              fi
         else
          echo "bad password"
          exit;
          #fi
          fi
}
function who() {
    if [ "$aut"  = "USER" ];
    then
  USR=`echo "$first" | awk '{print $2}' | dos2unix `
                  if  [ -d "/home/users/$USR" ];
                    then
                 echo "+OK"
                 pass
                 else
                    echo "bad username"
                 exit;
              fi
   fi          
}
function what ()
{   
read first
aut=${first:0:4}
if [ "$aut" = "CAPA" -o "$aut" = "AUTH" ];
     then
      echo "-ERR"
     what
     exit;
else
who
fi
#fi               
}                
function transaction()
{
while read line; do
   #echo "[$BASHPID] - $line" >> $LOGFILE
   line="$line"
COMMAND="${line:0:4}"
        case "$COMMAND" in
      RETR)
      ML=`echo "${line:5:3}" | dos2unix `
      OCT=`ls -l "$SPOOL/$USR/${line:5}" | awk '{print $5}' `
      if [ "$ML" = "*" -o "$ML" = "../" -o "$ML" = "./*" ];
      then
      exit;
      else
      echo "+OK $OCT octets"
      echo "$(cat $SPOOL/$USR/$ML)" 
      echo ""
      echo "."
      fi
      ;;
      STAT)
      N=`ls -1 "$SPOOL/$USR" | wc -l `
      M=`wc -c "$SPOOL/$USR/"* | sed -n '/total/p' | awk '{print $1}' `
         echo "+OK $N $M"
      ;;
      LIST)
         echo "+OK Mailbox scan listing follows"
         ls -l "$SPOOL/$USR" | sed '/total/d' | awk '{print $9, $5}'
         echo "."
      ;;
      DELE)
      DEL=`echo "${line:5}" | dos2unix `
      DR=`echo "${DEL:0:3}" `
                 if [ "$DR" = "../" -o "$DR" = "./*" ];
               then
               echo "yer outta here"
               exit;
               else
      rm "$SPOOL/$USR/$DR"
         echo "+OK message $DR deleted"
         fi
      ;;
      UIDL)
      echo "+OK"
      head -n 10 "$SPOOL/$USR/"* | sed -n '/Message/p' | awk '{print ""NR" "$0}'
      #head -n 10 "$SPOOL/$USR/"* | sed -n '/Message/p' | sed 's/Message-ID://g' | sed 's/<//' | sed 's/>//' | sed 's/@//' | sed 's/.//' | awk '{print ""NR" "$0}'
      echo "."
      ;;
      QUIT)
         echo "+OK bash POP3 server signing off (maildrop empty)"
         exit 0
      ;;
      *)
         echo "-ERR"
      ;;
   esac
   done
}
what




I also wrote this little script to easily add mailusers to the system.
It takes two arguments, the username and the password for that user.

Code:
#!/bin/bash

nam=` echo $1 | base64 | tr -d '\r' `
pass=` echo $2 | base64 | tr -d '\r'  `
echo "$nam $pass $1" >> /home/users/users
mkdir /home/users/"$1"
mkdir /home/users/temp/"$1"

exit;


Top
 Profile  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 16 posts ] 

All times are UTC - 6 hours


Who is online

Users browsing this forum: No registered users and 6 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Jump to:  
cron


BashScripts | Promote Your Page Too
Powered by phpBB © 2011 phpBB Group
© 2003 - 2011 USA LINUX USERS GROUP