Postfix SMTP, sasl, mysql alapon

Üdv!

Nem tudom járt-e már így valaki, de gondoltam megosztom mással is ne szívjon vele fölöslegesen:

Egy - saját - keretrendszer keretén belül kezelem az email címeket. A postfix-ben pedig használom a címben is szereplő összetevőket. A szívás onnan eredt, hogy az autentikációkor az SQL táblában szereplő encrypt-elt jelszó ha üres, azaz nincs egy árva karakter se benne, akkor akármilyen(!)
jelszót elfogad a saslauth PAM-on keresztül!

Majdnem leestem a székről!

Eddig azok az ügyfelek, akiknek már nem kellett az email, azoknál az azonosítót meghagytam - kell -, de a jelszót simán kiürítettem. Ma vettem észre, hogy olyan ügyfél, aki már nem ügyfél, csont nélkül küldözgeti a leveleit, a szerverünkön keresztül!

Tanulság: sokkal sűrűbben kell figyelni a logokat!

Tilla

Hozzászólások

Az olyan ügyfél, aki nem ügyfél, annak nyugodtan lehet a fiókját és a domainjét is törölni, egyrészt adatvédelmi okok miatt, másrészt meg azért, mert majd jönnek a katyvaszok, hogy nem kapja meg a leveleit azoktól a userektől, akik ugyanazon a gépen vannak...
Ez különösen nagy szolgáltatóknál szokott izgalmas lenni.
--
Discover It - Have a lot of fun!

Postafiókja törlődik, adatvédelmi szempontból legalább egy évig tudnom kell róla, azon az email címen, pedig nem lehet máshol se belőle több!

Ad absurdum, ha egyedi domain-en volt és a domain-el együtt "távozott", akkor úgy a domain-t is törlöm, így nincs katyvasz!

DE

A bejegyzés lényege nem ez volt, hanem az, hogy üres jelszó mező esetén bármilyen(!) jelszót elfogad a PAM!!!

Tilla

Igen mert a user letiltásának módja nem ez, hanem az hogy inaktívvá teszed.
Ezért van például egy where=mailbox.active=1 az /etc/pam.d/smtp-ban, ha pl postfixadmin-t használsz.

Arra azért kíváncsi lennék, hogy mi van a /etc/pam.d/smtp-ban nálad.
Meg arra is, hogy bármilyen jelszóval beengedte a usereket vagy csak üres jelszóval.

Az user letiltása nem csak ebből állt! Bár a pam -os smtp -ben nincs
"where" érték! (ez hiba, de nem mentesíti a pam_mysql modult, hogy
egyező username és NEM egyező crypt mező alapján elfogadjon egy login procedúrát!

A smtp file-ban azon kívül, hogy nincs "where" rész, teljesen hétköznapi a dolog!

Igen, teljesen mindegy volt hogy mit írtam be jelszónak, simán beengedett.
Egyébként a crypt=1 esetén az üresen megadott jelszó encryptelt értéke soha nem lesz üres string, azaz így se lehetne egyezőség!

Itt két olyan hiba "együttállás" volt, ami gondot okozott, külön-külön nem
jelentett volna semmilyen problémát!

Ezért írtam ide, hogy erre figyelni kell! Utólag már én is okosabb lettem!

Tilla

Itt van egyébként a problémás rész asszem:


// static pam_mysql_err_t pam_mysql_check_passwd(pam_mysql_ctx_t *ctx,
//		const char *user, const char *passwd, int null_inhibited)
// pam_mysql.c 2559. sor


				/* ENCRYPT */
				case 1:
					vresult = strcmp(row[0], crypt(passwd, row[0]));

Próbáltam reprodukálni:


int main(void)
{
  char * cr1 = crypt("djskahd", "");
  int retval1 = strcmp("djskahd", cr1);
  printf("%d.\n", retval1);
  printf("%s.\n", cr1);

  char * cr2 = crypt("", "");
  int retval2 = strcmp("", cr2);
  printf("%d.\n", retval2);
  printf("%s.\n", cr2);

  return 0;
}

Futási eredmény:


$ ./a.out 
1.
.
0.
.

Ez alapján ez csak az üres jelszavakkal működött, nem bármilyen jelszóval, bár már fáradt vagyok és lehet benézhetek valamit.
Esetleg valami más is bekavar, ami itt most nem látszik.
Azt megköszönném, ha kipróbálnád, hogy most akkor tényleg mindenfélével megy,
többek között üressel is, vagy csak üressel, vagy csak nem üressel.
Most már kíváncsi vagyok.
Amúgy meg hogy ez most a pam_mysql a crypt vagy a te hibád az megérne egy flame war-t :)

(Szerk.)

Este megnézem én is, de a lényeg, hogy az SQL táblában - eredetileg - benne volt a jelszava annak az ügyfélnek aki már nem ügyfél (hiba itt: nem lett kivéve az ügyfél a táblából). Logokat elemezve észrevettem, hogy sasl loginnal ez az ügyfél leveleket küld. Ebben az állapotban az ügyfél, az eredeti jelszavát használva - kvázi szabályosan - autentikálva levelet küld smtp-sasl segítségével.

"Fejemhez kap" és hirtelen ötlettől vezérelve a 'crypt' mezőt kitöröltem.
(Ügyfelet a táblából nem törlök legalább 1 évig!).
Néhány órán belüli log elemzésnél kiderül, hogy simám(!) küldi a leveleket tovább, holott ekkor már nincs jelszó!

Ekkor "lettem rosszul" :)

Mindenesetre a crypt mezőt feltöltöttem néhány "karakterrel" és a pam-os smtp file-ba beletettem a 'where' feltételt is. Ennél többet maximum este lesz időm átnézni...

Tilla

Kipróbáltam én is, és valóban bármivel működik.
Próbálok majd még rájönni, hogy mi az oka.

Szerk.:
Nah kissé pihentebb aggyal ugyanaz nem elírva.

Egyébként a crypt=1 esetén az üresen megadott jelszó encryptelt értéke soha nem lesz üres string, azaz így se lehetne egyezőség!
De bizony, igazándiból nem is a jelszó üres, hanem a salt és emiatt ad vissza üres stringet a crypt.


int main(void)
{

  char * userpassword = "abcdef";
  char * sqlpassword = "";
  int vresult = -1;
  //vresult = strcmp(row[0], crypt(passwd, row[0]));
  vresult = strcmp(sqlpassword, crypt(userpassword, sqlpassword));
  printf("vresult: %d\n", vresult);
  return 0;
}

Kimenet:


vresult: 0

Be kéne jelenteni, meg patch-et beküldeni.
Van valakinek ötlete egy korrekt workaround-ra?

Itt van egy ezzel kapcsolatos bug: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=623220
És ezt írják. (Nem olvastam végig az egészet.)
"An optional salt string to base the hashing on. If not provided, the behaviour is defined by the algorithm implementation and can lead to unexpected results. "
"There is nothing wrong about returning empty string (aka unexpected
result) - which hashing do you want anyway?"

Javítják, de úgy néz ki, hogy csak a php implementációban:
"Even though I think that it's the application which needs fixing and
the implementation follows system crypt (which will return empty
string in case you provide the empty salt), you have convinced me that
it's worth fixing in squeeze."