Initial version of the patches
[transmission-rpc-pam.git] / libtransmission-native-auth.c.patch
1 Index: libtransmission/native-auth.c
2 ===================================================================
3 --- libtransmission/native-auth.c       (revision 0)
4 +++ libtransmission/native-auth.c       (revision 0)
5 @@ -0,0 +1,158 @@
6 +/******************************************************************************
7 + * $Id:$
8 + *
9 + * Copyright (c) Transmission authors and contributors
10 + *
11 + * Permission is hereby granted, free of charge, to any person obtaining a
12 + * copy of this software and associated documentation files (the "Software"),
13 + * to deal in the Software without restriction, including without limitation
14 + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 + * and/or sell copies of the Software, and to permit persons to whom the
16 + * Software is furnished to do so, subject to the following conditions:
17 + *
18 + * The above copyright notice and this permission notice shall be included in
19 + * all copies or substantial portions of the Software.
20 + *
21 + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22 + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24 + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 + * DEALINGS IN THE SOFTWARE.
28 + *****************************************************************************/
29 +
30 +#include "native-auth.h"
31 +
32 +
33 +#if defined(HAVE_NATIVE_AUTH_ENABLED) && defined(linux)
34 + #define  NATIVE_AUTH_ENABLED 1
35 +
36 + #include "transmission.h"
37 + #include "utils.h"
38 +
39 + #include <assert.h>
40 + #include <string.h>
41 +
42 + #include <security/pam_appl.h>
43 +#endif
44 +
45 +#if defined(NATIVE_AUTH_ENABLED)
46 +static struct pam_response *
47 +makePAMResponse( const char * data )
48 +{
49 +    struct pam_response * response = ( struct pam_response * )tr_malloc( sizeof( struct pam_response ) );
50 +    if ( !response )
51 +    {
52 +        tr_err( _("Cannot allocate memory for PAM response") );
53 +        return NULL;
54 +    }
55 +
56 +    response->resp_retcode = PAM_SUCCESS;
57 +       response->resp = strdup( data );
58 +
59 +    return response;
60 +}
61 +
62 +static int
63 +pamAuthConversation( int numMsg,
64 +                     const struct pam_message ** messages,
65 +                     struct pam_response ** responses,
66 +                     void * data )
67 +{
68 +    int msgIndex;
69 +       bool errorOccurred = false;
70 +
71 +    assert( data );
72 +
73 +    *responses = (struct pam_response *)tr_malloc0( numMsg*sizeof( struct pam_response ) );
74 +    if ( !*responses )
75 +    {
76 +        return PAM_CONV_ERR;
77 +    }
78 +
79 +    for( msgIndex = 0; msgIndex < numMsg && !errorOccurred; ++msgIndex )
80 +    {
81 +        const struct pam_message * msg = *messages++;
82 +        switch( msg->msg_style )
83 +               {
84 +            case PAM_PROMPT_ECHO_OFF:
85 +            case PAM_PROMPT_ECHO_ON:
86 +            {
87 +                const char * password = (char *)data;
88 +                struct pam_response * response = makePAMResponse( password );
89 +
90 +                if ( !response )
91 +                    errorOccurred = true;
92 +                else
93 +                    responses[msgIndex] = response;
94 +
95 +                break;
96 +            }
97 +
98 +            case PAM_TEXT_INFO:
99 +                break;
100 +
101 +            default:
102 +                errorOccurred = true;
103 +                tr_err( _("Error while PAM conversation occurred") );
104 +        }
105 +    }
106 +
107 +    if( errorOccurred )
108 +    {
109 +        tr_free( *responses );
110 +        return PAM_CONV_ERR;
111 +    }
112 +
113 +    return PAM_SUCCESS;
114 +}
115 +
116 +static void
117 +performPAMAuthentication( const char * user, const char * password, bool * isSuccess )
118 +{
119 +    const char * PAM_AUTH_MODULE = "auth"; 
120 +    struct pam_conv pamConversation = { pamAuthConversation, (void *) password };
121 +    int pamError = 0;
122 +    pam_handle_t * pamHandle = NULL;
123 +
124 +    *isSuccess = false;
125 +               
126 +    pamError = pam_start( PAM_AUTH_MODULE, user, &pamConversation, &pamHandle );
127 +    if ( PAM_SUCCESS != pamError )
128 +    {
129 +        tr_err( _( "Failed to start PAM session: %s" ), pam_strerror( pamHandle, pamError ) );
130 +        return;
131 +    }
132 +
133 +    pamError = pam_authenticate( pamHandle, PAM_SILENT );
134 +    if ( PAM_SUCCESS == pamError )
135 +        *isSuccess = true;
136 +    else
137 +        pamError = pam_end( pamHandle, /* last status */ 0 );
138 +
139 +    if ( PAM_SUCCESS != pamError )
140 +    {
141 +        tr_err( _( "Failed to close PAM session: %s" ), pam_strerror( pamHandle, pamError ) );
142 +    }
143 +}
144 +#endif
145 +
146 +void
147 +tr_performNativeAuthentication( const char * user, const char * password, tr_rpcNativeAuthenticationResult * result )
148 +{
149 +    bool isSuccessAuth = false;
150 +
151 +#ifdef HAVE_NATIVE_AUTH_ENABLED
152 +
153 +#if defined(linux)
154 +    performPAMAuthentication( user, password, &isSuccessAuth );        
155 +#else
156 +    #warning Native user authentication for this platform is not supported yet.
157 +#endif
158 +
159 +#endif /* HAVE_NATIVE_AUTH_ENABLED */
160 +
161 +    *result = ( isSuccessAuth ) ? NATIVE_AUTHENTICATON_SUCCESS : NATIVE_AUTHENTICATON_FAIL;
162 +}
163 +