2011-05-06 29 views
8

Tôi có một ứng dụng cũ nhận được yêu cầu tên người dùng/mật khẩu không đồng bộ trên dây. Vì tôi đã có tên người dùng và mật khẩu được lưu trữ dưới dạng biến, cách nào là cách tốt nhất để xác thực với PAM trên Linux (Debian 6)?Xác thực PAM cho Ứng dụng kế thừa

Tôi đã thử viết chức năng hội thoại của riêng mình, nhưng tôi không chắc chắn cách tốt nhất để nhận mật khẩu vào đó. Tôi đã xem xét việc lưu trữ nó trong appdata và tham khảo từ cấu trúc pam_conv, nhưng hầu như không có tài liệu hướng dẫn về cách thực hiện điều đó.

Có cách nào đơn giản hơn để xác thực người dùng mà không có chức năng cuộc trò chuyện quá mức không? Tôi không thể sử dụng thành công pam_set_data, và tôi không chắc chắn điều đó có phù hợp hay không.

Đây là những gì tôi đang làm:

user = guiMessage->username; 
pass = guiMessage->password; 

pam_handle_t* pamh = NULL; 
int   pam_ret; 
struct pam_conv conv = { 
    my_conv, 
    NULL 
}; 

pam_start("nxs_login", user, &conv, &pamh); 
pam_ret = pam_authenticate(pamh, 0); 

if (pam_ret == PAM_SUCCESS) 
    permissions = 0xff; 

pam_end(pamh, pam_ret); 

Và ban đầu nỗ lực chức năng trò chuyện dẫn đến (mật khẩu được mã hóa cứng để thử nghiệm):

int 
my_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *data) 
{ 
    struct pam_response *aresp; 

    if (num_msg <= 0 || num_msg > PAM_MAX_NUM_MSG) 
    return (PAM_CONV_ERR); 
    if ((aresp = (pam_response*)calloc(num_msg, sizeof *aresp)) == NULL) 
    return (PAM_BUF_ERR); 
    aresp[0].resp_retcode = 0; 
    aresp[0].resp = strdup("mypassword"); 

    *resp = aresp; 
    return (PAM_SUCCESS); 
} 

Bất kỳ trợ giúp sẽ được đánh giá cao. Cảm ơn bạn!

Trả lời

12

Đây là những gì tôi đã kết thúc. Xem nhận xét được đánh dấu bằng ba dấu hoa thị.

#include <stdlib.h> 
#include <iostream> 
#include <fstream> 
#include <security/pam_appl.h> 
#include <unistd.h> 

// To build this: 
// g++ test.cpp -lpam -o test 

struct pam_response *reply; 

//function used to get user input 
int function_conversation(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) 
{ 
    *resp = reply; 
    return PAM_SUCCESS; 
} 

int main(int argc, char** argv) 
{ 
    if(argc != 2) { 
     fprintf(stderr, "Usage: check_user <username>\n"); 
     exit(1); 
    } 
    const char *username; 
    username = argv[1]; 

    const struct pam_conv local_conversation = { function_conversation, NULL }; 
    pam_handle_t *local_auth_handle = NULL; // this gets set by pam_start 

    int retval; 

    // local_auth_handle gets set based on the service 
    retval = pam_start("common-auth", username, &local_conversation, &local_auth_handle); 

    if (retval != PAM_SUCCESS) 
    { 
    std::cout << "pam_start returned " << retval << std::endl; 
    exit(retval); 
    } 

    reply = (struct pam_response *)malloc(sizeof(struct pam_response)); 

    // *** Get the password by any method, or maybe it was passed into this function. 
    reply[0].resp = getpass("Password: "); 
    reply[0].resp_retcode = 0; 

    retval = pam_authenticate(local_auth_handle, 0); 

    if (retval != PAM_SUCCESS) 
    { 
    if (retval == PAM_AUTH_ERR) 
    { 
     std::cout << "Authentication failure." << std::endl; 
    } 
    else 
    { 
     std::cout << "pam_authenticate returned " << retval << std::endl; 
    } 
    exit(retval); 
    } 

    std::cout << "Authenticated." << std::endl; 

    retval = pam_end(local_auth_handle, retval); 

    if (retval != PAM_SUCCESS) 
    { 
    std::cout << "pam_end returned " << retval << std::endl; 
    exit(retval); 
    } 

    return retval; 
} 
+0

Cảm ơn! Và ở đây tôi đã cố gắng tìm cách để giao tiếp _into_ chức năng hội thoại thay vì chỉ bỏ qua và làm việc với phản ứng bên ngoài nó. –

+0

Thao tác này không hoạt động đối với 'root' (chỉ là 'root', tất cả những người dùng khác đều được xác thực là tốt). Đó có phải là một lỗi không? – alexandernst

+0

Tôi không biết. Tôi đã không cố gắng root. Bạn có thể làm điều gì đó sai nếu bạn cần sử dụng mật khẩu gốc một cách thường xuyên. – Fantius

1

Cách thông tin tiêu chuẩn (chẳng hạn như mật khẩu) được truyền cho PAM là bằng cách sử dụng các biến đặt trong tay cầm pam với pam_set_item (xem man page của pam_set_item).

Bạn có thể đặt bất kỳ thứ gì mà ứng dụng của bạn sẽ cần sử dụng sau này vào pam_stack. Nếu bạn muốn đặt mật khẩu vào pam_stack bạn sẽ có thể để làm điều đó ngay lập tức sau khi gọi pam_start() bằng cách thiết lập các biến PAM_AUTHTOK vào ngăn xếp tương tự như mã giả dưới đây:

pam_handle_t* handle = NULL; 
pam_start("common-auth", username, NULL, &handle); 
pam_set_item(handle, PAM_AUTHTOK, password); 

này sẽ làm cho mật khẩu có sẵn trên ngăn xếp cho bất kỳ mô-đun nào quan tâm để sử dụng nó, nhưng thông thường bạn phải yêu cầu mô-đun sử dụng nó bằng cách đặt các tùy chọn use_first_pass hoặc try_first_pass chuẩn trong pam_configuration cho dịch vụ (trong trường hợp này là /etc/pam.d/ chung-auth).

Mô-đun pam_unix chuẩn hỗ trợ try_first_pass, do đó, sẽ không gây tổn thương khi thêm mô-đun vào cấu hình pam trên hệ thống của bạn (ở cuối dòng cho pam_unix).

Sau khi bạn thực hiện cuộc gọi này đến pam_authenticate() được gọi từ dịch vụ chung-auth, bạn chỉ cần chọn mật khẩu và tiếp tục với nó.

Một lưu ý nhỏ về sự khác nhau giữa use_first_pass và try_first_pass: Cả hai đều yêu cầu mô-đun (trong trường hợp này pam_unix) thử mật khẩu trên pam_stack, nhưng chúng khác nhau về hành vi khi không có mật khẩu/AUTHTOK. Trong trường hợp thiếu use_first_pass không thành công và try_first_pass cho phép mô-đun nhắc nhập mật khẩu.

+0

http://pubs.opengroup.org/onlinepubs/8329799/chap4.htm#tagcjh_05_02_01_01 đề cập rằng 'PAM_AUTHTOK' là" _only có sẵn cho mô-đun PAM chứ không phải cho ứng dụng_ ". Vì vậy, bạn sẽ không thể làm điều đó mà bạn mô tả. Bạn đã kiểm tra xem nó có hoạt động không? Có lẽ nó không nhưng không di động? –

+0

Sau đó, một lần nữa tài liệu 'pam_set_item' (http://pubs.opengroup.org/onlinepubs/8329799/pam_set_item.htm#tagmref_pam_set_item) dường như không lặp lại điều kiện đó khi nó cung cấp' PAM_AUTHOK'. –

0

Giải pháp Fantius 'có hiệu quả đối với tôi, thậm chí là gốc.

Ban đầu tôi chọn giải pháp của John vì nó sạch hơn và sử dụng biến PAM không có chức năng trò chuyện (thực sự, không cần thiết ở đây), nhưng không, và sẽ không hoạt động. Như Adam Badura ám chỉ trong cả hai bài viết, PAM có một số kiểm tra nội bộ để ngăn chặn thiết lập trực tiếp của PAM_AUTHTOK.

Giải pháp của John sẽ dẫn đến hành vi tương tự như được đề cập here, trong đó bất kỳ giá trị mật khẩu nào sẽ được phép đăng nhập (ngay cả khi bạn khai báo, nhưng không xác định, biến pam_conv).

Tôi cũng khuyên người dùng nên biết vị trí của malloc, vì nó có khả năng sẽ khác trong ứng dụng của bạn (hãy nhớ, mã ở trên có nhiều thử nghiệm/mẫu hơn bất kỳ thứ gì khác).

+0

Điều này không cung cấp câu trả lời cho câu hỏi. Khi bạn có đủ [danh tiếng] (https://stackoverflow.com/help/whats-reputation), bạn sẽ có thể [nhận xét về bất kỳ bài đăng nào] (https://stackoverflow.com/help/privileges/comment); thay vào đó, [cung cấp câu trả lời không yêu cầu làm rõ từ người hỏi] (https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can- i-do-thay thế). - [Từ đánh giá] (/ đánh giá/bài đăng chất lượng thấp/18803902) – Umair

+0

Vui lòng không thêm "cảm ơn" làm câu trả lời. Thay vào đó, hãy bỏ phiếu cho các câu trả lời mà bạn thấy hữu ích. - [Từ đánh giá] (/ review/low-quality-posts/18803902) – Graham

+0

cảm ơn vì đã nhắc tôi tại sao tôi là người bình thường trên các loại trang web này;) lời xin lỗi của tôi! – gagan

Các vấn đề liên quan