FEATURE initial python3 bindings commit

- integration into build system
- basic functionality to connect to the server and provide information
  about the NETCONF session
- no NETCONF operation (except the implicit close-session) supported yet
diff --git a/python/ssh.c b/python/ssh.c
new file mode 100644
index 0000000..a4c34a9
--- /dev/null
+++ b/python/ssh.c
@@ -0,0 +1,249 @@
+/**
+ * @file ssh.c
+ * @author Radek Krejci <rkrejci@cesnet.cz>
+ * @brief SSH parameters management
+ *
+ * Copyright (c) 2017 CESNET, z.s.p.o.
+ *
+ * This source code is licensed under BSD 3-Clause License (the "License").
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     https://opensource.org/licenses/BSD-3-Clause
+ */
+
+/* Python API header */
+#include <Python.h>
+#include <structmember.h>
+
+/* standard headers */
+#include <string.h>
+
+#include "netconf.h"
+
+static void
+ncSSHFree(ncSSHObject *self)
+{
+    Py_XDECREF(self->username); /* PyUnicode */
+    Py_XDECREF(self->password); /* PyUnicode */
+    Py_XDECREF(self->pubkeys);  /* PyList */
+    Py_XDECREF(self->privkeys); /* PyList */
+
+    Py_TYPE(self)->tp_free((PyObject*)self);
+}
+
+static int
+ncSSHInit(ncSSHObject *self, PyObject *args, PyObject *kwds)
+{
+    PyObject *user = NULL, *password = NULL;
+    PyObject *pubkey_path = NULL, *pubkey = NULL;
+    PyObject *privkey_path = NULL, *privkey = NULL;
+
+    char *kwlist[] = {"username", "password", "pubkey", "pubkey_file", "privkey", "privkey_file", NULL};
+
+    /* Get input parameters */
+    if (!PyArg_ParseTupleAndKeywords(args, kwds, "|UUUUUU", kwlist,
+                                     &user, &password,
+                                     &pubkey, &pubkey_path,
+                                     &privkey, &privkey_path)) {
+        return -1;
+    }
+
+    if ((pubkey || pubkey_path) != (privkey || privkey_path)) {
+        PyErr_SetString(PyExc_TypeError, "Both public and private keys must be set.");
+        goto error;
+    }
+
+    /* username and password */
+    if (user) {
+        Py_XDECREF(self->username);
+        Py_INCREF(user);
+        self->username = user;
+    }
+    if (password) {
+        Py_XDECREF(self->password);
+        Py_INCREF(password);
+        self->password = password;
+    }
+
+    /* keys */
+    Py_XDECREF(self->pubkeys);
+    Py_XDECREF(self->privkeys);
+
+    if (pubkey || pubkey_path) {
+        self->pubkeys = PyList_New(0);
+        self->privkeys = PyList_New(0);
+
+        if (!self->pubkeys || self->privkeys) {
+            PyErr_SetString(PyExc_MemoryError, "Unable to allocate memory for keys list.");
+            goto error;
+        }
+    } else {
+        self->pubkeys = NULL;
+        self->privkeys = NULL;
+    }
+
+    if (pubkey) {
+        PyList_Append(self->pubkeys, pubkey);
+    }
+    if (pubkey_path) {
+        /* process keys in the file */
+    }
+
+    if (privkey) {
+        PyList_Append(self->privkeys, privkey);
+    }
+    if (privkey_path) {
+        /* process keys in the file */
+    }
+
+    /* check that the keys pairs together */
+
+    return 0;
+
+error:
+
+    Py_CLEAR(self->username);
+    Py_CLEAR(self->password);
+    Py_CLEAR(self->pubkeys);
+    Py_CLEAR(self->privkeys);
+
+    return -1;
+}
+
+static PyObject *
+ncSSHStr(ncSSHObject *self)
+{
+    if (self->privkeys) {
+        if (self->username && self->password) {
+            return PyUnicode_FromFormat("SSH Settings with %d keys and password for user %U",
+                                        PyList_Size(self->privkeys), self->username);
+        } else if (self->password) {
+            return PyUnicode_FromFormat("SSH Settings with %d keys and password for default user.",
+                                        PyList_Size(self->privkeys));
+        } else {
+            return PyUnicode_FromFormat("SSH Settings with %d keys", PyList_Size(self->privkeys));
+        }
+    } else if (self->password) {
+        if (self->username) {
+            return PyUnicode_FromFormat("SSH Settings with password authentication for user %U.", self->username);
+        } else {
+            return PyUnicode_FromString("SSH Settings with password authentication for default user.");
+        }
+    } else if (self->username) {
+        return PyUnicode_FromFormat("SSH Settings for user %U.", self->username);
+    } else {
+        return PyUnicode_FromString("Default SSH Settings.");
+    }
+}
+
+/*
+ * tp_methods callbacks held by ncSessionMethods[]
+ */
+
+/*
+ * tp_getset callbacs held by ncSessionGetSetters[]
+ */
+static int
+ncSSHSetUser(ncSSHObject *self, PyObject *value, void *closure)
+{
+    if (!value) {
+        Py_XDECREF(self->username);
+    } else if (!PyUnicode_Check(value)) {
+        PyErr_SetString(PyExc_TypeError, "The attribute value must be a string.");
+        return -1;
+    } else {
+        Py_XDECREF(self->username);
+        Py_INCREF(value);
+    }
+    self->username = value;
+
+    return 0;
+}
+
+static PyObject *
+ncSSHGetUser(ncSSHObject *self, void *closure)
+{
+    Py_XINCREF(self->username);
+    return self->username;
+}
+
+static int
+ncSSHSetPassword(ncSSHObject *self, PyObject *value, void *closure)
+{
+    if (!value) {
+        Py_XDECREF(self->password);
+    } else if (!PyUnicode_Check(value)) {
+        PyErr_SetString(PyExc_TypeError, "The attribute value must be a string.");
+        return -1;
+    } else {
+        Py_XDECREF(self->password);
+        Py_INCREF(value);
+    }
+    self->password = value;
+
+    return 0;
+}
+
+/*
+ * Callback structures
+ */
+
+static PyGetSetDef ncSSHGetSetters[] = {
+    {"username", (getter)ncSSHGetUser, (setter)ncSSHSetUser, "SSH username.", NULL},
+    {"password", NULL, (setter)ncSSHSetPassword, "SSH password (or key passphrase).", NULL},
+    {NULL} /* Sentinel */
+};
+
+
+PyDoc_STRVAR(ncSSHDoc,
+             "Settings for SSH authentication\n"
+             "netconf2.SSH([user, password]) -> password authentication of the specified user\n"
+             "netconf2.SSH([user, password]) -> password authentication of the specified user\n"
+             "Arguments:\n"
+             "\thost         - address of the server (default localhost)\n"
+             "\tport         - port where to connect to (default 830)\n"
+             "\ttransport    - NETCONF transport protocol (default SSH), supported SSH or TLS\n");
+
+PyTypeObject ncSSHType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "netconf2.SSH",            /* tp_name */
+    sizeof(ncSSHObject),       /* tp_basicsize */
+    0,                         /* tp_itemsize */
+    (destructor)ncSSHFree,     /* tp_dealloc */
+    0,                         /* tp_print */
+    0,                         /* tp_getattr */
+    0,                         /* tp_setattr */
+    0,                         /* tp_reserved */
+    (reprfunc)ncSSHStr,        /* tp_repr */
+    0,                         /* tp_as_number */
+    0,                         /* tp_as_sequence */
+    0,                         /* tp_as_mapping */
+    0,                         /* tp_hash  */
+    0,                         /* tp_call */
+    (reprfunc)ncSSHStr,        /* tp_str */
+    0,                         /* tp_getattro */
+    0,                         /* tp_setattro */
+    0,                         /* tp_as_buffer */
+    Py_TPFLAGS_DEFAULT |
+        Py_TPFLAGS_BASETYPE,   /* tp_flags */
+    ncSSHDoc,                  /* tp_doc */
+    0,                         /* tp_traverse */
+    0,                         /* tp_clear */
+    0,                         /* tp_richcompare */
+    0,                         /* tp_weaklistoffset */
+    0,                         /* tp_iter */
+    0,                         /* tp_iternext */
+    0,                         /* tp_methods */
+    0,                         /* tp_members */
+    ncSSHGetSetters,           /* tp_getset */
+    0,                         /* tp_base */
+    0,                         /* tp_dict */
+    0,                         /* tp_descr_get */
+    0,                         /* tp_descr_set */
+    0,                         /* tp_dictoffset */
+    (initproc)ncSSHInit,       /* tp_init */
+    0,                         /* tp_alloc */
+    0,                         /* tp_new */
+};
+