/*
 * Copyright (c) 2009, 2018 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0, which is available at
 * http://www.eclipse.org/legal/epl-2.0.
 *
 * This Source Code may also be made available under the following Secondary
 * Licenses when the conditions for such availability set forth in the
 * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
 * version 2 with the GNU Classpath Exception, which is available at
 * https://www.gnu.org/software/classpath/license.html.
 *
 * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
 */

package org.jvnet.libpam.impl;

import static org.jvnet.libpam.impl.CLibrary.libc;

import java.util.Arrays;
import java.util.List;

import com.sun.jna.Callback;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Pointer;
import com.sun.jna.PointerType;
import com.sun.jna.Structure;
import com.sun.jna.ptr.PointerByReference;

/**
 * libpam.so binding.
 *
 * See http://www.opengroup.org/onlinepubs/008329799/apdxa.htm for the online reference of pam_appl.h
 *
 * @author Kohsuke Kawaguchi
 */
public interface PAMLibrary extends Library {
    
    final int PAM_USER = 2;

    // error code
    final int PAM_SUCCESS = 0;
    final int PAM_CONV_ERR = 6;

    final int PAM_PROMPT_ECHO_OFF = 1; /* Echo off when getting response */
    final int PAM_PROMPT_ECHO_ON = 2; /* Echo on when getting response */
    final int PAM_ERROR_MSG = 3; /* Error message */
    final int PAM_TEXT_INFO = 4; /* Textual information */

    public static final PAMLibrary libpam = Native.loadLibrary("pam", PAMLibrary.class);
    
    
    class pam_handle_t extends PointerType {
        public pam_handle_t() {
        }

        public pam_handle_t(Pointer pointer) {
            super(pointer);
        }
    }

    class pam_message extends Structure {
        public int msg_style;
        public String msg;

        /**
         * Attach to the memory region pointed by the given pointer.
         */
        public pam_message(Pointer src) {
            useMemory(src);
            read();
        }

        @Override
        protected List getFieldOrder() {
            return Arrays.asList("msg_style", "msg");
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }

        public void setMsgStyle(int msg_style) {
            this.msg_style = msg_style;
        }
    }

    class pam_response extends Structure {
        
        public static final int SIZE = new pam_response().size();
        
        /**
         * This is really a string, but this field needs to be malloc-ed by the conversation method, and to be freed by the
         * caler, so I bind it to {@link Pointer} here.
         *
         * The man page doesn't say that, but see http://www.netbsd.org/docs/guide/en/chap-pam.html#pam-sample-conv This
         * behavior is confirmed with a test, too; if I don't do strdup, libpam crashes.
         */
        public Pointer resp;
        public int resp_retcode;

        /**
         * Attach to the memory region pointed by the given memory.
         */
        public pam_response(Pointer src) {
            useMemory(src);
            read();
        }

        public pam_response() {
        }

        /**
         * Sets the response code.
         */
        public void setResp(String msg) {
            this.resp = libc.strdup(msg);
        }

        protected Pointer getResp() {
            return resp;
        }

        public void setRespCode(int resp_retcode) {
            this.resp_retcode = resp_retcode;
        }

        public int getRespCode() {
            return resp_retcode;
        }

        @Override
        protected List getFieldOrder() {
            return Arrays.asList("resp", "resp_retcode");
        }
    }

    class pam_conv extends Structure {
        public interface PamCallback extends Callback {
            /**
             * According to http://www.netbsd.org/docs/guide/en/chap-pam.html#pam-sample-conv, resp and its member string both needs
             * to be allocated by malloc, to be freed by the caller.
             */
            int callback(int num_msg, Pointer msg, Pointer resp, Pointer pointer);
        }

        public PamCallback conv;
        public Pointer pointer;

        public pam_conv(PamCallback conv) {
            this.conv = conv;
        }

        @Override
        protected List getFieldOrder() {
            return Arrays.asList("conv", "pointer");
        }

        protected PamCallback getConv() {
            return conv;
        }
    }

    int pam_start(String service, String user, pam_conv conv, PointerByReference/* pam_handle_t** */ pamh_p);

    int pam_end(pam_handle_t handle, int pam_status);

    int pam_set_item(pam_handle_t handle, int item_type, String item);

    int pam_get_item(pam_handle_t handle, int item_type, PointerByReference item);

    int pam_authenticate(pam_handle_t handle, int flags);

    int pam_setcred(pam_handle_t handle, int flags);

    int pam_acct_mgmt(pam_handle_t handle, int flags);

    String pam_strerror(pam_handle_t handle, int pam_error);

    
}
