blob: 8ec9f0e3e218e4c98c813fdf05c4ebf33eb0dd15 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
You need to add the following (or equivalent) to the
/etc/pam.d/ranger-remote file:
# check authorization
auth required pam_unix.so
account required pam_unix.so
*/
#include <stdio.h>
#include <stdarg.h>
#include <unistd.h>
#include <stdlib.h>
#include <pwd.h>
#include <string.h>
#include <sys/types.h>
#include <security/pam_appl.h>
#define STRLEN 64
int pamconv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) {
if (num_msg != 1 || msg[0]->msg_style != PAM_PROMPT_ECHO_OFF) {
fprintf(stderr, "ERROR: Unexpected PAM conversation '%d/%s'\n", msg[0]->msg_style, msg[0]->msg);
return PAM_CONV_ERR;
}
if (!appdata_ptr) {
fprintf(stderr, "ERROR: No password available to conversation!\n");
return PAM_CONV_ERR;
}
*resp = calloc(num_msg, sizeof(struct pam_response));
if (!*resp) {
fprintf(stderr, "ERROR: Out of memory!\n");
return PAM_CONV_ERR;
}
(*resp)[0].resp = strdup((char *) appdata_ptr);
(*resp)[0].resp_retcode = 0;
return ((*resp)[0].resp ? PAM_SUCCESS : PAM_CONV_ERR);
}
struct pam_conv conv = { pamconv, NULL };
int main(int ac, char **av, char **ev)
{
char username[STRLEN] ;
char password[STRLEN] ;
char line[512] ;
char format[20];
int retval;
pam_handle_t *pamh = NULL;
sprintf(format, "LOGIN:%%%ds %%%ds", STRLEN-1, STRLEN-1);
fgets(line,512,stdin) ;
sscanf(line, format, username,password) ;
conv.appdata_ptr = (char *) password;
retval = pam_start("ranger-remote", username, &conv, &pamh);
if (retval != PAM_SUCCESS) {
/* why expose this? */
fprintf(stdout, "FAILED: [%s] does not exists.\n", username) ;
if (pamh) {
pam_end(pamh, retval);
}
exit(1);
}
retval = pam_authenticate(pamh, 0);
if (retval != PAM_SUCCESS) {
fprintf(stdout, "FAILED: Password did not match(%s).\n", pam_strerror(pamh, retval)) ;
if (pamh) {
pam_end(pamh, retval);
}
exit(1);
}
/* authorize */
retval = pam_acct_mgmt(pamh, 0);
if (retval != PAM_SUCCESS) {
fprintf(stdout, "FAILED: [%s] is not authorized.\n", username) ;
if (pamh) {
pam_end(pamh, retval);
}
exit(1);
}
/* establish the requested credentials */
if ((retval = pam_setcred(pamh, PAM_ESTABLISH_CRED)) != PAM_SUCCESS) {
fprintf(stdout, "FAILED: Error setting credentials for [%s].\n", username) ;
if (pamh) {
pam_end(pamh, retval);
}
exit(1);
}
/* not opening a session, as logout has not been implemented as a remote service */
fprintf(stdout, "OK:\n") ;
if (pamh) {
pam_end(pamh, retval);
}
exit(0) ;
}