指定されたユーザー名を追加して、sshを介して呼び出されるプロセスにデータをインポートしようとしています。
ssh user@smuggledata@host
私はPAMモジュールを書いたが、
- sshd は、PAM を呼び出す前にユーザーが悪いユーザーであることを確認しました。
- PAM_USERを変更しましたが、後続のモジュールは依然として送信されたユーザー名に基づいて認証します。
auth requisite mymodule.so
まず、 と のコードを使ってコードを実行してみましたpam_sm_authenticate()
。コードがトリガーされましたが動作しません。
May 1 22:40:30 animal sshd[3827]: Invalid user colin@example from 127.0.0.1
May 1 22:40:30 animal sshd[3827]: input_userauth_request: invalid user colin@example [preauth]
May 1 22:40:35 animal pam_pat[3827]: Retrieved username colin@example
May 1 22:40:35 animal pam_pat[3827]: checking char c against 3 dividers
May 1 22:40:35 animal pam_pat[3827]: checking char o against 3 dividers
May 1 22:40:35 animal pam_pat[3827]: checking char l against 3 dividers
May 1 22:40:35 animal pam_pat[3827]: checking char i against 3 dividers
May 1 22:40:35 animal pam_pat[3827]: checking char n against 3 dividers
May 1 22:40:35 animal pam_pat[3827]: checking char @ against 3 dividers
May 1 22:40:35 animal pam_pat[3827]: Found divider @
May 1 22:40:35 animal pam_pat[3827]: user=colin, data=example
May 1 22:40:35 animal sshd[3827]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=127.0.0.1 user=colin
May 1 22:40:37 animal sshd[3827]: Failed password for invalid user colin@example from 127.0.0.1 port 43998 ssh2
May 1 22:41:28 animal sshd[3827]: Connection closed by 127.0.0.1 port 43998 [preauth]
実行がpam_unixに達すると認証は失敗しますが、ユーザーはPAM_USERに変換された値として報告されます。パスワードが正しいため、pam_unixがPAM_USERに対して認証されない可能性があります。
account requisite mymodule.so
また、コードを試しましたが、pam_sm_acct_mgmt()
コードは呼び出されませんでした。
May 1 22:57:10 animal sshd[4105]: Invalid user colin@exmple from 127.0.0.1
May 1 22:57:10 animal sshd[4105]: input_userauth_request: invalid user colin@exmple [preauth]
May 1 22:57:16 animal sshd[4105]: pam_unix(sshd:auth): check pass; user unknown
May 1 22:57:16 animal sshd[4105]: pam_unix(sshd:auth): authentication failure; logname= uid=0 euid=0 tty=ssh ruser= rhost=127.0.0.1
May 1 22:57:18 animal sshd[4105]: Failed password for invalid user colin@exmple from 127.0.0.1 port 44118 ssh2
May 1 22:57:27 animal sshd[4105]: Connection closed by 127.0.0.1 port 44118 [preauth]
見ているpam_unixのソースコード検索されたユーザー名は、pam_get_user()
明らかにPAM_USER以外の名前を指します。
その後、認証に使用されるユーザー値をどのように変更しますか?
- ユーザー名を別の方法で処理する前にこれが発生するかどうかを確認できますか?
- pam_get_user()が返したポインタを書き換えるよりも良い方法はありますか?
修正する コード(pam_get_user()追加):
char *submitted_name;
char work_bufr[PAT_BUFR];
char log_entry[PAT_BUFR];
int an_int;
char dividers[]="@%+";
int num_dividers;
char *cursor;
char divider_found[]="0";
const char *debug_user;
openlog("pam_pat", LOG_CONS | LOG_PID | LOG_NDELAY, LOG_AUTH);
/* retrieve a copy of the submitted username */
if (PAM_SUCCESS != pam_get_item(pamh, PAM_USER, (void *) &submitted_name) || !(submitted_name)) {
syslog (LOG_ERR, "Failed to retrieve username from pam");
closelog();
return(PAM_IGNORE);
}
syslog (LOG_ERR, "Retrieved username %s", submitted_name);
strncpy(work_bufr, submitted_name, PAT_BUFR);
submitted_name=work_bufr;
/* search for dividers and split string */
cursor=submitted_name;
an_int=PAT_BUFR;
num_dividers=(int)strlen(dividers);
while (--an_int && '\0'!=*cursor) {
syslog(LOG_ERR, "checking char %c against %d dividers", (int)*cursor, num_dividers);
for (int x=0; x<num_dividers; x++) {
if (*cursor==dividers[x]) {
syslog(LOG_ERR, "Found divider %c", *cursor);
an_int=0;
*divider_found=*cursor;
*cursor='\0';
if (PAM_SUCCESS==pam_set_item(pamh, PAM_USER, submitted_name)) {
++cursor;
syslog (LOG_ERR, "user=%s, data=%s",submitted_name,cursor);
setenv("PAM_PAT_DIVDR", divider_found, 1);
setenv("PAM_PAT_DATA", cursor, 1);
if (PAM_SUCCESS == pam_get_user(pamh, &debug_user, NULL)) {
syslog (LOG_ERR, "pam_get_user() found %s", debug_user);
}
closelog();
return(PAM_IGNORE);
} else {
syslog (LOG_ERR, "Failed to update username");
}
}
}
cursor++;
}
syslog (LOG_ERR, "Extended username not found.");
closelog();
return(PAM_IGNORE);
}
答え1
input_userauth_request() は、ユーザー名を求める sshd の関数です。
以下について前後にお読みください。pam_ldap(ローカルシステムは認証されているユーザー名は必ずしもわかりません。)LDAP NSSライブラリがインストールまたは構成されていない場合は、「sshd [xxx]:input_userauth_request:無効なユーザー...」というメッセージが表示されます。これから、私はsshdがPAM(WTF?)に引き渡される前に最初にユーザー名を解決しようとすると推測します。したがって、この初期エラーを回避するにはNSSモジュールを作成する必要があります(おそらくgetpwnam()を実装しますが、どのように機能するかを知るにはsshdを分離する必要があります)。
よく!
(まだこれが問題を解決できるかどうかはわかりません)
答え2
古いスレッドですが、完全な答えを整理したかったです。
私も同様の要件があり、ここで言及されているものをほとんど使用してソリューションをまとめました。
libnss-ato
- 存在しないユーザーを引き続き許可するために必要です。 (以前にもこの方法を使用したことがあります。)PAM_SUCCESS
以下を除いて、単純なPAMモジュール(主に返された仮想関数)を作成しました。
static char*
_find_base_user (const char *user)
{
char *p = NULL;
static char user_base[64] = {0};
if ((p = strchr(user, '@'))) {
memset(user_base, 0, 64);
strncpy(user_base, user, (int)(p - user));
return user_base;
}
return NULL;
}
int
pam_sm_authenticate (pam_handle_t *pamh,
int flags,
int argc,
const char **argv)
{
int ret = 0;
const char *user;
char *user_pfx = NULL;
ret = pam_get_user(pamh, &user, NULL);
if (ret != PAM_SUCCESS || user == NULL) {
pam_syslog(pamh, LOG_ERR, "no user specified");
} else {
pam_syslog(pamh, LOG_DEBUG, "user = %s", user);
}
user_pfx = _find_base_user(user);
if (user_pfx) {
pam_syslog(pamh, LOG_DEBUG, "user base name: %s", user_pfx);
} else {
pam_syslog(pamh, LOG_ERR, "no separator in user name found");
return PAM_SUCCESS;
}
ret = pam_set_item(pamh, PAM_USER, (const void *)user_pfx);
if (ret!= PAM_SUCCESS) {
pam_syslog(pamh, LOG_ERR, "user resetting failed");
return PAM_USER_UNKNOWN;
}
return PAM_SUCCESS;
}
これを呼び出しpam_changeuser.so
て、PAMスタック(最初のモジュール)の一番上に追加します。
auth required pam_changeuser.so
これで私はできる密輸一部追加資料ユーザー名で!
これが誰かに役立つことを願っています。
-
答え3
のマニュアルページには、pam_get_user(3)
ユーザーから値を取得すると記載されていますpam_start(3)
。この関数は、その構造の要素を設定するために使用できますpam_set_item(3)
。 3番目の機能のマニュアルページは、認証がテストされるユーザー名を変更するための明確な参照を提供します。
この
pam_set_item
機能を使用すると、アプリケーションとPAMサービスモジュールがアクセスして更新できますitem_type
。これを行うには、アイテムパラメータが指すオブジェクトのコピーを作成します。次のitem_typesがサポートされています[...]PAM_user IDサービスを提供するエンティティのユーザー名。つまり、認証後、PAM_USER はサービスの使用を開始するローカルエンティティを識別します。この値は、PAMスタック内のすべてのモジュールによって何か(たとえば「anonymous」)から他の値(たとえば「guest119」)にマッピングできます。したがって、アプリケーションはPAM関数を呼び出すたびにPAM_USER値を参照する必要があります。