diff -ur pure-ftpd-1.0.49.org/config.h.in pure-ftpd-1.0.49/config.h.in --- pure-ftpd-1.0.49.org/config.h.in 2019-03-25 18:00:47.000000000 +0100 +++ pure-ftpd-1.0.49/config.h.in 2019-06-10 11:13:52.181133752 +0200 @@ -3,6 +3,9 @@ /* Define if building universal (internal helper macro) */ #undef AC_APPLE_UNIVERSAL_BUILD +/* with apparmor */ +#undef APPARMOR + /* display only boring messages */ #undef BORING_MODE diff -ur pure-ftpd-1.0.49.org/configure.ac pure-ftpd-1.0.49/configure.ac --- pure-ftpd-1.0.49.org/configure.ac 2019-04-03 12:41:30.000000000 +0200 +++ pure-ftpd-1.0.49/configure.ac 2019-06-10 11:13:52.181133752 +0200 @@ -790,6 +790,13 @@ AC_DEFINE(QUOTAS,,[with quotas]) fi ]) +AC_ARG_WITH(apparmor, +[AS_HELP_STRING(--with-apparmorquotas,Support changing Apparmor Hats)], +[ if test "x$withval" = "xyes" ; then + AC_DEFINE(APPARMOR,,[with apparmor]) + LIBS="$LIBS -lapparmor" + fi ]) + AC_ARG_WITH(ftpwho, [AS_HELP_STRING(--with-ftpwho,Support for pure-ftpwho)], [ if test "x$withval" = "xyes" ; then Only in pure-ftpd-1.0.49: configure.ac.orig diff -ur pure-ftpd-1.0.49.org/pureftpd-mysql.conf pure-ftpd-1.0.49/pureftpd-mysql.conf --- pure-ftpd-1.0.49.org/pureftpd-mysql.conf 2019-06-10 11:13:16.120061167 +0200 +++ pure-ftpd-1.0.49/pureftpd-mysql.conf 2019-06-10 11:13:52.181133752 +0200 @@ -112,6 +112,9 @@ # MySQLGetBandwidthDL SELECT DLBandwidth FROM users WHERE User='\L' +# Optional : Apparmor Hat to use. +# MYSQLGetApparmorHat SELECT hat FROM users WHERE User='\L' + # Enable ~ expansion. NEVER ENABLE THIS BLINDLY UNLESS : # 1) You know what you are doing. # 2) Real and virtual users match. diff -ur pure-ftpd-1.0.49.org/README.Authentication-Modules pure-ftpd-1.0.49/README.Authentication-Modules --- pure-ftpd-1.0.49.org/README.Authentication-Modules 2019-03-25 18:10:06.000000000 +0100 +++ pure-ftpd-1.0.49/README.Authentication-Modules 2019-06-10 11:17:27.140847844 +0200 @@ -118,6 +118,9 @@ The maximal authorized number of concurrent sessions. +* apparmor_hat:xxx (optional) + +Apparmor HAT name. ------------------------ EXAMPLE ------------------------ diff -ur pure-ftpd-1.0.49.org/src/ftpd.c pure-ftpd-1.0.49/src/ftpd.c --- pure-ftpd-1.0.49.org/src/ftpd.c 2019-06-10 11:13:16.123394599 +0200 +++ pure-ftpd-1.0.49/src/ftpd.c 2019-06-10 11:13:52.184467185 +0200 @@ -18,6 +18,9 @@ #ifdef QUOTAS # include "quotas.h" #endif +#ifdef APPARMOR +# include +#endif #ifdef WITH_DIRALIASES # include "diraliases.h" #endif @@ -1516,6 +1519,9 @@ result.ratio_download = ratio_download; result.ratio_ul_changed = result.ratio_dl_changed = 0; #endif +#ifdef APPARMOR + result.apparmor_hat = NULL; +#endif #ifdef PER_USER_LIMITS result.per_user_max = per_user_max; #endif @@ -1944,6 +1950,16 @@ # endif enablesignals(); #endif + +#ifdef APPARMOR + if (authresult.apparmor_hat != NULL) { + if (change_hat(authresult.apparmor_hat, zrand()) < 0) + die(421, LOG_ERR, MSG_CHROOT_FAILED); + logfile(LOG_INFO, MSG_APPARMOR_HAT, account, authresult.apparmor_hat); + free(authresult.apparmor_hat); + } +#endif + logfile(LOG_INFO, MSG_IS_NOW_LOGGED_IN, account); #ifdef FTPWHO if (shm_data_cur != NULL) { diff -ur pure-ftpd-1.0.49.org/src/ftpd.h pure-ftpd-1.0.49/src/ftpd.h --- pure-ftpd-1.0.49.org/src/ftpd.h 2019-06-10 11:13:16.123394599 +0200 +++ pure-ftpd-1.0.49/src/ftpd.h 2019-06-10 11:13:52.184467185 +0200 @@ -291,6 +291,9 @@ #ifdef PER_USER_LIMITS unsigned int per_user_max; #endif +#ifdef APPARMOR + const char *apparmor_hat; +#endif } AuthResult; typedef struct PureFileInfo_ { diff -ur pure-ftpd-1.0.49.org/src/log_extauth.c pure-ftpd-1.0.49/src/log_extauth.c --- pure-ftpd-1.0.49.org/src/log_extauth.c 2019-04-03 12:38:36.000000000 +0200 +++ pure-ftpd-1.0.49/src/log_extauth.c 2019-06-10 11:15:54.581435088 +0200 @@ -145,6 +145,19 @@ #endif } +static void callback_reply_apparmor_hat(const char *str, AuthResult * const result) +{ +#ifdef APPARMOR + if (*str) { + free((void *) (result->apparmor_hat)); + result->apparmor_hat = strdup(str); + } +#else + (void) str; + (void) result; +#endif +} + static void callback_reply_end(const char *str, AuthResult * const result) { (void) str; @@ -221,6 +234,9 @@ result->uid = (uid_t) 0; result->gid = (gid_t) 0; result->dir = NULL; +#ifdef APPARMOR + result->apparmor_hat = NULL; +#endif result->slow_tilde_expansion = 1; auth_finalized = 0; if ((readnb = safe_read(kindy, line, sizeof line - 1U)) <= (ssize_t) 0) { diff -ur pure-ftpd-1.0.49.org/src/log_extauth.h pure-ftpd-1.0.49/src/log_extauth.h --- pure-ftpd-1.0.49.org/src/log_extauth.h 2019-03-25 18:11:33.000000000 +0100 +++ pure-ftpd-1.0.49/src/log_extauth.h 2019-06-10 11:14:18.448581707 +0200 @@ -35,6 +35,7 @@ #define EXTAUTH_REPLY_RATIO_UPLOAD "ratio_upload" EXTAUTH_KEYWORD_SEP #define EXTAUTH_REPLY_RATIO_DOWNLOAD "ratio_download" EXTAUTH_KEYWORD_SEP #define EXTAUTH_REPLY_PER_USER_MAX "per_user_max" EXTAUTH_KEYWORD_SEP +#define EXTAUTH_REPLY_APPARMOR_HAT "apparmor_hat" EXTAUTH_KEYWORD_SEP #define EXTAUTH_REPLY_END "end" #endif diff -ur pure-ftpd-1.0.49.org/src/log_extauth_p.h pure-ftpd-1.0.49/src/log_extauth_p.h --- pure-ftpd-1.0.49.org/src/log_extauth_p.h 2018-09-19 23:53:06.000000000 +0200 +++ pure-ftpd-1.0.49/src/log_extauth_p.h 2019-06-10 11:15:04.449947766 +0200 @@ -34,6 +34,7 @@ static void callback_reply_ratio_upload(const char *str, AuthResult * const result); static void callback_reply_ratio_download(const char *str, AuthResult * const result); static void callback_reply_per_user_max(const char *str, AuthResult * const result); +static void callback_reply_apparmor_hat(const char *str, AuthResult * const result); static void callback_reply_end(const char *str, AuthResult * const result); static ExtauthCallBack extauth_callbacks[] = { @@ -49,6 +50,7 @@ { EXTAUTH_REPLY_RATIO_UPLOAD, callback_reply_ratio_upload }, { EXTAUTH_REPLY_RATIO_DOWNLOAD, callback_reply_ratio_download }, { EXTAUTH_REPLY_PER_USER_MAX, callback_reply_per_user_max }, + { EXTAUTH_REPLY_APPARMOR_HAT, callback_reply_apparmor_hat }, { EXTAUTH_REPLY_END, callback_reply_end }, { NULL, callback_reply_end } }; diff -ur pure-ftpd-1.0.49.org/src/log_ldap.c pure-ftpd-1.0.49/src/log_ldap.c --- pure-ftpd-1.0.49.org/src/log_ldap.c 2019-04-02 16:00:40.000000000 +0200 +++ pure-ftpd-1.0.49/src/log_ldap.c 2019-06-10 11:13:52.184467185 +0200 @@ -635,6 +635,9 @@ if ((result->dir = strdup(pw->pw_dir)) == NULL) { return; } +#ifdef APPARMOR + result->apparmor_hat = NULL; +#endif result->slow_tilde_expansion = 1; result->auth_ok = 1; /* User found, authentication ok */ } diff -ur pure-ftpd-1.0.49.org/src/log_mysql.c pure-ftpd-1.0.49/src/log_mysql.c --- pure-ftpd-1.0.49.org/src/log_mysql.c 2019-06-10 11:13:16.126728032 +0200 +++ pure-ftpd-1.0.49/src/log_mysql.c 2019-06-10 11:13:52.184467185 +0200 @@ -332,6 +332,9 @@ const char *bandwidth_ul = NULL; /* stored bandwidth UL */ const char *bandwidth_dl = NULL; /* stored bandwidth DL */ #endif +#ifdef APPARMOR + const char *apparmor_hat = NULL; /* Apparmor hat name */ +#endif char *escaped_account = NULL; char *escaped_ip = NULL; char *escaped_port = NULL; @@ -620,6 +623,15 @@ } } #endif +#ifdef APPARMOR + if ((apparmor_hat = pw_mysql_getquery(id_sql_server, sqlreq_getapparmor_hat, + escaped_account, escaped_ip, + escaped_port, escaped_peer_ip, + escaped_decimal_ip)) != NULL) { + result->apparmor_hat = apparmor_hat; + apparmor_hat = NULL; + } +#endif result->slow_tilde_expansion = !tildexp; result->auth_ok = -result->auth_ok; bye: @@ -649,6 +661,9 @@ free((void *) bandwidth_ul); free((void *) bandwidth_dl); #endif +#ifdef APPARMOR + free((void *) apparmor_hat); +#endif free((void *) escaped_account); free((void *) escaped_ip); free((void *) escaped_port); @@ -717,6 +732,9 @@ ZFREE(sqlreq_getbandwidth_ul); ZFREE(sqlreq_getbandwidth_dl); #endif +#ifdef APPARMOR + ZFREE(sqlreq_getapparmor_hat); +#endif } #else extern signed char v6ready; diff -ur pure-ftpd-1.0.49.org/src/log_mysql_p.h pure-ftpd-1.0.49/src/log_mysql_p.h --- pure-ftpd-1.0.49.org/src/log_mysql_p.h 2018-09-19 23:53:06.000000000 +0200 +++ pure-ftpd-1.0.49/src/log_mysql_p.h 2019-06-10 11:13:52.184467185 +0200 @@ -38,6 +38,9 @@ static char *sqlreq_getbandwidth_ul; static char *sqlreq_getbandwidth_dl; #endif +#ifdef APPARMOR +static char *sqlreq_getapparmor_hat; +#endif static signed char server_down; static ConfigKeywords mysql_config_keywords[] = { @@ -68,6 +71,9 @@ { "MYSQLGetBandwidthUL", &sqlreq_getbandwidth_ul }, { "MYSQLGetBandwidthDL", &sqlreq_getbandwidth_dl }, #endif +#ifdef APPARMOR + { "MYSQLGetApparmorHat", &sqlreq_getapparmor_hat }, +#endif { NULL, NULL } }; diff -ur pure-ftpd-1.0.49.org/src/log_pam.c pure-ftpd-1.0.49/src/log_pam.c --- pure-ftpd-1.0.49.org/src/log_pam.c 2019-04-02 16:00:40.000000000 +0200 +++ pure-ftpd-1.0.49/src/log_pam.c 2019-06-10 11:13:52.184467185 +0200 @@ -202,6 +202,9 @@ (void) pam_close_session(pamh, PAM_SILENT); /* It doesn't matter if it fails */ #endif result->dir = dir; +#ifdef APPARMOR + result->apparmor_hat = NULL; +#endif dir = NULL; result->uid = pw.pw_uid; result->gid = pw.pw_gid; diff -ur pure-ftpd-1.0.49.org/src/log_pgsql.c pure-ftpd-1.0.49/src/log_pgsql.c --- pure-ftpd-1.0.49.org/src/log_pgsql.c 2019-06-10 11:13:16.120061167 +0200 +++ pure-ftpd-1.0.49/src/log_pgsql.c 2019-06-10 11:13:52.184467185 +0200 @@ -402,6 +402,9 @@ const char *bandwidth_ul = NULL; /* stored bandwidth UL */ const char *bandwidth_dl = NULL; /* stored bandwidth DL */ #endif +#ifdef APPARMOR + const char *apparmor_hat = NULL; /* Apparmor hat name */ +#endif char *escaped_account = NULL; char *escaped_ip = NULL; char *escaped_port = NULL; @@ -662,6 +665,15 @@ } } #endif +#ifdef APPARMOR + if ((apparmor_hat = pw_pgsql_getquery(id_sql_server, sqlreq_getapparmor_hat, + escaped_account, escaped_ip, + escaped_port, escaped_peer_ip, + escaped_decimal_ip)) != NULL) { + result->apparmor_hat = apparmor_hat; + apparmor_hat = NULL; + } +#endif result->slow_tilde_expansion = 1; result->auth_ok = -result->auth_ok; bye: @@ -692,6 +704,9 @@ free((void *) bandwidth_ul); free((void *) bandwidth_dl); #endif +#ifdef APPARMOR + free((void *) apparmor_hat); +#endif free((void *) escaped_account); free((void *) escaped_ip); free((void *) escaped_port); @@ -746,6 +761,9 @@ ZFREE(sqlreq_getbandwidth_ul); ZFREE(sqlreq_getbandwidth_dl); #endif +#ifdef APPARMOR + ZFREE(sqlreq_getapparmor_hat); +#endif } #else extern signed char v6ready; diff -ur pure-ftpd-1.0.49.org/src/log_pgsql_p.h pure-ftpd-1.0.49/src/log_pgsql_p.h --- pure-ftpd-1.0.49.org/src/log_pgsql_p.h 2018-09-19 23:53:06.000000000 +0200 +++ pure-ftpd-1.0.49/src/log_pgsql_p.h 2019-06-10 11:13:52.184467185 +0200 @@ -28,6 +28,9 @@ static char *sqlreq_getbandwidth_ul; static char *sqlreq_getbandwidth_dl; #endif +#ifdef APPARMOR +static char *sqlreq_getapparmor_hat; +#endif static signed char server_down; static ConfigKeywords pgsql_config_keywords[] = { @@ -55,6 +58,9 @@ { "PGSQLGetBandwidthUL", &sqlreq_getbandwidth_ul }, { "PGSQLGetBandwidthDL", &sqlreq_getbandwidth_dl }, #endif +#ifdef APPARMOR + { "PGSQLGetApparmorHat", &sqlreq_getapparmor_hat }, +#endif { NULL, NULL } }; diff -ur pure-ftpd-1.0.49.org/src/log_puredb.c pure-ftpd-1.0.49/src/log_puredb.c --- pure-ftpd-1.0.49.org/src/log_puredb.c 2019-04-02 16:00:40.000000000 +0200 +++ pure-ftpd-1.0.49/src/log_puredb.c 2019-06-10 11:13:52.187800617 +0200 @@ -335,6 +335,9 @@ result->user_quota_size = strtoull(line, NULL, 10); } #endif +#ifdef APPARMOR + result->apparmor_hat = NULL; +#endif if ((line = my_strtok2(NULL, *PW_LINE_SEP)) == NULL) { /* allowed local ip */ return 0; } diff -ur pure-ftpd-1.0.49.org/src/log_unix.c pure-ftpd-1.0.49/src/log_unix.c --- pure-ftpd-1.0.49.org/src/log_unix.c 2019-04-02 16:00:40.000000000 +0200 +++ pure-ftpd-1.0.49/src/log_unix.c 2019-06-10 11:13:52.187800617 +0200 @@ -87,6 +87,9 @@ result->uid = pw.pw_uid; result->gid = pw.pw_gid; result->dir = dir; +#ifdef APPARMOR + result->apparmor_hat = NULL; +#endif result->slow_tilde_expansion = 0; result->auth_ok = -result->auth_ok; return; diff -ur pure-ftpd-1.0.49.org/src/Makefile.am pure-ftpd-1.0.49/src/Makefile.am --- pure-ftpd-1.0.49.org/src/Makefile.am 2019-03-25 16:48:42.000000000 +0100 +++ pure-ftpd-1.0.49/src/Makefile.am 2019-06-10 11:13:52.187800617 +0200 @@ -143,6 +143,7 @@ pure_ftpd_LDADD = \ libpureftpd.a \ ../puredb/src/libpuredb_read.a \ + -lapparmor \ @LDAP_SSL_LIBS@ @GETLOADAVG_LIBS@ @BONJOUR_LDADD@ pure_ftpd_SOURCES = \ diff -ur pure-ftpd-1.0.49.org/src/messages_en.h pure-ftpd-1.0.49/src/messages_en.h --- pure-ftpd-1.0.49.org/src/messages_en.h 2019-06-10 11:13:16.126728032 +0200 +++ pure-ftpd-1.0.49/src/messages_en.h 2019-06-10 11:13:52.187800617 +0200 @@ -57,6 +57,7 @@ #define MSG_CURRENT_DIR_IS "OK. Current directory is %s" #define MSG_CURRENT_RESTRICTED_DIR_IS "OK. Current restricted directory is %s" #define MSG_IS_NOW_LOGGED_IN "%s is now logged in" +#define MSG_APPARMOR_HAT "User %s apparmor hat is %s" #define MSG_CANT_CHANGE_DIR "Can't change directory to %s" #define MSG_PATH_TOO_LONG "Path too long" #define MSG_CANT_PASV "You cannot use PASV on IPv6 connections. Use EPSV instead."