On Wed, Jan 13, 2016 at 12:42:31PM +0100, 'Oleg Ponomarev' via ganeti-devel 
wrote:
> As proposed in doc/design-rapi-pam.rst, implement ValidateRequest
> function that interacts with PAM in order to perform authentication
> and then authorization.
> 
> Signed-off-by: Oleg Ponomarev <[email protected]>
> ---
>  Makefile.am             |   1 +
>  lib/errors.py           |   6 +
>  lib/rapi/auth/pam.py    | 366 
> ++++++++++++++++++++++++++++++++++++++++++++++++
>  src/Ganeti/Constants.hs |   7 +
>  4 files changed, 380 insertions(+)
>  create mode 100644 lib/rapi/auth/pam.py

> diff --git a/lib/rapi/auth/pam.py b/lib/rapi/auth/pam.py
> new file mode 100644
> index 0000000..edecbab
> --- /dev/null
> +++ b/lib/rapi/auth/pam.py
> @@ -0,0 +1,366 @@
> +#
> +#
> +
> +# Copyright (C) 2015 Google Inc.

s/2015/2015, 2016/

> +# All rights reserved.
> +#


> +def ValidateRequest(cf, username, uri_access_rights, password=None,
> +                    service=DEFAULT_SERVICE_NAME, authtok=None, uri=None,
> +                    method=None, body=None):
> +  """Checks whether it's permitted to execute an rapi request.
> +
> +  Calls pam_authenticate and then pam_acct_mgmt in order to check whether a
> +  request should be executed.
> +
> +  @param cf: An instance of CFunctions class containing necessary imports
> +  @param username: username
> +  @param uri_access_rights: handler access rights
> +  @param password: password
> +  @param service: a service name that will be used for the interaction with 
> PAM
> +  @param authtok: user's authentication token (e.g. some kind of signature)
> +  @param uri: an uri of a target resource obtained from an http header
> +  @param method: http method trying to access the uri
> +  @param body: a body of an RAPI request
> +
> +  """
> +  ValidateParams(username, uri_access_rights, password, service, authtok, 
> uri,
> +                 method, body)
> +
> +  def ConversationFunction(num_msg, msg, resp, _app_data_ptr):
> +    """Conversation function that will be provided to PAM modules.
> +
> +    The function replies with a password for each message with
> +    PAM_PROMPT_ECHO_OFF style and just ignores the others.
> +
> +    """
> +    if num_msg > MAX_MSG_COUNT:
> +      logging.info("Too many messages passed to conv function: [%d]", 
> num_msg)
> +      return PAM_BUF_ERR
> +    response = cf.calloc(num_msg, c.sizeof(PamResponse))
> +    if not response:
> +      logging.info("calloc failed in conv function")

s/info/warning/

> +      return PAM_BUF_ERR
> +    resp[0] = c.cast(response, c.POINTER(PamResponse))
> +    for i in range(num_msg):
> +      if msg[i].contents.msg_style != PAM_PROMPT_ECHO_OFF:
> +        continue
> +      resp.contents[i].resp = cf.strndup(password, len(password))
> +      if not resp.contents[i].resp:
> +        logging.info("strndup failed in conv function")

s/info/warning/

> +        for j in range(i):
> +          cf.free(c.cast(resp.contents[j].resp, c.c_void_p))
> +        cf.free(response)
> +        return PAM_BUF_ERR
> +      resp.contents[i].resp_retcode = 0
> +    return PAM_SUCCESS
> +
> +  pam_handle = PamHandleT()
> +  conv = PamConv(CONV_FUNC(ConversationFunction), 0)
> +  ret = cf.pam_start(service, username, c.pointer(conv), 
> c.pointer(pam_handle))
> +  if ret != PAM_SUCCESS:
> +    cf.pam_end(pam_handle, ret)
> +    raise http.HttpInternalServerError("pam_start call failed [%d]" % ret)
> +
> +  Authenticate(cf, pam_handle, authtok)
> +  Authorize(cf, pam_handle, uri_access_rights, uri, method, body)
> +
> +  cf.pam_end(pam_handle, PAM_SUCCESS)

Rest LGTM

-- 
Klaus Aehlig
Google Germany GmbH, Dienerstr. 12, 80331 Muenchen
Registergericht und -nummer: Hamburg, HRB 86891
Sitz der Gesellschaft: Hamburg
Geschaeftsfuehrer: Matthew Scott Sucherman, Paul Terence Manicle

Reply via email to