Commit ffffb03b authored by Jan Koester's avatar Jan Koester
Browse files

signature support

parent 2a28540a
Loading
Loading
Loading
Loading
Loading
+3 −0
Changes for data/admin.html: 3 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -352,6 +352,9 @@ function editUserForm(uid) {
        html += '<tr><td><label>Windows Login:</label></td><td><input type="checkbox" id="eu_windowslogin"' + (data.windowslogin ? ' checked' : '') + '> <span class="hint">An: Konto wird Windows-Konto (vergibt SID + Kerberos, Passwort nötig). Aus: zurück zu Web-only.</span></td></tr>';
        html += '<tr><td><label>Passwort:</label></td><td><input type="password" name="pwhash" id="eu_password" placeholder="nur zum Aktivieren von Windows Login / Passwortwechsel"></td></tr>';
        html += '<tr><td><label>ProfilBild:</label></td><td><input type="file" name="avatar" id="eu_avatar"></td></tr>';
        html += '<tr><td><label>Unterschrift (PNG):</label></td><td><input type="file" name="signature" accept="image/png">'
             + (data.hassignature ? ' <label><input type="checkbox" name="removesignature" value="1"> entfernen</label>' : ' <span class="hint">keine hinterlegt</span>')
             + '</td></tr>';
        html += '<tr><td></td><td><input type="button" value="Save" onclick="submitEditUser(\'' + uid + '\')"></td></tr>';
        html += '</table></form>';
        setContent(html);
+49 −0
Changes for src/admin.cpp: 49 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -226,6 +226,9 @@ namespace fenrirds {
                try { af("mail", udat.getMail()); } catch (...) {}
                json_object_object_add(jobj, "fields", jfields);
                json_object_object_add(jobj, "windowslogin", json_object_new_boolean(false));
                std::vector<char> sig;
                udat.getSignature(sig);
                json_object_object_add(jobj, "hassignature", json_object_new_boolean(!sig.empty()));
                sendJson(curreq, jobj);
                json_object_put(jobj);
                return;
@@ -261,6 +264,7 @@ namespace fenrirds {
            addField("userprincipalname", e.str("userPrincipalName"));
            json_object_object_add(jobj, "fields", jfields);
            json_object_object_add(jobj, "windowslogin", json_object_new_boolean(!e.objectSid.empty()));
            json_object_object_add(jobj, "hassignature", json_object_new_boolean(!e.str("fenrirdsSignature").empty()));
            sendJson(curreq, jobj);
            json_object_put(jobj);
        }
@@ -377,6 +381,40 @@ namespace fenrirds {
            json_object_put(jobj);
        }

        /* ---- API: Get User Signature (raw PNG, 404 if none) ----
         * Deliberately behind the admin API, not public like /getavatar:
         * a signature image must not be fetchable by anyone knowing a uid. */
        void apiGetSignature(libhttppp::HttpRequest &curreq, const char *cdid, const char *cuid) {
            uuid::uuid uid;
            uid.parse(cuid);
            std::vector<char> sig;
            if (strcmp(cdid, "admin") == 0) {
                User user;
                class UserData udat(uid);
                size_t upos = sizeof(AuthHeader);
                user.info(_AdminBackend, udat, upos);
                udat.getSignature(sig);
            } else {
                std::string domain = domainNameFor(cdid);
                if (domain.empty() || !g_AdPlugin)
                    throw AuthBackendError("getSignature: no directory for domain!");
                dsdb::Entry e;
                std::string err;
                if (!g_AdPlugin->dirGet(domain, uid, e, err))
                    throw AuthBackendError("getSignature: " + err);
                std::string v = e.str("fenrirdsSignature");
                sig.assign(v.begin(), v.end());
            }
            if (sig.empty()) {
                sendJsonError(curreq, "no signature", 404);
                return;
            }
            libhttppp::HttpResponse rep;
            rep.setState(HTTP200);
            rep.setContentType("image/png");
            rep.send(curreq, sig, sig.size());
        }

        /* ---- JSON API: Remove User ---- */
        void apiRemoveUser(libhttppp::HttpRequest &curreq, const char *cdid, const char *cuid) {
            if (strcmp(cdid, "admin") == 0) {
@@ -465,6 +503,9 @@ namespace fenrirds {
                    else if (name == "lastname")  udat.setLastName(val);
                    else if (name == "mail")      udat.setMail(val);
                    else if (name == "pwhash" && !val.empty()) { Hash h; std::string hh; h.hash(val, hh); udat.setPwHash(hh); }
                    else if (name == "signature")  udat.setSignature(fd.value);
                    else if (name == "removesignature" && (val == "1" || val == "true" || val == "on"))
                        udat.setSignature(std::vector<char>());
                }
                upos = sizeof(AuthHeader);
                user.edit(_AdminBackend, udat, upos);
@@ -511,6 +552,10 @@ namespace fenrirds {
                else if (name == "pwhash")           { if (!val.empty()) pw = val; }
                else if (name == "windowslogin")     wantWin = (val == "1" || val == "true" || val == "on") ? 1 : 0;
                else if (name == "avatar" && isFile) attrs["thumbnailPhoto"] = {val};
                else if (name == "signature")        attrs["fenrirdsSignature"] = {val};
                /* an empty value list deletes the attribute (Directory::modify) */
                else if (name == "removesignature" && (val == "1" || val == "true" || val == "on"))
                    attrs["fenrirdsSignature"] = {};
            }

            std::string err;
@@ -2641,6 +2686,10 @@ namespace fenrirds {
                        checkDomainAccess(sdat, domain);
                        checkGPO(sdat, "a1b2c3d4-452e-11f0-b1cc-1a2b3c4d5e02");
                        apiGetUser(curreq, domain, param);
                    } else if (strcmp(apiurl, "getsignature") == 0 && param[0]) {
                        checkDomainAccess(sdat, domain);
                        checkGPO(sdat, "a1b2c3d4-452e-11f0-b1cc-1a2b3c4d5e02");
                        apiGetSignature(curreq, domain, param);
                    } else if (strcmp(apiurl, "createuser") == 0) {
                        checkDomainAccess(sdat, domain);
                        checkGPO(sdat, "a1b2c3d4-452e-11f0-b1cc-1a2b3c4d5e02");
+3 −0
Changes for src/dsdb/schema.cpp: 3 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -160,6 +160,9 @@ namespace {
            {"preferredLanguage",     "2.16.840.1.113730.3.1.39",     S::Unicode,    SG, 0},
            {"thumbnailPhoto",        "2.16.840.1.113730.3.1.35",     S::Octet,      SG|GC, 0},
            {"jpegPhoto",             "0.9.2342.19200300.100.1.60",   S::Octet,      0, 0},
            /* handwritten signature image (PNG) for documents a user signs/approves;
             * no registered arc, so a UUID-derived OID (ITU-T X.667, 2.25) */
            {"fenrirdsSignature",     "2.25.59363178883830960658818192165224902784", S::Octet, SG, 0},
            {"homeDirectory",         "1.2.840.113556.1.4.44",        S::Unicode,    SG, 0},
            {"homeDrive",             "1.2.840.113556.1.4.45",        S::Unicode,    SG, 0},
            {"scriptPath",            "1.2.840.113556.1.4.62",        S::Unicode,    SG, 0},
+19 −0
Changes for src/user.cpp: 19 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ fenrirds::UserData::UserData(const uuid::uuid &id) : AuthData(id){
    pwhash=nullptr;
    krbkey=nullptr;
    avatar=nullptr;
    signature=nullptr;
    Data.type=DataType::UserData;
}

@@ -171,6 +172,24 @@ void fenrirds::UserData::getAvatar(std::vector<char>& dest){
        throw(fenrirds::AuthBackendError("Avatar data nout found !"));
}

void fenrirds::UserData::setSignature(const std::vector<char>& src){
    setAuthData<char>(DataType::UserData,StorageType::BinaryStorage,this,&signature,"signature",src.data(),src.size());
}

void fenrirds::UserData::getSignature(std::vector<char>& dest){
    if(!signature){
        try{
            getAuthData<char>(DataType::UserData,StorageType::BinaryStorage,this,&signature,"signature");
        }catch(AuthBackendError &){
            return;
        }
    }

    if(signature && signature->data && signature->datasize)
        std::copy(signature->data,signature->data+signature->datasize,
                  std::back_inserter(dest));
}

void fenrirds::User::create(AuthBackend &backend,class UserData* dat){
    AuthBackend::Guard guard(backend);
    int exi=0;
+5 −0
Changes for src/user.h: 5 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -69,6 +69,10 @@ namespace fenrirds {
        void setAvatar(const std::vector<char> &src);
        void getAvatar(std::vector<char> &dest);

        /* empty src clears the signature; getSignature leaves dest empty if none */
        void setSignature(const std::vector<char> &src);
        void getSignature(std::vector<char> &dest);

    private:
        AuthData::Record* username;
        AuthData::Record* firstname;
@@ -78,6 +82,7 @@ namespace fenrirds {
        AuthData::Record* krbkey;
        //optional
        AuthData::Record* avatar;
        AuthData::Record* signature;
        friend class User;
    };