├── NEWS ├── debian ├── compat ├── liboauth0.install ├── docs ├── liboauth-dev.install ├── control ├── copyright ├── rules └── changelog ├── doc ├── libOAuth.png ├── Makefile.am └── mainpage.dox.in ├── COPYING ├── .travis.yml ├── oauth.pc.in ├── src ├── xmalloc.h ├── Makefile.am ├── xmalloc.c ├── sha1.c ├── hash.c └── oauth_http.c ├── tests ├── commontest.h ├── Makefile.am ├── oauthsign.c ├── oauthbodyhash.c ├── selftest_other.c ├── selftest_eran.c ├── oauthtest2.c ├── oauthdatapost.c ├── commontest.c ├── oauthexample.c ├── oauthtest.c └── selftest_wiki.c ├── liboauth.lsm.in ├── .gitignore ├── Makefile.am ├── COPYING.MIT ├── AUTHORS ├── README.md ├── LICENSE.OpenSSL ├── ChangeLog ├── configure.ac ├── INSTALL └── COPYING.GPL /NEWS: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 5 2 | -------------------------------------------------------------------------------- /debian/liboauth0.install: -------------------------------------------------------------------------------- 1 | usr/lib/lib*.so.* 2 | -------------------------------------------------------------------------------- /debian/docs: -------------------------------------------------------------------------------- 1 | tests/oauthexample.c 2 | tests/oauthtest.c 3 | -------------------------------------------------------------------------------- /doc/libOAuth.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/x42/liboauth/HEAD/doc/libOAuth.png -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | if configured with '--enable-gpl' see COPYING.GPL and LICENSE.OpenSSL 2 | otherwise read COPYING.MIT and the README 3 | -------------------------------------------------------------------------------- /doc/Makefile.am: -------------------------------------------------------------------------------- 1 | ACLOCAL_AMFLAGS= -I m4 2 | man_MANS=oauth.3 3 | 4 | EXTRA_DIST=oauth.3 mainpage.dox libOAuth.png 5 | 6 | clean: 7 | rm -rf html man 8 | -------------------------------------------------------------------------------- /debian/liboauth-dev.install: -------------------------------------------------------------------------------- 1 | usr/include/* 2 | usr/lib/pkgconfig/* 3 | usr/share/man/man3/oauth.3 4 | usr/lib/lib*.a 5 | usr/lib/lib*.so 6 | usr/lib/lib*.la 7 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: c 2 | compiler: 3 | - gcc 4 | - clang 5 | os: linux 6 | 7 | before_script: aclocal && autoheader && libtoolize --copy && autoconf && automake --gnu --add-missing --copy && ./configure 8 | script: make && make check 9 | -------------------------------------------------------------------------------- /oauth.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@prefix@ 2 | exec_prefix=@exec_prefix@ 3 | libdir=@libdir@ 4 | includedir=@includedir@ 5 | 6 | Name: oauth 7 | Description: OAuth - server to server secure API authentication 8 | Version: @VERSION@ 9 | Libs: -L${libdir} -loauth 10 | Libs.private: -lm @PC_LIB@ 11 | Cflags: -I${includedir} 12 | -------------------------------------------------------------------------------- /src/xmalloc.h: -------------------------------------------------------------------------------- 1 | #ifndef _OAUTH_XMALLOC_H 2 | #define _OAUTH_XMALLOC_H 1 3 | 4 | /* Prototypes for functions defined in xmalloc.c */ 5 | void *xmalloc (size_t size); 6 | void *xcalloc (size_t nmemb, size_t size); 7 | void *xrealloc (void *ptr, size_t size); 8 | char *xstrdup (const char *s); 9 | void xfree(void *ptr); 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /src/Makefile.am: -------------------------------------------------------------------------------- 1 | ACLOCAL_AMFLAGS= -I m4 2 | lib_LTLIBRARIES = liboauth.la 3 | include_HEADERS = oauth.h 4 | 5 | liboauth_la_SOURCES=oauth.c config.h hash.c xmalloc.c xmalloc.h oauth_http.c 6 | liboauth_la_LDFLAGS=@LIBOAUTH_LDFLAGS@ -version-info @VERSION_INFO@ 7 | liboauth_la_LIBADD=@HASH_LIBS@ @CURL_LIBS@ 8 | liboauth_la_CFLAGS=@LIBOAUTH_CFLAGS@ @HASH_CFLAGS@ @CURL_CFLAGS@ 9 | 10 | EXTRA_DIST= sha1.c 11 | -------------------------------------------------------------------------------- /tests/commontest.h: -------------------------------------------------------------------------------- 1 | int test_encoding(char *param, char *expected); 2 | #ifdef TEST_UNICODE 3 | int test_uniencoding(wchar_t *src, char *expected); 4 | #endif 5 | int test_normalize(char *param, char *expected); 6 | int test_request(char *http_method, char *request, char *expected); 7 | int test_sha1(char *c_secret, char *t_secret, char *base, char *expected); 8 | int test_sign_get(char const * const url, OAuthMethod method, const char *c_key, const char *c_secret, const char *t_key, const char *t_secret, const char *expected); 9 | -------------------------------------------------------------------------------- /liboauth.lsm.in: -------------------------------------------------------------------------------- 1 | Begin3 2 | Title: liboauth 3 | Version: @VERSION@ 4 | Entered-date: @ISODATE@ 5 | Description: OAuth - secure authentication for web applications 6 | @configure_input@ 7 | liboauth implements request signing and url escape functions 8 | according to the OAuth standard. see http://oauth.net/ 9 | Keywords: OAuth 10 | Author: robin@gareus.org (Robin Gareus) 11 | Maintained-by: robin@gareus.org (Robin Gareus) 12 | Primary-site: liboauth.sf.net /pool/ 13 | 384k liboauth-@VERSION@.tar.gz 14 | 500 liboauth.lsm 15 | Alternate-site: 16 | Original-site: 17 | Platforms: 18 | Copying-policy: GNU copyleft 19 | End 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | cscope.* 2 | tags 3 | *.swp 4 | 5 | configure 6 | stamp-* 7 | /autom4te.cache 8 | /m4 9 | 10 | Doxyfile 11 | doc/mainpage.dox 12 | doc/html/ 13 | doc/man/ 14 | 15 | Makefile 16 | Makefile.in 17 | config.* 18 | .deps 19 | .libs 20 | *.o 21 | *.lo 22 | *.la 23 | *.exe 24 | *.dll 25 | *.dylib 26 | 27 | atconfig 28 | depcomp 29 | compile 30 | aclocal.m4 31 | libtool 32 | missing 33 | ltmain.sh 34 | install-sh 35 | 36 | oauth.pc 37 | liboauth.lsm 38 | 39 | tests/oauthbodyhash 40 | tests/oauthdatapost 41 | tests/oauthexample 42 | tests/oauthsign 43 | tests/oauthtest 44 | tests/oauthtest2 45 | tests/tcwiki 46 | tests/tcother 47 | tests/tceran 48 | 49 | debian/*debhelper* 50 | debian/*substvars* 51 | debian/tmp 52 | debian/files 53 | debian/liboauth-dev 54 | debian/liboauth0 55 | -------------------------------------------------------------------------------- /Makefile.am: -------------------------------------------------------------------------------- 1 | AUTOMAKE_OPTIONS = foreign 2 | ACLOCAL_AMFLAGS= -I m4 3 | SUBDIRS = @subdirs@ 4 | 5 | EXTRA_DIST=liboauth.lsm.in oauth.pc.in Doxyfile.in \ 6 | COPYING.GPL COPYING.MIT LICENSE.OpenSSL \ 7 | m4 8 | 9 | pkgconfigdir = $(libdir)/pkgconfig 10 | pkgconfig_DATA = oauth.pc 11 | 12 | TESTS=tests/tcwiki@EXESUF@ tests/tceran@EXESUF@ tests/tcother@EXESUF@ 13 | 14 | CLEANFILES = stamp-doxygen stamp-doc 15 | 16 | MAINTAINERCLEANFILES = \ 17 | src/Makefile.in \ 18 | tests/Makefile.in \ 19 | tests/atconfig \ 20 | doc/Makefile.in \ 21 | Makefile.in \ 22 | aclocal.m4 \ 23 | compile \ 24 | config.guess \ 25 | config.h.in \ 26 | config.sub \ 27 | configure \ 28 | depcomp \ 29 | install-sh \ 30 | missing 31 | 32 | dox: stamp-doxygen 33 | 34 | stamp-doxygen: src/oauth.h doc/mainpage.dox Doxyfile 35 | $(DOXYGEN) Doxyfile && touch stamp-doxygen 36 | cp doc/man/man3/oauth.h.3 doc/oauth.3 37 | sed 's/ -\([qsdU]\)/ \\-\1/g' doc/man/man3/oauth.h.3 \ 38 | | sed 's/ -1 / \\-1 /' \ 39 | | sed 's/--/\\-\\-/' \ 40 | > doc/oauth.3 41 | -------------------------------------------------------------------------------- /COPYING.MIT: -------------------------------------------------------------------------------- 1 | Copyright 2007, 2008 Robin Gareus 2 | 3 | Unless otherwise indicated, Source Code is licensed under MIT license. 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: liboauth 2 | Section: libs 3 | Priority: optional 4 | Maintainer: Robin Gareus 5 | Build-Depends: debhelper (>= 5), autotools-dev, automake, libnss3-dev, libtool, autoconf 6 | Standards-Version: 3.8.4 7 | Homepage: http://liboauth.sourceforge.net/ 8 | Vcs-Git: git://rg42.org/liboauth 9 | 10 | Package: liboauth-dev 11 | Section: libdevel 12 | Architecture: any 13 | Depends: liboauth0 (= ${binary:Version}), ${misc:Depends} 14 | Description: Development files for liboauth 15 | OAuth - secure authentication for desktop and web applications. 16 | http://liboauth.sf.net/ is a collection of c functions implementing the 17 | OAuth Core 1.0 standard API (RFC 5849). liboauth provides functions to escape 18 | and encode parameters according to OAuth specfication and offers high-level 19 | functionality to sign requests or verify signatures. 20 | 21 | Package: liboauth0 22 | Section: libs 23 | Architecture: any 24 | Depends: ${shlibs:Depends}, ${misc:Depends} 25 | Description: OAuth - secure authentication for desktop and web applications 26 | http://liboauth.sf.net/ is a collection of c functions implementing the 27 | OAuth Core 1.0 standard API (RFC 5849). liboauth provides functions to escape 28 | and encode parameters according to OAuth specification and offers high-level 29 | functionality to sign requests or verify signatures. 30 | -------------------------------------------------------------------------------- /tests/Makefile.am: -------------------------------------------------------------------------------- 1 | check_PROGRAMS = oauthexample oauthdatapost tcwiki tceran tcother oauthtest oauthtest2 oauthsign oauthbodyhash 2 | ACLOCAL_AMFLAGS= -I m4 3 | 4 | OAUTHDIR =../src 5 | AM_CPPFLAGS = -I$(srcdir)/$(OAUTHDIR) 6 | MYCFLAGS = @LIBOAUTH_CFLAGS@ @HASH_CFLAGS@ @CURL_CFLAGS@ 7 | MYLDADD = $(OAUTHDIR)/liboauth.la 8 | LIBS = -lm @HASH_LIBS@ @CURL_LIBS@ @LIBS@ 9 | 10 | tcwiki_SOURCES = selftest_wiki.c commontest.c commontest.h 11 | tcwiki_LDADD = $(MYLDADD) 12 | tcwiki_CFLAGS = $(MYCFLAGS) @TEST_UNICODE@ 13 | 14 | tceran_SOURCES = selftest_eran.c commontest.c commontest.h 15 | tceran_LDADD = $(MYLDADD) 16 | tceran_CFLAGS = $(MYCFLAGS) @TEST_UNICODE@ 17 | 18 | tcother_SOURCES = selftest_other.c commontest.c commontest.h 19 | tcother_LDADD = $(MYLDADD) 20 | tcother_CFLAGS = $(MYCFLAGS) 21 | 22 | oauthtest_SOURCES = oauthtest.c 23 | oauthtest_LDADD = $(MYLDADD) 24 | oauthtest_CFLAGS = $(MYCFLAGS) 25 | 26 | oauthtest2_SOURCES = oauthtest2.c 27 | oauthtest2_LDADD = $(MYLDADD) 28 | oauthtest2_CFLAGS = $(MYCFLAGS) 29 | 30 | oauthexample_SOURCES = oauthexample.c 31 | oauthexample_LDADD = $(MYLDADD) 32 | oauthexample_CFLAGS = $(MYCFLAGS) 33 | 34 | oauthsign_SOURCES = oauthsign.c 35 | oauthsign_LDADD = $(MYLDADD) 36 | oauthsign_CFLAGS = $(MYCFLAGS) 37 | 38 | oauthdatapost_SOURCES = oauthdatapost.c 39 | oauthdatapost_LDADD = $(MYLDADD) 40 | oauthdatapost_CFLAGS = $(MYCFLAGS) 41 | 42 | oauthbodyhash_SOURCES = oauthbodyhash.c 43 | oauthbodyhash_LDADD = $(MYLDADD) 44 | oauthbodyhash_CFLAGS = $(MYCFLAGS) 45 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | This package was debianized by Robin Gareus on 2 | Sun, 09 Dec 2007 22:01:34 +0100. 3 | 4 | It was downloaded from: 5 | 6 | http://liboauth.sourceforge.net/pool/liboauth-0.8.0.tar.gz 7 | 8 | Upstream Author: 9 | 10 | Robin Gareus 11 | 12 | Copyright: 13 | 14 | Copyright (C) 2007-2012 Robin Gareus 15 | 16 | License: 17 | 18 | This package is free software; you can redistribute it and/or 19 | modify it under the terms of the GNU General Public 20 | License as published by the Free Software Foundation; either 21 | version 2 of the License, or (at your option) any later version. 22 | 23 | This package is distributed in the hope that it will be useful, 24 | but WITHOUT ANY WARRANTY; without even the implied warranty of 25 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 26 | General Public License for more details. 27 | 28 | You should have received a copy of the GNU General Public 29 | License along with this package; if not, write to the Free Software 30 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 31 | 32 | On Debian systems, the complete text of the GNU General 33 | Public License can be found in `/usr/share/common-licenses/GPL'. 34 | 35 | The Debian packaging is (C) 2007, Robin Gareus and 36 | is licensed under the GPL, see `/usr/share/common-licenses/GPL'. 37 | 38 | Note that liboauth without packaging can be distributed under ther MIT license. 39 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Robin Gareus has written and is maintaining liboauth. 2 | 3 | The base64 code is used with permission from Jan-Henrik 4 | Haukeland . 5 | 6 | escape_url() contains code from curl by Daniel Stenberg 7 | 8 | cheers to Arjan for using and testing this code; and 9 | Ralph Meijer for fixing the debian package and quality control. 10 | 11 | Kudos to Marc Worrel - http://www.marcworrell.com/ - for an introduction 12 | to the OAuth API and helping to get this project alive. And last but not 13 | standing ovations to the http://oauth.net team who made it possible in i 14 | the first place. 15 | 16 | Marc Powell suggested minor changes and contributed patches to make this 17 | library more usable. 18 | 19 | Stephen Paul Weber sent patches for the 20 | initial Debian package. 21 | 22 | Dave Gamble has jumped on board. Writing a lightweight 23 | c-api for soundcloud, he sent fixes for windows MSVC support and added the 24 | oauth_curl_post_data_with_callback() function. 25 | 26 | Emil A Eklund provided a patch for CURLOPT_TIMEOUT to avoid problems with 27 | HTTP timeouts. 28 | 29 | Many thanks to Diego Elio Pettenò who sent patches for the build-system and 30 | packages liboauth for Gentoo. Likewise Tom Parker for Debian, as well as 31 | Paul Wise who metorered Bilal Akhtar on debian-mentors. All of which provided 32 | valuable feedback. 33 | 34 | Last but not least, Jeff Squyres inspired the '-Wl,--as-needed' linker flags 35 | check. 36 | 37 | -------------------------------------------------------------------------------- /src/xmalloc.c: -------------------------------------------------------------------------------- 1 | /* xmalloc.c -- memory allocation including 'out of memory' checks 2 | * 3 | * Copyright 2010 Robin Gareus 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | * THE SOFTWARE. 22 | * 23 | */ 24 | 25 | #include 26 | #include 27 | #include 28 | #include 29 | 30 | static void *xmalloc_fatal(size_t size) { 31 | if (size==0) return NULL; 32 | fprintf(stderr, "Out of memory."); 33 | exit(1); 34 | } 35 | 36 | void *xmalloc (size_t size) { 37 | void *ptr = malloc (size); 38 | if (ptr == NULL) return xmalloc_fatal(size); 39 | return ptr; 40 | } 41 | 42 | void *xcalloc (size_t nmemb, size_t size) { 43 | void *ptr = calloc (nmemb, size); 44 | if (ptr == NULL) return xmalloc_fatal(nmemb*size); 45 | return ptr; 46 | } 47 | 48 | void *xrealloc (void *ptr, size_t size) { 49 | void *p = realloc (ptr, size); 50 | if (p == NULL) return xmalloc_fatal(size); 51 | return p; 52 | } 53 | 54 | char *xstrdup (const char *s) { 55 | void *ptr = xmalloc(strlen(s)+1); 56 | strcpy (ptr, s); 57 | return (char*) ptr; 58 | } 59 | 60 | void xfree(void *ptr) { 61 | return free(ptr); 62 | } 63 | // vi: sts=2 sw=2 ts=2 64 | -------------------------------------------------------------------------------- /tests/oauthsign.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | static void usage (char *program_name) { 7 | printf(" usage: %s mode url ckey tkey csec tsec\n", program_name); 8 | exit (1); 9 | } 10 | 11 | /** 12 | * 13 | * compile: 14 | * gcc -loauth -o oauthsign oauthsign.c 15 | */ 16 | int main (int argc, char **argv) { 17 | 18 | char *url; //< the url to sign 19 | char *c_key; //< consumer key 20 | char *c_secret; //< consumer secret 21 | char *t_key; //< token key 22 | char *t_secret ; //< token secret 23 | 24 | int mode = 0; //< mode: 0=GET 1=POST 25 | 26 | // TODO: use getopt to parse parameters 27 | 28 | // FIXME: read secrets from stdin - they show up in ps(1) 29 | // also overwrite memory of secrets before freeing it. 30 | 31 | if (argc !=7) usage(argv[0]); 32 | 33 | if ( atoi(argv[1]) > 0 ) mode=atoi(argv[1]);// questionable numeric shortcut 34 | else if (!strcasecmp(argv[1],"GET")) mode=1; 35 | else if (!strcasecmp(argv[1],"POST")) mode=2; 36 | else if (!strcasecmp(argv[1],"POSTREQUEST")) mode=4; 37 | else usage(argv[0]); 38 | 39 | url = argv[2]; 40 | c_key = argv[3]; 41 | t_key = argv[4]; 42 | c_secret = argv[5]; 43 | t_secret = argv[6]; 44 | 45 | if (mode==1) { // GET 46 | char *geturl = NULL; 47 | geturl = oauth_sign_url2(url, NULL, OA_HMAC, NULL, c_key, c_secret, t_key, t_secret); 48 | if(geturl) { 49 | printf("%s\n", geturl); 50 | free(geturl); 51 | } 52 | } else { // POST 53 | char *postargs = NULL, *post = NULL; 54 | post = oauth_sign_url2(url, &postargs, OA_HMAC, NULL, c_key, c_secret, t_key, t_secret); 55 | if (!post || !postargs) { 56 | return (1); 57 | } 58 | if (mode==2) { // print postargs only 59 | if (postargs) printf("%s\n", postargs); 60 | } else if (mode==3) { // print url and postargs 61 | if (post && postargs) printf("%s\n%s\n", post, postargs); 62 | } else if (post && postargs) { 63 | char *reply = oauth_http_post(post,postargs); 64 | if(reply){ 65 | //write(STDOUT, reply, strlen(reply)) 66 | printf("%s\n", reply); 67 | free(reply); 68 | } 69 | } 70 | if(post) free(post); 71 | if(postargs) free(postargs); 72 | } 73 | 74 | return (0); 75 | } 76 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | liboauth 2 | ======== 3 | 4 | liboauth is a collection of c functions implementing the http://oauth.net API. 5 | 6 | liboauth provides functions to escape and encode stings according to 7 | OAuth specifications and offers high-level functionality built on top to sign 8 | requests or verify signatures using either NSS or OpenSSL for calculating 9 | the hash/signatures. 10 | 11 | The included documentation in the `doc/` folder and example code from `tests/` 12 | can also be found online at http://liboauth.sourceforge.net/ 13 | 14 | Send bug-reports, patches or suggestions to robin@gareus.org. 15 | or inquire information at http://groups.google.com/group/oauth/ 16 | 17 | [![Build Status](https://travis-ci.org/x42/liboauth.svg)](https://travis-ci.org/x42/liboauth) 18 | 19 | License and Notes 20 | ----------------- 21 | 22 | The source-code of liboauth can be distributed under MIT License, 23 | or at your option: in terms of the the GNU General Public License. 24 | see COPYING.MIT or COPYING.GPL for details. 25 | 26 | Note: OpenSSL is not strictly compatible with the GPL license. 27 | An exemption (to the GPL) allowing to link and redistribute 28 | liboauth with the OpenSSL library is is included in the source files. 29 | for more information, see LICENSE.OpenSSL and 30 | http://lists.debian.org/debian-legal/2004/05/msg00595.html 31 | 32 | You can avoid this whole issue by using NSS instead of OpenSSL; 33 | configure with '--enable-nss'. 34 | 35 | The Debian packaging that comes with the source-code is licensed under 36 | the GNU General Public License. 37 | 38 | Test and Example Code 39 | --------------------- 40 | 41 | After compilation `make check` can be used to perform a off-line self-test. 42 | 43 | There is also example code to perform and verify OAuth requests online, 44 | but they are not run automatically. 45 | 46 | 47 | * `tests/oauthexample.c` - CONNECTS TO INTERNET 48 | walk-though http://term.ie/oauth/example 49 | 50 | * `tests/oauthtest.c` - CONNECTS TO INTERNET 51 | gets a request-token from http://term.ie test-server 52 | 53 | * `tests/oauthtest2.c` - CONNECTS TO INTERNET 54 | gets a request-token from http://term.ie test-server 55 | using OAuth HTTP Authorization header: 56 | see http://oauth.net/core/1.0a/#auth_header 57 | and http://oauth.net/core/1.0a/#consumer_req_param 58 | 59 | * `tests/selftest_wiki.c` 60 | * `tests/selftest_eran.c` 61 | Test-Cases for parameter encoding, signatures, etc 62 | 63 | * `tests/commontest.c` 64 | Common Test-Case functions exercising the low-level API used by self-tests. 65 | 66 | * `tests/oauthdatapost.c` - CONNECTS TO INTERNET 67 | Experimental code to sign data uploads 68 | Note: The example keys have since been deleted from the test-server. 69 | Code remains for inspiration/example purposes. 70 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | # -*- makefile -*- 3 | # Sample debian/rules that uses debhelper. 4 | # This file was originally written by Joey Hess and Craig Small. 5 | # As a special exception, when this file is copied by dh-make into a 6 | # dh-make output file, you may use that output file without restriction. 7 | # This special exception was added by Craig Small in version 0.37 of dh-make. 8 | 9 | # Uncomment this to turn on verbose mode. 10 | #export DH_VERBOSE=1 11 | 12 | 13 | # These are used for cross-compiling and for saving the configure script 14 | # from having to guess our platform (since we know it already) 15 | DEB_HOST_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_HOST_GNU_TYPE) 16 | DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) 17 | 18 | 19 | # shared library versions, option 1 20 | version=2.0.5 21 | major=2 22 | # option 2, assuming the library is created as src/.libs/libfoo.so.2.0.5 or so 23 | version=`ls src/.libs/lib*.so.* | \ 24 | awk '{if (match($$0,/[0-9]+\.[0-9]+\.[0-9]+$$/)) print substr($$0,RSTART)}'` 25 | major=`ls src/.libs/lib*.so.* | \ 26 | awk '{if (match($$0,/\.so\.[0-9]+$$/)) print substr($$0,RSTART+4)}'` 27 | 28 | configure: 29 | aclocal 30 | autoheader 31 | libtoolize --copy 32 | autoconf 33 | automake --gnu --add-missing --copy 34 | 35 | config.status: configure 36 | dh_testdir 37 | # Add here commands to configure the package. 38 | ./configure --host=$(DEB_HOST_GNU_TYPE) --build=$(DEB_BUILD_GNU_TYPE) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info CFLAGS="$(CFLAGS)" LDFLAGS="-Wl,-z,defs" --enable-nss --with-curltimeout=120 39 | 40 | 41 | build: build-stamp 42 | build-stamp: config.status 43 | dh_testdir 44 | 45 | $(MAKE) 46 | 47 | touch $@ 48 | 49 | clean: 50 | dh_testdir 51 | dh_testroot 52 | rm -f build-stamp 53 | 54 | [ ! -f Makefile ] || $(MAKE) distclean 55 | rm -f configure config.sub config.guess 56 | 57 | dh_clean -a 58 | 59 | install: build 60 | dh_testdir 61 | dh_testroot 62 | dh_clean -k -a 63 | dh_installdirs 64 | 65 | $(MAKE) DESTDIR=$(CURDIR)/debian/tmp install 66 | 67 | 68 | # Build architecture-independent files here. 69 | binary-indep: build install 70 | # We have nothing to do by default. 71 | 72 | # Build architecture-dependent files here. 73 | binary-arch: build install 74 | dh_testdir 75 | dh_testroot 76 | dh_install -a --sourcedir=debian/tmp --list-missing 77 | dh_installdocs -a 78 | dh_installchangelogs -a ChangeLog 79 | dh_installexamples -a 80 | # dh_installmenu 81 | # dh_installdebconf 82 | # dh_installlogrotate 83 | # dh_installemacsen 84 | # dh_installpam 85 | # dh_installmime 86 | # dh_installinit 87 | # dh_installcron 88 | # dh_installinfo 89 | dh_installman -a 90 | dh_link -a 91 | dh_strip -a 92 | dh_compress -a 93 | dh_fixperms -a 94 | # dh_perl -a 95 | # dh_python -a 96 | dh_makeshlibs -a 97 | dh_installdeb -a 98 | dh_shlibdeps -a 99 | dh_gencontrol -a 100 | dh_md5sums -a 101 | dh_builddeb -a 102 | 103 | binary: binary-indep binary-arch 104 | .PHONY: build clean binary-indep binary-arch binary install 105 | -------------------------------------------------------------------------------- /tests/oauthbodyhash.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief experimental code to sign data uploads 3 | * @file oauthbodysign.c 4 | * @author Robin Gareus 5 | * 6 | * Copyright 2009, 2012 Robin Gareus 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | int my_data_post(char *url, char *data) { 33 | const char *c_key = "key"; //< consumer key 34 | const char *c_secret = "secret"; //< consumer secret 35 | char *t_key = "tkey"; //< access token key 36 | char *t_secret = "tsecret"; //< access token secret 37 | 38 | char *postarg = NULL; 39 | char *req_url = NULL; 40 | char *reply = NULL; 41 | char *bh; 42 | char *uh; 43 | char *sig_url; 44 | 45 | bh=oauth_body_hash_data(strlen(data), data); 46 | uh = (char*) malloc((strlen(url)+strlen(bh)+2) * sizeof(char)); 47 | if (!uh) return -1; 48 | 49 | strcat(uh, url); 50 | strcat(uh, "?"); 51 | strcat(uh, bh); 52 | 53 | printf("URL: %s\n", uh); 54 | req_url = oauth_sign_url2(uh, &postarg, OA_HMAC, NULL, c_key, c_secret, t_key, t_secret); 55 | printf("POST: %s?%s\n", req_url, postarg); 56 | if (uh) free(uh); 57 | 58 | sig_url = malloc(2+strlen(req_url)+strlen(postarg)); 59 | sprintf(sig_url,"%s?%s",req_url, postarg); 60 | reply = oauth_post_data(sig_url, data, strlen(data), "Content-Type: application/json"); 61 | if(sig_url) free(sig_url); 62 | 63 | if (reply) { 64 | printf("REPLY: %s\n", reply); 65 | free(reply); 66 | } else { 67 | printf("Error performing the request\n"); 68 | } 69 | return 0; 70 | } 71 | 72 | int main (int argc, char **argv) { 73 | char *base_url = "http://localhost/oauthtest.php"; 74 | char *teststring="Hello World!"; 75 | 76 | /* TEST_BODY_HASH_FILE and TEST_BODY_HASH_DATA are only 77 | * here as examples and for testing during development. 78 | * 79 | * the my_data_post() function above uses oauth_body_hash_data() 80 | */ 81 | 82 | #if defined TEST_BODY_HASH_FILE || defined TEST_BODY_HASH_DATA 83 | char *bh=NULL; 84 | #endif 85 | 86 | #ifdef TEST_BODY_HASH_FILE // example hash file 87 | char *filename="/tmp/test"; 88 | bh=oauth_body_hash_file(filename); 89 | if (bh) printf("%s\n", bh); 90 | if (bh) free(bh); 91 | #endif 92 | 93 | #ifdef TEST_BODY_HASH_DATA // example hash data 94 | bh=oauth_body_hash_data(strlen(teststring), teststring); 95 | if (bh) printf("%s\n", bh); 96 | if (bh) free(bh); 97 | #endif 98 | 99 | my_data_post(base_url, teststring); 100 | return(0); 101 | } 102 | -------------------------------------------------------------------------------- /tests/selftest_other.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief self-test for liboauth. 3 | * @file selftest.c 4 | * @author Robin Gareus 5 | * 6 | * Copyright 2009, 2010, 2012 Robin Gareus 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "commontest.h" 33 | 34 | int loglevel = 1; //< report each successful test 35 | 36 | int main (int argc, char **argv) { 37 | int fail=0; 38 | 39 | if (loglevel) printf("\n *** Testing query parameter array encoding.\n"); 40 | 41 | fail|=test_request("GET", "http://example.com" 42 | "?k1=v1" 43 | "&a1[ak1]=av1" 44 | "&a1[aa1][aak2]=aav2" 45 | "&a1[aa1][aak1]=aav1" 46 | "&k2=v2" 47 | "&a1[ak2]=av2", 48 | "GET&http%3A%2F%2Fexample.com%2F&a1%255Baa1%255D%255Baak1%255D%3Daav1%26a1%255Baa1%255D%255Baak2%255D%3Daav2%26a1%255Bak1%255D%3Dav1%26a1%255Bak2%255D%3Dav2%26k1%3Dv1%26k2%3Dv2"); 49 | 50 | if (loglevel) printf("\n *** Testing http://tools.ietf.org/html/rfc5849 example.\n"); 51 | 52 | fail|=test_request("GET", "http://example.com" 53 | "/request?b5=%3D%253D&a3=a&c%40=&a2=r%20b" 54 | "&c2&a3=2+q" 55 | "&oauth_consumer_key=9djdj82h48djs9d2" 56 | "&oauth_token=kkk9d7dh3k39sjv7" 57 | "&oauth_signature_method=HMAC-SHA1" 58 | "&oauth_timestamp=137131201" 59 | "&oauth_nonce=7d8f3e4a" 60 | "&oauth_signature=djosJKDKJSD8743243%2Fjdk33klY%3D", 61 | "GET&http%3A%2F%2Fexample.com%2Frequest&a2%3Dr%2520b%26a3%3D2%2520q%26a3%3Da%26b5%3D%253D%25253D%26c%2540%3D%26c2%3D%26oauth_consumer_key%3D9djdj82h48djs9d2%26oauth_nonce%3D7d8f3e4a%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D137131201%26oauth_token%3Dkkk9d7dh3k39sjv7"); 62 | 63 | if (loglevel) printf("\n *** Testing body hash calculation.\n"); 64 | 65 | char *bh; 66 | const char *teststring="Hello World!"; 67 | bh=oauth_body_hash_data(strlen(teststring), teststring); 68 | if (bh) { 69 | if (strcmp(bh,"oauth_body_hash=Lve95gjOVATpfV8EL5X4nxwjKHE=")) fail|=1; 70 | free(bh); 71 | } else { 72 | fail|=1; 73 | } 74 | 75 | if (loglevel) printf("\n *** Testing PLAINTEXT signature.\n"); 76 | fail |= test_sign_get( 77 | "http://host.net/resource" "?" "name=value&name=value" 78 | "&oauth_nonce=fake&&oauth_timestamp=1", 79 | OA_PLAINTEXT, 80 | "abcd", "&", 81 | "1234", "&", 82 | "http://host.net/resource?name=value&name=value&oauth_consumer_key=abcd&oauth_nonce=fake&oauth_signature_method=PLAINTEXT&oauth_timestamp=1&oauth_token=1234&oauth_version=1.0&oauth_signature=%2526%26%2526" 83 | ); 84 | 85 | 86 | // report 87 | if (fail) { 88 | printf("\n !!! One or more test cases failed.\n\n"); 89 | } else { 90 | printf(" *** Test cases verified sucessfully.\n"); 91 | } 92 | 93 | return (fail?1:0); 94 | } 95 | -------------------------------------------------------------------------------- /tests/selftest_eran.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief self-test for liboauth. 3 | * @file selftest.c 4 | * @author Robin Gareus 5 | * 6 | * This code contains examples provided by Eran Hammer-Lahav 7 | * on the oauth.net mailing list. 8 | * 9 | * Copyright 2008, 2009 Robin Gareus 10 | * 11 | * Permission is hereby granted, free of charge, to any person obtaining a copy 12 | * of this software and associated documentation files (the "Software"), to deal 13 | * in the Software without restriction, including without limitation the rights 14 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 15 | * copies of the Software, and to permit persons to whom the Software is 16 | * 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 FROM, 26 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 27 | * THE SOFTWARE. 28 | */ 29 | 30 | #ifdef TEST_UNICODE 31 | #include 32 | #endif 33 | 34 | #include 35 | #include 36 | #include 37 | #include 38 | 39 | #include "commontest.h" 40 | 41 | int loglevel = 1; //< report each successful test 42 | 43 | int main (int argc, char **argv) { 44 | int fail=0; 45 | char *tmptst; 46 | 47 | if (loglevel) printf("\n *** testing liboauth against Eran's Test cases ***\n http://groups.google.com/group/oauth/browse_frm/thread/243f4da439fd1f51?hl=en\n"); 48 | 49 | // Eran's test-cases - http://groups.google.com/group/oauth/browse_frm/thread/243f4da439fd1f51?hl=en 50 | fail|=test_encoding("1234=asdf=4567","1234%3Dasdf%3D4567"); 51 | fail|=test_encoding("asdf-4354=asew-5698","asdf-4354%3Dasew-5698"); 52 | fail|=test_encoding("erks823*43=asd&123ls%23","erks823%2A43%3Dasd%26123ls%2523"); 53 | fail|=test_encoding("dis9$#$Js009%==","dis9%24%23%24Js009%25%3D%3D"); 54 | fail|=test_encoding("3jd834jd9","3jd834jd9"); 55 | fail|=test_encoding("12303202302","12303202302"); 56 | fail|=test_encoding("taken with a 30% orange filter","taken%20with%20a%2030%25%20orange%20filter"); 57 | fail|=test_encoding("mountain & water view","mountain%20%26%20water%20view"); 58 | 59 | fail|=test_request("GET", "http://example.com:80/photo" "?" 60 | "oauth_version=1.0" 61 | "&oauth_consumer_key=1234=asdf=4567" 62 | "&oauth_timestamp=12303202302" 63 | "&oauth_nonce=3jd834jd9" 64 | "&oauth_token=asdf-4354=asew-5698" 65 | "&oauth_signature_method=HMAC-SHA1" 66 | "&title=taken with a 30% orange filter" 67 | "&file=mountain \001 water view" 68 | "&format=jpeg" 69 | "&include=date" 70 | "&include=aperture", 71 | "GET&http%3A%2F%2Fexample.com%2Fphoto&file%3Dmountain%2520%2526%2520water%2520view%26format%3Djpeg%26include%3Daperture%26include%3Ddate%26oauth_consumer_key%3D1234%253Dasdf%253D4567%26oauth_nonce%3D3jd834jd9%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D12303202302%26oauth_token%3Dasdf-4354%253Dasew-5698%26oauth_version%3D1.0%26title%3Dtaken%2520with%2520a%252030%2525%2520orange%2520filter" ); 72 | 73 | tmptst = oauth_sign_url2( 74 | "http://example.com:80/photo" "?" 75 | "oauth_version=1.0" 76 | "&oauth_timestamp=12303202302" 77 | "&oauth_nonce=3jd834jd9" 78 | "&title=taken with a 30% orange filter" 79 | "&file=mountain \001 water view" 80 | "&format=jpeg" 81 | "&include=date" 82 | "&include=aperture", 83 | NULL, OA_HMAC, NULL, "1234=asdf=4567", "erks823*43=asd&123ls%23", "asdf-4354=asew-5698", "dis9$#$Js009%=="); 84 | if (strcmp(tmptst,"http://example.com/photo?file=mountain%20%26%20water%20view&format=jpeg&include=aperture&include=date&oauth_consumer_key=1234%3Dasdf%3D4567&oauth_nonce=3jd834jd9&oauth_signature_method=HMAC-SHA1&oauth_timestamp=12303202302&oauth_token=asdf-4354%3Dasew-5698&oauth_version=1.0&title=taken%20with%20a%2030%25%20orange%20filter&oauth_signature=jMdUSR1vOr3SzNv3gZ5DDDuGirA%3D")) { 85 | printf(" got '%s'\n expected: '%s'\n",tmptst, "http://example.com/photo?file=mountain%20%26%20water%20view&format=jpeg&include=aperture&include=date&oauth_consumer_key=1234%3Dasdf%3D4567&oauth_nonce=3jd834jd9&oauth_signature_method=HMAC-SHA1&oauth_timestamp=12303202302&oauth_token=asdf-4354%3Dasew-5698&oauth_version=1.0&title=taken%20with%20a%2030%25%20orange%20filter&oauth_signature=jMdUSR1vOr3SzNv3gZ5DDDuGirA%3D"); 86 | fail|=1; 87 | } else if (loglevel) printf("request signature ok.\n"); 88 | if(tmptst) free(tmptst); 89 | 90 | // report 91 | if (fail) { 92 | printf("\n !!! One or more of Eran's Test Cases failed.\n\n"); 93 | } else { 94 | printf(" *** Eran's Test-Cases verified sucessfully.\n"); 95 | } 96 | 97 | return (fail?1:0); 98 | } 99 | -------------------------------------------------------------------------------- /tests/oauthtest2.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief self-test and example code for liboauth using 3 | * HTTP Authorization header. 4 | * @file oauthtest.c 5 | * @author Robin Gareus 6 | * 7 | * Copyright 2010, 2011 Robin Gareus 8 | * 9 | * Permission is hereby granted, free of charge, to any person obtaining a copy 10 | * of this software and associated documentation files (the "Software"), to deal 11 | * in the Software without restriction, including without limitation the rights 12 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | * copies of the Software, and to permit persons to whom the Software is 14 | * furnished to do so, subject to the following conditions: 15 | * 16 | * The above copyright notice and this permission notice shall be included in 17 | * all copies or substantial portions of the Software. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 25 | * THE SOFTWARE. 26 | */ 27 | 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | /* 34 | * a example requesting and parsing a request-token from an OAuth service-provider 35 | * using OAuth HTTP Authorization header: 36 | * see http://oauth.net/core/1.0a/#auth_header 37 | * and http://oauth.net/core/1.0a/#consumer_req_param 38 | */ 39 | void request_token_example_get(void) { 40 | #if 0 41 | const char *request_token_uri = "http://localhost/oauthtest.php?test=test"; 42 | const char *req_c_key = "17b09ea4c9a4121145936f0d7d8daa28047583796"; //< consumer key 43 | const char *req_c_secret = "942295b08ffce77b399419ee96ac65be"; //< consumer secret 44 | #else 45 | const char *request_token_uri = "http://term.ie/oauth/example/request_token.php"; 46 | const char *req_c_key = "key"; //< consumer key 47 | const char *req_c_secret = "secret"; //< consumer secret 48 | #endif 49 | char *res_t_key = NULL; //< replied key 50 | char *res_t_secret = NULL; //< replied secret 51 | 52 | char *req_url = NULL; 53 | char *req_hdr = NULL; 54 | char *http_hdr= NULL; 55 | char *reply; 56 | 57 | 58 | //req_url = oauth_sign_url2(request_token_uri, NULL, OA_HMAC, NULL, req_c_key, req_c_secret, NULL, NULL); 59 | 60 | // oauth_sign_url2 (see oauth.h) in steps 61 | int argc; 62 | char **argv = NULL; 63 | 64 | argc = oauth_split_url_parameters(request_token_uri, &argv); 65 | if (1) { 66 | int i; 67 | for (i=0;i 5 | * 6 | * Copyright 2008, 2012 Robin Gareus 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #ifdef USE_MMAP 33 | #include 34 | #endif 35 | 36 | /** 37 | * example oauth body signature and HTTP-POST. 38 | * WARNING: This is request type is not part of the 39 | * oauth core 1.0. 40 | * 41 | * This is an experimental extension. 42 | */ 43 | int oauth_image_post(char *filename, char *url) { 44 | const char *c_key = "key"; //< consumer key 45 | const char *c_secret = "secret"; //< consumer secret 46 | char *t_key = NULL; //< access token key 47 | char *t_secret = NULL; //< access token secret 48 | 49 | char *postarg = NULL; 50 | char *req_url = NULL; 51 | char *reply = NULL; 52 | 53 | char *filedata = NULL; 54 | size_t filelen = 0; 55 | 56 | FILE *F; 57 | 58 | char *okey, *sign; 59 | char *sig_url; 60 | 61 | // get acces token - see oautexample.c 62 | t_key = strdup("key"); //< access token key 63 | t_secret = strdup("secret"); //< access token secret 64 | 65 | // read raw data to sign and send from file. 66 | F= fopen(filename, "r"); 67 | if (!F) return 1; 68 | fseek(F, 0L, SEEK_END); 69 | filelen= ftell(F); 70 | rewind(F); 71 | 72 | #ifdef USE_MMAP 73 | filedata=mmap(NULL,filelen,PROT_READ,MAP_SHARED,fileno(F),0L); 74 | #else 75 | filedata=malloc(filelen*sizeof(char)); 76 | if (filelen != fread(filedata,sizeof(char), filelen, F)) { 77 | fclose(F); 78 | return 2; 79 | } 80 | fclose(F); 81 | #endif 82 | 83 | // sign the body 84 | okey = oauth_catenc(2, c_secret, t_secret); 85 | sign = oauth_sign_hmac_sha1_raw(filedata,filelen,okey,strlen(okey)); 86 | free(okey); 87 | sig_url = malloc(63+strlen(url)+strlen(sign)); 88 | sprintf(sig_url,"%s&xoauth_body_signature=%s&xoauth_body_signature_method=HMAC_SHA1",url, sign); 89 | 90 | // sign a POST request 91 | req_url = oauth_sign_url2(sig_url, &postarg, OA_HMAC, NULL, c_key, c_secret, t_key, t_secret); 92 | free(sig_url); 93 | 94 | // append the oauth [post] parameters to the request-URL!! 95 | sig_url = malloc(2+strlen(req_url)+strlen(postarg)); 96 | sprintf(sig_url,"%s?%s",req_url, postarg); 97 | 98 | printf("POST:'%s'\n",sig_url); 99 | //reply = oauth_post_file(sig_url,filename,filelen,"Content-Type: image/jpeg;"); 100 | printf("reply:'%s'\n",reply); 101 | 102 | if(req_url) free(req_url); 103 | if(postarg) free(postarg); 104 | if(reply) free(reply); 105 | if(t_key) free(t_key); 106 | if(t_secret) free(t_secret); 107 | 108 | #ifdef USE_MMAP 109 | munmap(filedata,filelen); 110 | fclose(F); 111 | #else 112 | if(filedata) free(filedata); 113 | #endif 114 | return(0); 115 | } 116 | 117 | 118 | /** 119 | * Main Test and Example Code. 120 | * 121 | * compile: 122 | * gcc -lssl -loauth -o oauthdatapost oauthdatapost.c 123 | */ 124 | 125 | int main (int argc, char **argv) { 126 | char *base_url = "http://mms06.test.mediamatic.nl"; 127 | char *filename = "/tmp/test.jpg"; 128 | int anyid = 18704; 129 | char *title = "test"; 130 | char *url; 131 | 132 | if (argc>4) base_url = argv[4]; 133 | if (argc>3) title = argv[3]; 134 | if (argc>2) anyid = atoi(argv[2]); 135 | if (argc>1) filename = argv[1]; 136 | 137 | // TODO check if file exists; also read oauth-params from args or file 138 | 139 | // anyMeta.nl image-post module URL 140 | url = malloc(1024*sizeof(char)); 141 | if (anyid<1 && !title) 142 | sprintf(url,"%s/module/ImagePost/",base_url); 143 | else if (anyid>0 && !title) 144 | sprintf(url,"%s/module/ImagePost/%i?echoid=1",base_url,anyid); 145 | else if (anyid<1 && title) { 146 | char *tp = oauth_url_escape(title); 147 | sprintf(url,"%s/module/ImagePost/?title=%s",base_url,tp); 148 | free(tp); 149 | } 150 | else if (anyid>0 && title) { 151 | char *tp = oauth_url_escape(title); 152 | sprintf(url,"%s/module/ImagePost/%i?echoid=1&title=%s",base_url,anyid,tp); 153 | free(tp); 154 | } 155 | 156 | // doit 157 | switch(oauth_image_post(filename, url)) { 158 | case 0: 159 | printf("request ok.\n"); 160 | break; 161 | default: 162 | printf("upload failed.\n"); 163 | break; 164 | } 165 | return(0); 166 | } 167 | -------------------------------------------------------------------------------- /tests/commontest.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief test and example code for liboauth. 3 | * @file commontest.c 4 | * @author Robin Gareus 5 | * 6 | * Copyright 2007, 2008, 2012 Robin Gareus 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #ifdef TEST_UNICODE 28 | #include 29 | #endif 30 | 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #include "commontest.h" 37 | 38 | extern int loglevel; //< report each successful test 39 | 40 | /* 41 | * test parameter encoding 42 | */ 43 | int test_encoding(char *param, char *expected) { 44 | int rv=0; 45 | char *testcase=NULL; 46 | testcase = oauth_url_escape(param); 47 | if (strcmp(testcase,expected)) { 48 | rv=1; 49 | printf("parameter encoding test for '%s' failed.\n" 50 | " got: '%s' expected: '%s'\n", param, testcase, expected); 51 | } 52 | else if (loglevel) printf("parameter encoding ok. ('%s')\n", testcase); 53 | if (testcase) free(testcase); 54 | return (rv); 55 | } 56 | 57 | #ifdef TEST_UNICODE 58 | /* 59 | * test unicode paramter encoding 60 | */ 61 | int test_uniencoding(wchar_t *src, char *expected) { 62 | size_t n; 63 | char *dst; 64 | // check unicode: http://www.thescripts.com/forum/thread223350.html 65 | const char *encoding = "en_US.UTF-8"; // or try en_US.ISO-8859-1 etc. 66 | //wchar_t src[] = {0x0080, 0}; 67 | 68 | if(setlocale(LC_CTYPE, encoding) == NULL) { 69 | printf("requested encoding unavailable\n"); 70 | return -1; 71 | } 72 | 73 | n = wcstombs(NULL, src, 0); 74 | dst = malloc(n + 1); 75 | if(dst == NULL) { 76 | printf("memory allocation failed\n"); 77 | return -2; 78 | } 79 | if(wcstombs(dst, src, n + 1) != n) { 80 | printf("conversion failed\n"); 81 | free(dst); 82 | return -3; 83 | } 84 | return test_encoding(dst, expected); 85 | } 86 | #endif 87 | 88 | /* 89 | * test request normalization 90 | */ 91 | int test_normalize(char *param, char *expected) { 92 | int rv=2; 93 | int i, argc; 94 | char **argv = NULL; 95 | char *testcase; 96 | 97 | argc = oauth_split_url_parameters(param, &argv); 98 | qsort(argv, argc, sizeof(char *), oauth_cmpstringp); 99 | testcase= oauth_serialize_url(argc,0, argv); 100 | 101 | rv=strcmp(testcase,expected); 102 | if (rv) { 103 | printf("parameter normalization test failed for: '%s'.\n" 104 | " got: '%s' expected: '%s'\n", param, testcase, expected); 105 | } 106 | else if (loglevel) printf("parameter normalization ok. ('%s')\n", testcase); 107 | for (i=0;i 5 | * 6 | * Copyright 2008, 2010 Robin Gareus 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | /** 33 | * split and parse URL parameters replied by the test-server 34 | * into oauth_token and oauth_token_secret. 35 | */ 36 | int parse_reply(const char *reply, char **token, char **secret) { 37 | int rc; 38 | int ok=1; 39 | char **rv = NULL; 40 | rc = oauth_split_url_parameters(reply, &rv); 41 | qsort(rv, rc, sizeof(char *), oauth_cmpstringp); 42 | if( rc==2 43 | && !strncmp(rv[0],"oauth_token=",11) 44 | && !strncmp(rv[1],"oauth_token_secret=",18) ) { 45 | ok=0; 46 | if (token) *token =strdup(&(rv[0][12])); 47 | if (secret) *secret=strdup(&(rv[1][19])); 48 | printf("key: '%s'\nsecret: '%s'\n",*token, *secret); // XXX token&secret may be NULL. 49 | } 50 | if(rv) free(rv); 51 | return ok; 52 | } 53 | 54 | /** 55 | * an example requesting a request-token from an OAuth service-provider 56 | * exchaning it with an access token 57 | * and make an example request. 58 | * exercising either the oauth-HTTP GET or POST function. 59 | */ 60 | int oauth_consumer_example(int use_post) { 61 | const char *request_token_uri = "http://term.ie/oauth/example/request_token.php"; 62 | const char *access_token_uri = "http://term.ie/oauth/example/access_token.php"; 63 | const char *test_call_uri = "http://term.ie/oauth/example/echo_api.php?method=foo%20bar&bar=baz"; 64 | const char *c_key = "key"; //< consumer key 65 | const char *c_secret = "secret"; //< consumer secret 66 | 67 | char *t_key = NULL; //< access token key 68 | char *t_secret = NULL; //< access token secret 69 | 70 | char *req_url = NULL; 71 | char *postarg = NULL; 72 | char *reply = NULL; 73 | 74 | printf("Request token..\n"); 75 | if (use_post) { // HTTP POST 76 | req_url = oauth_sign_url2(request_token_uri, &postarg, OA_HMAC, NULL, c_key, c_secret, NULL, NULL); 77 | reply = oauth_http_post(req_url,postarg); 78 | } else { // HTTP GET 79 | req_url = oauth_sign_url2(request_token_uri, NULL, OA_HMAC, NULL, c_key, c_secret, NULL, NULL); 80 | reply = oauth_http_get(req_url,postarg); 81 | } 82 | if (req_url) free(req_url); 83 | if (postarg) free(postarg); 84 | if (!reply) return(1); 85 | if (parse_reply(reply, &t_key, &t_secret)) return(2); 86 | free(reply); 87 | 88 | // The Request Token provided above is already authorized, for this test server 89 | // so we may use it to request an Access Token right away. 90 | 91 | printf("Access token..\n"); 92 | 93 | if (use_post) { 94 | req_url = oauth_sign_url2(access_token_uri, &postarg, OA_HMAC, NULL, c_key, c_secret, t_key, t_secret); 95 | reply = oauth_http_post(req_url,postarg); 96 | } else { 97 | req_url = oauth_sign_url2(access_token_uri, NULL, OA_HMAC, NULL, c_key, c_secret, t_key, t_secret); 98 | reply = oauth_http_get(req_url,postarg); 99 | } 100 | if (req_url) free(req_url); 101 | if (postarg) free(postarg); 102 | if (!reply) return(3); 103 | if(t_key) free(t_key); 104 | if(t_secret) free(t_secret); 105 | if (parse_reply(reply, &t_key, &t_secret)) return(4); 106 | free(reply); 107 | 108 | printf("make some request..\n"); 109 | 110 | if (use_post) { 111 | req_url = oauth_sign_url2(test_call_uri, &postarg, OA_HMAC, NULL, c_key, c_secret, t_key, t_secret); 112 | reply = oauth_http_post(req_url,postarg); 113 | } else { 114 | req_url = oauth_sign_url2(test_call_uri, NULL, OA_HMAC, NULL, c_key, c_secret, t_key, t_secret); 115 | reply = oauth_http_get(req_url,postarg); 116 | } 117 | printf("query:'%s'\n",req_url); 118 | printf("reply:'%s'\n",reply); 119 | if(req_url) free(req_url); 120 | if(postarg) free(postarg); 121 | 122 | if (strcmp(reply,"bar=baz&method=foo+bar")) return (5); 123 | 124 | if(reply) free(reply); 125 | if(t_key) free(t_key); 126 | if(t_secret) free(t_secret); 127 | 128 | return(0); 129 | } 130 | 131 | 132 | /** 133 | * Main Test and Example Code. 134 | * 135 | * compile: 136 | * gcc -lssl -loauth -o oauthexample oauthexample.c 137 | */ 138 | 139 | int main (int argc, char **argv) { 140 | switch(oauth_consumer_example(0)) { 141 | case 1: 142 | printf("HTTP request for an oauth request-token failed.\n"); 143 | break; 144 | case 2: 145 | printf("did not receive a request-token.\n"); 146 | break; 147 | case 3: 148 | printf("HTTP request for an oauth access-token failed.\n"); 149 | break; 150 | case 4: 151 | printf("did not receive an access-token.\n"); 152 | break; 153 | case 5: 154 | printf("test call 'echo-api' did not respond correctly.\n"); 155 | break; 156 | default: 157 | printf("request ok.\n"); 158 | break; 159 | } 160 | return(0); 161 | } 162 | -------------------------------------------------------------------------------- /LICENSE.OpenSSL: -------------------------------------------------------------------------------- 1 | Certain source files in this program permit linking with the OpenSSL 2 | library (http://www.openssl.org), which otherwise wouldn't be allowed 3 | under the GPL. For purposes of identifying OpenSSL, most source files 4 | giving this permission limit it to versions of OpenSSL having a license 5 | identical to that listed in this file (LICENSE.OpenSSL). It is not 6 | necessary for the copyright years to match between this file and the 7 | OpenSSL version in question. However, note that because this file is 8 | an extension of the license statements of these source files, this file 9 | may not be changed except with permission from all copyright holders 10 | of source files in this program which reference this file. 11 | 12 | 13 | LICENSE ISSUES 14 | ============== 15 | 16 | The OpenSSL toolkit stays under a dual license, i.e. both the conditions of 17 | the OpenSSL License and the original SSLeay license apply to the toolkit. 18 | See below for the actual license texts. Actually both licenses are BSD-style 19 | Open Source licenses. In case of any license issues related to OpenSSL 20 | please contact openssl-core@openssl.org. 21 | 22 | OpenSSL License 23 | --------------- 24 | 25 | /* ==================================================================== 26 | * Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved. 27 | * 28 | * Redistribution and use in source and binary forms, with or without 29 | * modification, are permitted provided that the following conditions 30 | * are met: 31 | * 32 | * 1. Redistributions of source code must retain the above copyright 33 | * notice, this list of conditions and the following disclaimer. 34 | * 35 | * 2. Redistributions in binary form must reproduce the above copyright 36 | * notice, this list of conditions and the following disclaimer in 37 | * the documentation and/or other materials provided with the 38 | * distribution. 39 | * 40 | * 3. All advertising materials mentioning features or use of this 41 | * software must display the following acknowledgment: 42 | * "This product includes software developed by the OpenSSL Project 43 | * for use in the OpenSSL Toolkit. (http://www.openssl.org/)" 44 | * 45 | * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 46 | * endorse or promote products derived from this software without 47 | * prior written permission. For written permission, please contact 48 | * openssl-core@openssl.org. 49 | * 50 | * 5. Products derived from this software may not be called "OpenSSL" 51 | * nor may "OpenSSL" appear in their names without prior written 52 | * permission of the OpenSSL Project. 53 | * 54 | * 6. Redistributions of any form whatsoever must retain the following 55 | * acknowledgment: 56 | * "This product includes software developed by the OpenSSL Project 57 | * for use in the OpenSSL Toolkit (http://www.openssl.org/)" 58 | * 59 | * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 60 | * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 61 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 62 | * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 63 | * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 64 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 65 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 66 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 67 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 68 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 69 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 70 | * OF THE POSSIBILITY OF SUCH DAMAGE. 71 | * ==================================================================== 72 | * 73 | * This product includes cryptographic software written by Eric Young 74 | * (eay@cryptsoft.com). This product includes software written by Tim 75 | * Hudson (tjh@cryptsoft.com). 76 | * 77 | */ 78 | 79 | Original SSLeay License 80 | ----------------------- 81 | 82 | /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com) 83 | * All rights reserved. 84 | * 85 | * This package is an SSL implementation written 86 | * by Eric Young (eay@cryptsoft.com). 87 | * The implementation was written so as to conform with Netscapes SSL. 88 | * 89 | * This library is free for commercial and non-commercial use as long as 90 | * the following conditions are aheared to. The following conditions 91 | * apply to all code found in this distribution, be it the RC4, RSA, 92 | * lhash, DES, etc., code; not just the SSL code. The SSL documentation 93 | * included with this distribution is covered by the same copyright terms 94 | * except that the holder is Tim Hudson (tjh@cryptsoft.com). 95 | * 96 | * Copyright remains Eric Young's, and as such any Copyright notices in 97 | * the code are not to be removed. 98 | * If this package is used in a product, Eric Young should be given attribution 99 | * as the author of the parts of the library used. 100 | * This can be in the form of a textual message at program startup or 101 | * in documentation (online or textual) provided with the package. 102 | * 103 | * Redistribution and use in source and binary forms, with or without 104 | * modification, are permitted provided that the following conditions 105 | * are met: 106 | * 1. Redistributions of source code must retain the copyright 107 | * notice, this list of conditions and the following disclaimer. 108 | * 2. Redistributions in binary form must reproduce the above copyright 109 | * notice, this list of conditions and the following disclaimer in the 110 | * documentation and/or other materials provided with the distribution. 111 | * 3. All advertising materials mentioning features or use of this software 112 | * must display the following acknowledgement: 113 | * "This product includes cryptographic software written by 114 | * Eric Young (eay@cryptsoft.com)" 115 | * The word 'cryptographic' can be left out if the rouines from the library 116 | * being used are not cryptographic related :-). 117 | * 4. If you include any Windows specific code (or a derivative thereof) from 118 | * the apps directory (application code) you must include an acknowledgement: 119 | * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)" 120 | * 121 | * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND 122 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 123 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 124 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 125 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 126 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 127 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 128 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 129 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 130 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 131 | * SUCH DAMAGE. 132 | * 133 | * The licence and distribution terms for any publically available version or 134 | * derivative of this code cannot be changed. i.e. this code cannot simply be 135 | * copied and put under another distribution licence 136 | * [including the GNU Public Licence.] 137 | */ 138 | -------------------------------------------------------------------------------- /tests/oauthtest.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief self-test and example code for liboauth 3 | * @file oauthtest.c 4 | * @author Robin Gareus 5 | * 6 | * Copyright 2007, 2008, 2010 Robin Gareus 7 | * 8 | * Permission is hereby granted, free of charge, to any person obtaining a copy 9 | * of this software and associated documentation files (the "Software"), to deal 10 | * in the Software without restriction, including without limitation the rights 11 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 12 | * copies of the Software, and to permit persons to whom the Software is 13 | * furnished to do so, subject to the following conditions: 14 | * 15 | * The above copyright notice and this permission notice shall be included in 16 | * all copies or substantial portions of the Software. 17 | * 18 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 19 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 21 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 22 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 23 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 24 | * THE SOFTWARE. 25 | */ 26 | 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | /* 33 | * a example requesting and parsing a request-token from an OAuth service-provider 34 | * excercising the oauth-HTTP GET function. - it is almost the same as 35 | * \ref request_token_example_post below. 36 | */ 37 | void request_token_example_get(void) { 38 | #if 0 39 | const char *request_token_uri = "http://oauth-sandbox.mediamatic.nl/module/OAuth/request_token"; 40 | const char *req_c_key = "17b09ea4c9a4121145936f0d7d8daa28047583796"; //< consumer key 41 | const char *req_c_secret = "942295b08ffce77b399419ee96ac65be"; //< consumer secret 42 | #else 43 | const char *request_token_uri = "http://term.ie/oauth/example/request_token.php"; 44 | const char *req_c_key = "key"; //< consumer key 45 | const char *req_c_secret = "secret"; //< consumer secret 46 | #endif 47 | char *res_t_key = NULL; //< replied key 48 | char *res_t_secret = NULL; //< replied secret 49 | 50 | char *req_url = NULL; 51 | char *reply; 52 | 53 | req_url = oauth_sign_url2(request_token_uri, NULL, OA_HMAC, NULL, req_c_key, req_c_secret, NULL, NULL); 54 | 55 | printf("request URL:%s\n\n", req_url); 56 | reply = oauth_http_get(req_url,NULL); 57 | if (!reply) 58 | printf("HTTP request for an oauth request-token failed.\n"); 59 | else { 60 | // parse reply - example: 61 | //"oauth_token=2a71d1c73d2771b00f13ca0acb9836a10477d3c56&oauth_token_secret=a1b5c00c1f3e23fb314a0aa22e990266" 62 | int rc; 63 | char **rv = NULL; 64 | 65 | printf("HTTP-reply: %s\n", reply); 66 | rc = oauth_split_url_parameters(reply, &rv); 67 | qsort(rv, rc, sizeof(char *), oauth_cmpstringp); 68 | if( rc==2 69 | && !strncmp(rv[0],"oauth_token=",11) 70 | && !strncmp(rv[1],"oauth_token_secret=",18) ){ 71 | res_t_key=strdup(&(rv[0][12])); 72 | res_t_secret=strdup(&(rv[1][19])); 73 | printf("key: '%s'\nsecret: '%s'\n",res_t_key, res_t_secret); 74 | } 75 | if(rv) free(rv); 76 | } 77 | 78 | if(req_url) free(req_url); 79 | if(reply) free(reply); 80 | if(res_t_key) free(res_t_key); 81 | if(res_t_secret) free(res_t_secret); 82 | } 83 | 84 | /* 85 | * a example requesting and parsing a request-token from an OAuth service-provider 86 | * using the oauth-HTTP POST function. 87 | */ 88 | void request_token_example_post(void) { 89 | #if 0 90 | const char *request_token_uri = "http://oauth-sandbox.mediamatic.nl/module/OAuth/request_token"; 91 | const char *req_c_key = "17b09ea4c9a4121145936f0d7d8daa28047583796"; //< consumer key 92 | const char *req_c_secret = "942295b08ffce77b399419ee96ac65be"; //< consumer secret 93 | #else 94 | const char *request_token_uri = "http://term.ie/oauth/example/request_token.php"; 95 | const char *req_c_key = "key"; //< consumer key 96 | const char *req_c_secret = "secret"; //< consumer secret 97 | #endif 98 | char *res_t_key = NULL; //< replied key 99 | char *res_t_secret = NULL; //< replied secret 100 | 101 | char *postarg = NULL; 102 | char *req_url; 103 | char *reply; 104 | 105 | req_url = oauth_sign_url2(request_token_uri, &postarg, OA_HMAC, NULL, req_c_key, req_c_secret, NULL, NULL); 106 | 107 | printf("request URL:%s\n\n", req_url); 108 | reply = oauth_http_post(req_url,postarg); 109 | if (!reply) 110 | printf("HTTP request for an oauth request-token failed.\n"); 111 | else { 112 | //parse reply - example: 113 | //"oauth_token=2a71d1c73d2771b00f13ca0acb9836a10477d3c56&oauth_token_secret=a1b5c00c1f3e23fb314a0aa22e990266" 114 | int rc; 115 | char **rv = NULL; 116 | printf("HTTP-reply: %s\n", reply); 117 | rc = oauth_split_url_parameters(reply, &rv); 118 | qsort(rv, rc, sizeof(char *), oauth_cmpstringp); 119 | if( rc==2 120 | && !strncmp(rv[0],"oauth_token=",11) 121 | && !strncmp(rv[1],"oauth_token_secret=",18) ){ 122 | res_t_key=strdup(&(rv[0][12])); 123 | res_t_secret=strdup(&(rv[1][19])); 124 | printf("key: '%s'\nsecret: '%s'\n",res_t_key, res_t_secret); 125 | } 126 | if(rv) free(rv); 127 | } 128 | 129 | if(req_url) free(req_url); 130 | if(postarg) free(postarg); 131 | if(reply) free(reply); 132 | if(res_t_key) free(res_t_key); 133 | if(res_t_secret) free(res_t_secret); 134 | } 135 | 136 | 137 | /* 138 | * Main Test and Example Code. 139 | * 140 | * compile: 141 | * gcc -lssl -loauth -o oauthtest oauthtest.c 142 | */ 143 | int main (int argc, char **argv) { 144 | int fail=0; 145 | 146 | const char *url = "http://base.url/&just=append?post=or_get_parameters" 147 | "&arguments=will_be_formatted_automatically?&dont_care" 148 | "=about_separators"; 149 | //< the url to sign 150 | const char *c_key = "1234567890abcdef1234567890abcdef123456789"; 151 | //< consumer key 152 | const char *c_secret = "01230123012301230123012301230123"; 153 | //< consumer secret 154 | const char *t_key = "0987654321fedcba0987654321fedcba098765432"; 155 | //< token key 156 | const char *t_secret = "66666666666666666666666666666666"; 157 | //< token secret 158 | 159 | #if 1 // example sign GET request and print the signed request URL 160 | { 161 | char *geturl = NULL; 162 | geturl = oauth_sign_url2(url, NULL, OA_HMAC, NULL, c_key, c_secret, t_key, t_secret); 163 | printf("GET: URL:%s\n\n", geturl); 164 | if(geturl) free(geturl); 165 | } 166 | #endif 167 | 168 | #if 1 // sign POST ;) example 169 | { 170 | char *postargs = NULL, *post = NULL; 171 | post = oauth_sign_url2(url, &postargs, OA_HMAC, NULL, c_key, c_secret, t_key, t_secret); 172 | printf("POST: URL:%s\n PARAM:%s\n\n", post, postargs); 173 | if(post) free(post); 174 | if(postargs) free(postargs); 175 | } 176 | #endif 177 | 178 | printf(" *** sending HTTP request *** \n\n"); 179 | 180 | // These two will perform a HTTP request, requesting an access token. 181 | // it's intended both as test (verify signature) 182 | // and example code. 183 | #if 1 // POST a request-token request 184 | request_token_example_post(); 185 | #endif 186 | #if 1 // GET a request-token 187 | request_token_example_get(); 188 | #endif 189 | 190 | return (fail?1:0); 191 | } 192 | -------------------------------------------------------------------------------- /doc/mainpage.dox.in: -------------------------------------------------------------------------------- 1 | /** 2 | @mainpage OAuth library functions 3 | 4 | @section intro Introduction 5 | 6 | liboauth is a collection of POSIX-c functions implementing the OAuth Core RFC 5849 standard. 7 | liboauth provides functions to escape and encode parameters according to OAuth specification and offers high-level functionality to sign requests or verify OAuth signatures as well as perform HTTP requests. 8 | 9 | liboauth depends on either on the OpenSSL library or on 10 | NSS (Mozilla's Network Security Services) 11 | , which are used for generating the hash/signature, and optionally libcurl for issuing HTTP requests. 12 | 13 | The source includes example code and a self-tests based on http://wiki.oauth.net/TestCases. The library has been tested against the http://oauth-sandbox.mediamatic.nl (now offline) and http://term.ie/oauth/example test servers using commandline-cURL, libcurl and a QT4.3.2 QHttp C++ application on win32 (mingw), gnu/Linux and Mac/OSX. 14 | 15 | @section installation Installation 16 | The source is debianized. On Debian systems debian-buildpackage can be used to compile and dpkg -i to install liboauth and liboauth-dev packages. 17 | 18 | liboauth uses autotools and libtools. The tar.gz package includes the configure script, but if you get the source from the repository, you first need to generate the build environment with something alike: 19 | aclocal; autoheader; libtoolize --copy; autoconf; automake --gnu --add-missing --copy. (OSX users use glibtoolize). 20 | 21 | run ./configure and build liboauth with make. see the INSTALL file for further instructions on gnu autotools. 22 | 23 | run ./configure --help for information on optional features (--disable-curl, --disable-libcurl, --enable-nss, --with-curltimeout[=<int>]). 24 | 25 | If Doxygen is available, the documentation can be rendered from the source by calling make dox. The http://wiki.oauth.net/TestCases scenarios in the example code can be run with make check. 26 | 27 | @section usage Usage 28 | Consult \ref oauth.h for a detailed reference of available functions. This documentation is also available as unix manual page: man 3 oauth. 29 | 30 | See tests/oauthtest.c for the self-test code and example. tests/oauthexample.c implements a simple hardcoded OAuth-consumer. 31 | If you simply want to calculate the OAuth-signature, all you need is \ref oauth_sign_url. 32 | Future releases might include more elaborate usage information: Feel free to ask questions. 33 | 34 | oauth-utils includes a command-line OAuth-consumer and signature-verification tool using liboauth. 35 | 36 | @section usage Built-in HTTP client 37 | The curl wrapper interface should never have been part of libOauth. It came in handy during initial development and test deployments, and by the time I wanted to remove it, there were already too many users... 38 | 39 | It is still convenient for self-tests and getting started, but application developers should rather aim for a dedicated optimized implementation appropriate for each app. 40 | 41 | oauth_http.c does not do any error-handling for instance, also SSL certificate checking and/or similar CURL options depend on the use-case at hand. Furthermore the available curl options and parameters in oauth_http.c are limited. 42 | 43 | Therefore with the release of version 1.0.0 all oauth_http functions have been marked as deprecated. 44 | 45 | Developers of applications using oauth_http.c are advised to simply copy the relevent code into their application (the MIT license is very permissive) and adopt it, if neccesary. 46 | 47 | @section download Download 48 | 49 | Download Source: liboauth-@VERSION@.tar.gz 50 |  Changelog. 51 | 52 | liboauth is maintained at github: 53 | liboauth repository and mirrored at the OAuth googlecode SVN repository. 54 | 55 | 58 | 59 | @section bug Bugs 60 | Send bug reports, patches or suggestions to robin @ gareus . org. 61 | 62 | Ask the oauth-community or join the mailing list for discussion. 63 | 64 | @section license License 65 | The source-code of liboauth can be distributed under MIT License, 66 | or at your option in terms of the the GNU General Public License. 67 | 68 | Note: OpenSSL is not strictly compatible with the GPL license. 69 | An exemption (to the GPL) allowing to link and redistribute liboauth with the OpenSSL library is is included in the source files. 70 | More information is available in the 71 | README. 72 | You can avoid this whole issue by using NSS instead of OpenSSL, configuring liboauth with --enable-nss. 73 | 74 | The Debian packaging that comes with the source-code is licensed under the GNU General Public License. 75 | 76 | MIT License (source-code): 77 |
 78 |   Copyright 2007-2012 Robin Gareus
 79 | 
 80 |   Permission is hereby granted, free of charge, to any person obtaining a copy
 81 |   of this software and associated documentation files (the "Software"), to deal
 82 |   in the Software without restriction, including without limitation the rights
 83 |   to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 84 |   copies of the Software, and to permit persons to whom the Software is
 85 |   furnished to do so, subject to the following conditions:
 86 | 
 87 |   The above copyright notice and this permission notice shall be included in
 88 |   all copies or substantial portions of the Software.
 89 | 
 90 |   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 91 |   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 92 |   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 93 |   AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 94 |   LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 95 |   OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 96 |   THE SOFTWARE.
 97 | 
98 | 99 | GPL (Debian packaging and alternative source-code license): 100 |
101 |   This package is free software; you can redistribute it and/or
102 |   modify it under the terms of the GNU General Public
103 |   License as published by the Free Software Foundation; either
104 |   version 2 of the License, or (at your option) any later version.
105 | 
106 |   This package is distributed in the hope that it will be useful,
107 |   but WITHOUT ANY WARRANTY; without even the implied warranty of
108 |   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
109 |   General Public License for more details.
110 | 
111 |   You should have received a copy of the GNU General Public
112 |   License along with this package; if not, write to the Free Software
113 |   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
114 | 
115 | 116 | \example tests/oauthtest.c 117 | \example tests/oauthtest2.c 118 | \example tests/oauthexample.c 119 | \example tests/oauthbodyhash.c 120 | \example tests/selftest_wiki.c 121 | */ 122 | -------------------------------------------------------------------------------- /ChangeLog: -------------------------------------------------------------------------------- 1 | version 1.0.3 2 | - clarify documentation of oauth_curl 3 | - fix possible memleak in oauth_curl (only relevant if an error occurs) 4 | - fix TOCTOU in oauth_curl_post_file: the file may change between stat() and fopen() 5 | 6 | version 1.0.2 7 | - fix typos in documentation 8 | - add xfree, xstrdup patch from Kedar Sovani 9 | - prepare repository migration to github 10 | - built-in sha1 support big&little endian 11 | - (no changes to the actual library API or ABI) 12 | 13 | version 1.0.1 14 | - do not url-escape RSA-key for signature 15 | 16 | version 1.0.0 17 | - fix body-hash example code 18 | - mark all oauth_http functions a deprecated 19 | - freeze interface defitions for good 20 | - enter maintenance/bug-fix only cycle 21 | 22 | version 0.9.7 23 | - fixed tiny memory leak when oauth_curl_get() fails 24 | - fixed double-encoding of plaintext signature 25 | 26 | version 0.9.6 27 | - fixed typo, do not print a separator before first parameter 28 | when serializing url for auth-header. 29 | 30 | version 0.9.5 31 | - added "built-in" hmac-sha1 hashing (no RSA). 32 | - added some CURL options available via enviroment variables 33 | - fixed issue with decoding already encoded characters 34 | in the base-URL (not parameters). 35 | reported by L. Alberto Giménez 36 | 37 | version 0.9.4 38 | - fixed possible memory corrution in oauth_curl_get 39 | thanks to Bruce Rosen for reporting this issue 40 | 41 | version 0.9.3 42 | - yet more build-system fixes: 43 | - allow to override HASH_LIBS and CURL_LIBS using envoronment variables 44 | - include them in .pc and tests/Makefile.am 45 | 46 | version 0.9.2 47 | - fixed typo in build-system (LDFLAGS, -Wl,--as-needed detection) 48 | 49 | version 0.9.1 50 | - fixed typo in API: 51 | oauth_time_indepenent_equals[_n] is now deprecated in favor of 52 | oauth_time_independent_equals[_n] 53 | - added check for 'Wl,--as-needed' linker flag. 54 | 55 | version 0.9.0 56 | - fixed typo in pkg-config file. 57 | 58 | version 0.8.9 59 | - added constant-time string compare function motivated by 60 | http://rdist.root.org/2010/01/07/timing-independent-array-comparison/ 61 | - updated the build-system 62 | - avoid indirect linking (curl, ssl) 63 | - AS_IF expansion for PKG_PROG_PKG_CONFIG 64 | - only build tests when running `make check` 65 | 66 | version 0.8.8 67 | minor changes to the build-system 68 | - allow to overrice HASH_LIBS/CFLAGS (NSS, SpenSSL) 69 | - fixes for static linking in src/Makefile.am 70 | 71 | version 0.8.7 72 | fixed whitespace in interface revision number 73 | fixed test-build system: 74 | - unhardcode -lssl 75 | - add CFLAGS_CURL 76 | 77 | version 0.8.6 78 | removed non-posix prototypes 79 | 80 | version 0.8.5 81 | cleaned up man-page & added logo to html doc. 82 | 83 | version 0.8.4 84 | fixed pkgconfig dependencies (OpenSSL vs NSS) 85 | 86 | version 0.8.3 87 | added an interface to generate an OAuth HTTP Authorization header 88 | and oauth_http_[get|post]2 to preform such requests, 89 | as well as example code 'oauthtest2' to do so. 90 | 91 | version 0.8.2 92 | fixed potential NULL pointer exception when sorting 93 | duplicate URL parameters without value. 94 | It's a extremly rare edge-case - there's no practial 95 | use for duplicate empty URL parameters - but it could 96 | be used as a DOS attack-vector. 97 | 98 | version 0.8.1 99 | replaced a few forgotten mallocs with xmalloc. 100 | 101 | version 0.8.0 102 | replaced xmalloc with custom MIT-licensed version. 103 | removed --enable-gpl configure option. 104 | minor updates to README, documentation, etc. 105 | 106 | version 0.7.2 107 | added NSS as alternative to OpenSSL. 108 | use OpenSSL or NSS random number generator for nonce. 109 | 110 | version 0.7.1 111 | proper naming: replaced oAuth -> OAuth. 112 | fixed a few typos in the documentation. 113 | 114 | version 0.7.0 115 | resolved licensing issues: 116 | * xmalloc = GPL 117 | * openSSL & GPL exemption 118 | 119 | version 0.6.3 120 | also use curl timeout for commandline curl 121 | renamed --with-libcurl-timeout to --with-curl-timeout 122 | 123 | version 0.6.2 124 | added CURLOPT_TIMEOUT option. 125 | available at compile time with configure --with-libcurl-timeout= 126 | 127 | version 0.6.1 128 | added oauth_curl_send_data_with_callback 129 | to use HTTP-methods other than GET&POST with libcurl. 130 | 131 | version 0.6.0 132 | configure options to disable curl & libcurl 133 | replaced tabs with spaces in source 134 | 135 | version 0.5.4 136 | added oauth_post_data_with_callback() and 137 | fixes for MSVC/WIN32 platform 138 | by Dave Gamble 139 | 140 | version 0.5.3 141 | added oauth_body_hash calulation 142 | support for HTTP Posting data from memory. 143 | 144 | version 0.5.2 145 | added support for HTTP request methods other than GET & POST. 146 | 147 | version 0.5.1 148 | added oauth_sign_array() function - which allows to modify the parameters 149 | before siging them. 150 | fixed url-splitting to url-decode parameters when generating the parameter 151 | array. 152 | 153 | version 0.5.0 154 | fixed debian package liboauth -> liboauth0 155 | minor fixes in the manual 156 | else unchanged it's 0.4.5 after six month of stress tests in production 157 | 158 | version 0.4.5 159 | fixed dependencies in pkgconfig pc.in 160 | 161 | version 0.4.4 162 | libtool interface version number 163 | 164 | version 0.4.3 165 | added oauth_url_unescape() 166 | 167 | version 0.4.2 168 | fixed escaping of PLAINTEXT signature. 169 | 170 | version 0.4.1 171 | added oauth_serialize_url_sep() 172 | and OAUTH_VERSION defines in header file. 173 | 174 | version 0.4.0 175 | release on googlecode under MIT license 176 | and on sourceforge/debian under LGPL 177 | 178 | version 0.3.4 179 | allow to configure MIT only or LGPL licensed code (xmalloc) 180 | reorganized tests 181 | removed mixed declarations and code 182 | 183 | version 0.3.3 184 | added Eran's test-cases. 185 | removing ':80' portnumber from URL before signing 186 | when splitting URL parameters: use '\001' as request param value as alias for ampersand ('&') 187 | 188 | version 0.3.2 189 | added NULL uri check to oauth_split_post_paramters() 190 | testcode comment updates. 191 | 192 | version 0.3.1 193 | added #ifndef _OAUTH_H to header - avoid double include errors 194 | fixed some typos in the doc. 195 | 196 | version 0.3.0 197 | prefixed all public oauth.h functions with "oauth_" 198 | added RSA-SHA1 signature support 199 | 200 | version 0.2.4 201 | detect absoluteURI by ":/" (it was /^http/) - used to detect empty abs_path 202 | added shell escape for (bash like) `sh` to invoke curl/wget 203 | cleaned up example code and doc a bit. 204 | 205 | version 0.2.3 206 | fixed '?' in GET URL¶meter concatenation 207 | added cURL HTTP-GET function and test/example code 208 | test/example code using http://term.ie/oauth/example/ 209 | 210 | version 0.2.2 211 | fixed "empty HTTP Paths" see http://wiki.oauth.net/TestCases and 212 | http://groups.google.com/group/oauth/browse_thread/thread/c44b6f061bfd98c?hl=en 213 | fixed some compiler warnings 214 | made signature function args 'const char *' 215 | and mem-zero some possibly sensitive strings before free()ing them. 216 | 217 | version 0.2.1 218 | prepared for MIT license 219 | all c sources and headers by Robin Gareus are now MIT licensed. 220 | 221 | version 0.2.0 222 | updated documentation 223 | fixed configure.ac 224 | 225 | version 0.1.3 226 | removed getpid() on random-number initialization for win. 227 | moving to sourceforge. 228 | 229 | version 0.1.2 230 | different handlers for POST and GET query string. Get escapes '+' to ' '. 231 | oauth_sign_url() returns escaped query string. 232 | added oauth_curl_post_file - preparing for xoauth_body_signature. 233 | updated test code. 234 | 235 | version 0.1.1 236 | fixed parameter normalization and sorting for some edge cases. 237 | added Test Cases from http://wiki.oauth.net/TestCases 238 | added simple HTTP POST using libcurl or a command-line HTTP client. 239 | 240 | version 0.1.0 241 | added xmalloc - removed NULL checks after [re|m|c]alloc. 242 | libtoolized and prepared packaging. 243 | fixed a couple of typos 244 | added a some more documentation. 245 | 246 | version 0.0.1 247 | first public release 248 | oAuth parameter escape and URL request signing functions. 249 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | liboauth (1.0.3-1) unstable; urgency=low 2 | * new upstream release 3 | -- Robin Gareus Thu, 17 Apr 2014 19:47:00 +0200 4 | 5 | liboauth (1.0.2-1) unstable; urgency=low 6 | * new upstream release 7 | -- Robin Gareus Mon, 17 Mar 2014 16:03:22 +0100 8 | 9 | liboauth (1.0.1-1) unstable; urgency=low 10 | * new upstream release 11 | -- Robin Gareus Sat, 09 Mar 2013 11:24:17 +0100 12 | 13 | liboauth (1.0.0-1) unstable; urgency=low 14 | * new upstream release 15 | -- Robin Gareus Thu, 01 Nov 2012 05:33:33 +0100 16 | 17 | liboauth (0.9.7-1) unstable; urgency=low 18 | * new upstream release 19 | -- Robin Gareus Wed, 04 Jul 2012 11:45:57 +0200 20 | 21 | liboauth (0.9.6-1) unstable; urgency=low 22 | * new upstream release 23 | -- Robin Gareus Tue, 13 Dec 2011 01:38:29 +0100 24 | 25 | liboauth (0.9.5-1) unstable; urgency=low 26 | * new upstream release 27 | -- Robin Gareus Thu, 22 Sep 2011 12:24:17 +0200 28 | 29 | liboauth (0.9.4-1) unstable; urgency=low 30 | * new upstream release 31 | -- Robin Gareus Wed, 26 Jan 2011 17:00:31 +0100 32 | 33 | liboauth (0.9.3-1) unstable; urgency=low 34 | * new upstream release 35 | -- Robin Gareus Tue, 18 Jan 2011 17:44:45 +0100 36 | 37 | liboauth (0.9.2-1) unstable; urgency=low 38 | * new upstream release 39 | -- Robin Gareus Thu, 13 Jan 2011 00:27:02 +0100 40 | 41 | liboauth (0.9.1-1) unstable; urgency=low 42 | * new upstream release 43 | -- Robin Gareus Mon, 13 Sep 2010 14:10:35 +0200 44 | 45 | liboauth (0.9.0-1) unstable; urgency=low 46 | * new upstream release 47 | -- Robin Gareus Tue, 07 Sep 2010 02:10:50 +0200 48 | 49 | liboauth (0.8.9-1) unstable; urgency=low 50 | * new upstream release 51 | -- Robin Gareus Mon, 30 Aug 2010 17:34:36 +0200 52 | 53 | liboauth (0.8.8-1) unstable; urgency=low 54 | * new upstream release 55 | -- Robin Gareus Tue, 08 Jun 2010 15:24:45 +0200 56 | 57 | liboauth (0.8.7-1) unstable; urgency=low 58 | * new upstream release 59 | -- Robin Gareus Wed, 02 Jun 2010 17:49:10 +0200 60 | 61 | liboauth (0.8.6-1) unstable; urgency=low 62 | * new upstream release 63 | -- Robin Gareus Tue, 01 Jun 2010 04:40:51 +0200 64 | 65 | liboauth (0.8.5-1) unstable; urgency=low 66 | * new upstream release 67 | -- Robin Gareus Sun, 23 May 2010 16:32:51 +0200 68 | 69 | liboauth (0.8.4-1) unstable; urgency=low 70 | * new upstream release 71 | -- Robin Gareus Sat, 22 May 2010 18:56:32 +0200 72 | 73 | liboauth (0.8.3-1) unstable; urgency=low 74 | * new upstream release 75 | -- Robin Gareus Sat, 22 May 2010 17:15:29 +0200 76 | 77 | liboauth (0.8.2-1) unstable; urgency=low 78 | * new upstream release 79 | -- Robin Gareus Sat, 22 May 2010 02:02:48 +0200 80 | 81 | liboauth (0.8.1-1) unstable; urgency=low 82 | * new upstream release 83 | -- Robin Gareus Sat, 22 May 2010 01:24:53 +0200 84 | 85 | liboauth (0.8.0-1) unstable; urgency=low 86 | * new upstream release 87 | -- Robin Gareus Fri, 21 May 2010 22:35:34 +0200 88 | 89 | liboauth (0.7.2-1) unstable; urgency=low 90 | * new upstream release 91 | -- Robin Gareus Fri, 21 May 2010 15:46:15 +0200 92 | 93 | liboauth (0.7.1-1) unstable; urgency=low 94 | * new upstream release 95 | -- Robin Gareus Fri, 21 May 2010 15:33:25 +0200 96 | 97 | liboauth (0.7.0-1) unstable; urgency=low 98 | * new upstream release 99 | -- Robin Gareus Thu, 20 May 2010 17:14:33 +0200 100 | 101 | liboauth (0.6.3-1) unstable; urgency=low 102 | * new upstream release 103 | -- Robin Gareus Sun, 16 May 2010 18:34:47 +0200 104 | 105 | liboauth (0.6.2-1) unstable; urgency=low 106 | * new upstream release 107 | -- Robin Gareus Sun, 16 May 2010 16:39:32 +0200 108 | 109 | liboauth (0.6.1-1) unstable; urgency=low 110 | * new upstream release 111 | -- Robin Gareus Fri, 18 Sep 2009 14:57:58 +0200 112 | 113 | liboauth (0.6.0-1) unstable; urgency=low 114 | * new upstream release 115 | -- Robin Gareus Fri, 04 Sep 2009 13:51:55 +0200 116 | 117 | liboauth (0.5.4-1) unstable; urgency=low 118 | * new upstream release 119 | -- Robin Gareus Mon, 24 Aug 2009 22:27:15 +0200 120 | 121 | liboauth (0.5.3-1) unstable; urgency=low 122 | * new upstream release 123 | -- Robin Gareus Mon, 17 Aug 2009 14:37:36 +0200 124 | 125 | liboauth (0.5.2-1) unstable; urgency=low 126 | * new upstream release 127 | -- Robin Gareus Thu, 06 Aug 2009 12:56:58 +0200 128 | 129 | liboauth (0.5.1-1) unstable; urgency=low 130 | * new upstream release 131 | -- Robin Gareus Tue, 02 Jun 2009 13:33:16 +0200 132 | 133 | liboauth (0.5.0-1) unstable; urgency=low 134 | * new upstream release 135 | -- Robin Gareus Sun, 15 Feb 2009 00:06:47 +0100 136 | 137 | liboauth (0.4.5-1) unstable; urgency=low 138 | * new upstream release 139 | -- Robin Gareus Sun, 19 Oct 2008 14:21:13 +0200 140 | 141 | liboauth (0.4.4-1) unstable; urgency=low 142 | * new upstream release 143 | -- Robin Gareus Sun, 19 Oct 2008 14:01:52 +0200 144 | 145 | liboauth (0.4.3-1) unstable; urgency=low 146 | * new upstream release 147 | -- Robin Gareus Sat, 18 Oct 2008 00:17:35 +0200 148 | 149 | liboauth (0.4.2-1) unstable; urgency=low 150 | * new upstream release 151 | -- Robin Gareus Fri, 17 Oct 2008 22:22:06 +0200 152 | 153 | liboauth (0.4.1-1) unstable; urgency=low 154 | * new upstream release 155 | -- Robin Gareus Thu, 16 Oct 2008 22:45:10 +0200 156 | 157 | liboauth (0.4.0-1) unstable; urgency=low 158 | * new upstream release 159 | -- Robin Gareus Wed, 17 Sep 2008 14:07:12 +0200 160 | 161 | liboauth (0.3.4-1) unstable; urgency=low 162 | * new upstream release 163 | -- Robin Gareus Wed, 17 Sep 2008 11:07:07 +0200 164 | 165 | liboauth (0.3.3-1) unstable; urgency=low 166 | * new upstream release 167 | -- Robin Gareus Fri, 12 Sep 2008 13:47:17 +0200 168 | 169 | liboauth (0.3.2-1) unstable; urgency=low 170 | * new upstream release 171 | -- Robin Gareus Fri, 29 Aug 2008 21:36:14 +0200 172 | 173 | liboauth (0.3.1-1) unstable; urgency=low 174 | * new upstream release 175 | -- Robin Gareus Thu, 28 Aug 2008 01:11:37 +0200 176 | 177 | liboauth (0.3.0-1) unstable; urgency=low 178 | * new upstream release 179 | -- Robin Gareus Sun, 24 Aug 2008 22:33:44 +0200 180 | 181 | liboauth (0.2.4-1) unstable; urgency=low 182 | * new upstream release 183 | -- Robin Gareus Sun, 24 Aug 2008 14:21:37 +0200 184 | 185 | liboauth (0.2.3-2) unstable; urgency=low 186 | * new upstream release 187 | -- Robin Gareus Sun, 24 Aug 2008 12:10:10 +0200 188 | 189 | liboauth (0.2.3-1) unstable; urgency=low 190 | * new upstream release 191 | -- Robin Gareus Sun, 24 Aug 2008 10:54:52 +0200 192 | 193 | liboauth (0.2.2-1) unstable; urgency=low 194 | * new upstream release 195 | -- Robin Gareus Sat, 23 Aug 2008 17:34:41 +0200 196 | 197 | liboauth (0.2.1-1) unstable; urgency=low 198 | * new upstream release 199 | -- Robin Gareus Wed, 13 Aug 2008 16:11:25 +0200 200 | 201 | liboauth (0.2.0-1) unstable; urgency=low 202 | * new upstream release 203 | -- Robin Gareus Sat, 09 Aug 2008 19:02:05 +0200 204 | 205 | liboauth (0.1.3-1) unstable; urgency=low 206 | * new upstream release 207 | -- Robin Gareus Wed, 23 Jul 2008 21:51:11 +0200 208 | 209 | liboauth (0.1.2-1) unstable; urgency=low 210 | * new upstream release 211 | 212 | -- Robin Gareus Thu, 31 Jan 2008 14:46:33 +0100 213 | 214 | liboauth (0.1.1-1) unstable; urgency=low 215 | * new upstream release 216 | 217 | -- Robin Gareus Mon, 07 Jan 2008 23:57:20 +0100 218 | 219 | liboauth (0.1.0-1) unstable; urgency=low 220 | 221 | * Initial release 222 | 223 | -- Robin Gareus Sun, 09 Dec 2007 22:01:34 +0100 224 | 225 | -------------------------------------------------------------------------------- /tests/selftest_wiki.c: -------------------------------------------------------------------------------- 1 | /** 2 | * @brief self-test for liboauth. 3 | * @file selftest.c 4 | * @author Robin Gareus 5 | * 6 | * Copyright 2007, 2008 Robin Gareus 7 | * 8 | * This code contains examples from http://wiki.oauth.net/ may they be blessed. 9 | * 10 | * Permission is hereby granted, free of charge, to any person obtaining a copy 11 | * of this software and associated documentation files (the "Software"), to deal 12 | * in the Software without restriction, including without limitation the rights 13 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 14 | * copies of the Software, and to permit persons to whom the Software is 15 | * furnished to do so, subject to the following conditions: 16 | * 17 | * The above copyright notice and this permission notice shall be included in 18 | * all copies or substantial portions of the Software. 19 | * 20 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 21 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 22 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 23 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 24 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 25 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 26 | * THE SOFTWARE. 27 | */ 28 | 29 | #ifdef TEST_UNICODE 30 | #include 31 | #endif 32 | 33 | #include 34 | #include 35 | #include 36 | #include 37 | 38 | #include "commontest.h" 39 | 40 | int loglevel = 1; //< report each successful test 41 | 42 | int main (int argc, char **argv) { 43 | int fail=0; 44 | char *b64d; 45 | char *testurl, *testkey; 46 | #ifdef TEST_UNICODE 47 | wchar_t src[] = {0x000A, 0}; 48 | #endif 49 | 50 | if (loglevel) printf("\n *** testing liboauth against http://wiki.oauth.net/TestCases (july 2008) ***\n"); 51 | 52 | // http://wiki.oauth.net/TestCases 53 | fail|=test_encoding("abcABC123","abcABC123"); 54 | fail|=test_encoding("-._~","-._~"); 55 | fail|=test_encoding("%","%25"); 56 | fail|=test_encoding("+","%2B"); 57 | fail|=test_encoding("&=*","%26%3D%2A"); 58 | 59 | #ifdef TEST_UNICODE 60 | src[0] = 0x000A; fail|=test_uniencoding(src,"%0A"); 61 | src[0] = 0x0020; fail|=test_uniencoding(src,"%20"); 62 | src[0] = 0x007F; fail|=test_uniencoding(src,"%7F"); 63 | src[0] = 0x0080; fail|=test_uniencoding(src,"%C2%80"); 64 | src[0] = 0x3001; fail|=test_uniencoding(src,"%E3%80%81"); 65 | #endif 66 | 67 | fail|=test_normalize("name", "name="); 68 | fail|=test_normalize("a=b", "a=b"); 69 | fail|=test_normalize("a=b&c=d", "a=b&c=d"); 70 | fail|=test_normalize("a=x!y&a=x+y", "a=x%20y&a=x%21y"); 71 | fail|=test_normalize("x!y=a&x=a", "x=a&x%21y=a"); 72 | 73 | fail|=test_request("GET", "http://example.com/" "?" 74 | "n=v", 75 | // expect: 76 | "GET&http%3A%2F%2Fexample.com%2F&n%3Dv"); 77 | 78 | fail|=test_request("GET", "http://example.com" "?" 79 | "n=v", 80 | // expect: 81 | "GET&http%3A%2F%2Fexample.com%2F&n%3Dv"); 82 | 83 | fail|=test_request("POST", "https://photos.example.net/request_token" "?" 84 | "oauth_version=1.0" 85 | "&oauth_consumer_key=dpf43f3p2l4k3l03" 86 | "&oauth_timestamp=1191242090" 87 | "&oauth_nonce=hsu94j3884jdopsl" 88 | "&oauth_signature_method=PLAINTEXT" 89 | "&oauth_signature=ignored", 90 | // expect: 91 | "POST&https%3A%2F%2Fphotos.example.net%2Frequest_token&oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dhsu94j3884jdopsl%26oauth_signature_method%3DPLAINTEXT%26oauth_timestamp%3D1191242090%26oauth_version%3D1.0"); 92 | 93 | fail|=test_request("GET", "http://photos.example.net/photos" "?" 94 | "file=vacation.jpg&size=original" 95 | "&oauth_version=1.0" 96 | "&oauth_consumer_key=dpf43f3p2l4k3l03" 97 | "&oauth_token=nnch734d00sl2jdk" 98 | "&oauth_timestamp=1191242096" 99 | "&oauth_nonce=kllo9940pd9333jh" 100 | "&oauth_signature=ignored" 101 | "&oauth_signature_method=HMAC-SHA1", 102 | // expect: 103 | "GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jdk%26oauth_version%3D1.0%26size%3Doriginal"); 104 | 105 | fail|=test_sha1("cs","","bs","egQqG5AJep5sJ7anhXju1unge2I="); 106 | fail|=test_sha1("cs","ts","bs","VZVjXceV7JgPq/dOTnNmEfO0Fv8="); 107 | fail|=test_sha1("kd94hf93k423kf44","pfkkdhi9sl3r4s00","GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacation.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26oauth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jdk%26oauth_version%3D1.0%26size%3Doriginal","tR3+Ty81lMeYAr/Fid0kMTYa/WM="); 108 | 109 | // HMAC-SHA1 selftest. 110 | // see http://oauth.net/core/1.0/#anchor25 111 | testurl = "GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3D" 112 | "vacation.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce" 113 | "%3Dkllo9940pd9333jh%26oauth_signature_method%3DHMAC-SHA1%26o" 114 | "auth_timestamp%3D1191242096%26oauth_token%3Dnnch734d00sl2jdk" 115 | "%26oauth_version%3D1.0%26size%3Doriginal"; 116 | 117 | testkey = "kd94hf93k423kf44&pfkkdhi9sl3r4s00"; 118 | b64d = oauth_sign_hmac_sha1(testurl , testkey); 119 | if (strcmp(b64d,"tR3+Ty81lMeYAr/Fid0kMTYa/WM=")) { 120 | printf("HMAC-SHA1 signature test failed.\n"); 121 | fail|=1; 122 | } else if (loglevel) 123 | printf("HMAC-SHA1 signature test successful.\n"); 124 | free(b64d); 125 | 126 | // rsa-signature based on http://wiki.oauth.net/TestCases example 127 | b64d = oauth_sign_rsa_sha1( 128 | "GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacaction.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3D13917289812797014437%26oauth_signature_method%3DRSA-SHA1%26oauth_timestamp%3D1196666512%26oauth_version%3D1.0%26size%3Doriginal", 129 | 130 | "-----BEGIN PRIVATE KEY-----\n" 131 | "MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBALRiMLAh9iimur8V\n" 132 | "A7qVvdqxevEuUkW4K+2KdMXmnQbG9Aa7k7eBjK1S+0LYmVjPKlJGNXHDGuy5Fw/d\n" 133 | "7rjVJ0BLB+ubPK8iA/Tw3hLQgXMRRGRXXCn8ikfuQfjUS1uZSatdLB81mydBETlJ\n" 134 | "hI6GH4twrbDJCR2Bwy/XWXgqgGRzAgMBAAECgYBYWVtleUzavkbrPjy0T5FMou8H\n" 135 | "X9u2AC2ry8vD/l7cqedtwMPp9k7TubgNFo+NGvKsl2ynyprOZR1xjQ7WgrgVB+mm\n" 136 | "uScOM/5HVceFuGRDhYTCObE+y1kxRloNYXnx3ei1zbeYLPCHdhxRYW7T0qcynNmw\n" 137 | "rn05/KO2RLjgQNalsQJBANeA3Q4Nugqy4QBUCEC09SqylT2K9FrrItqL2QKc9v0Z\n" 138 | "zO2uwllCbg0dwpVuYPYXYvikNHHg+aCWF+VXsb9rpPsCQQDWR9TT4ORdzoj+Nccn\n" 139 | "qkMsDmzt0EfNaAOwHOmVJ2RVBspPcxt5iN4HI7HNeG6U5YsFBb+/GZbgfBT3kpNG\n" 140 | "WPTpAkBI+gFhjfJvRw38n3g/+UeAkwMI2TJQS4n8+hid0uus3/zOjDySH3XHCUno\n" 141 | "cn1xOJAyZODBo47E+67R4jV1/gzbAkEAklJaspRPXP877NssM5nAZMU0/O/NGCZ+\n" 142 | "3jPgDUno6WbJn5cqm8MqWhW1xGkImgRk+fkDBquiq4gPiT898jusgQJAd5Zrr6Q8\n" 143 | "AO/0isr/3aa6O6NLQxISLKcPDk2NOccAfS/xOtfOz4sJYM3+Bs4Io9+dZGSDCA54\n" 144 | "Lw03eHTNQghS0A==\n" 145 | "-----END PRIVATE KEY-----"); 146 | 147 | if (strcmp(b64d,"jvTp/wX1TYtByB1m+Pbyo0lnCOLIsyGCH7wke8AUs3BpnwZJtAuEJkvQL2/9n4s5wUmUl4aCI4BwpraNx4RtEXMe5qg5T1LVTGliMRpKasKsW//e+RinhejgCuzoH26dyF8iY2ZZ/5D1ilgeijhV/vBka5twt399mXwaYdCwFYE=")) { 148 | printf("RSA-SHA1 signature test failed.\n"); 149 | fail|=1; 150 | } else if (loglevel) 151 | printf("RSA-SHA1 signature test successful.\n"); 152 | free(b64d); 153 | 154 | if (oauth_verify_rsa_sha1( 155 | "GET&http%3A%2F%2Fphotos.example.net%2Fphotos&file%3Dvacaction.jpg%26oauth_consumer_key%3Ddpf43f3p2l4k3l03%26oauth_nonce%3D13917289812797014437%26oauth_signature_method%3DRSA-SHA1%26oauth_timestamp%3D1196666512%26oauth_version%3D1.0%26size%3Doriginal", 156 | 157 | "-----BEGIN CERTIFICATE-----\n" 158 | "MIIBpjCCAQ+gAwIBAgIBATANBgkqhkiG9w0BAQUFADAZMRcwFQYDVQQDDA5UZXN0\n" 159 | "IFByaW5jaXBhbDAeFw03MDAxMDEwODAwMDBaFw0zODEyMzEwODAwMDBaMBkxFzAV\n" 160 | "BgNVBAMMDlRlc3QgUHJpbmNpcGFsMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB\n" 161 | "gQC0YjCwIfYoprq/FQO6lb3asXrxLlJFuCvtinTF5p0GxvQGu5O3gYytUvtC2JlY\n" 162 | "zypSRjVxwxrsuRcP3e641SdASwfrmzyvIgP08N4S0IFzEURkV1wp/IpH7kH41Etb\n" 163 | "mUmrXSwfNZsnQRE5SYSOhh+LcK2wyQkdgcMv11l4KoBkcwIDAQABMA0GCSqGSIb3\n" 164 | "DQEBBQUAA4GBAGZLPEuJ5SiJ2ryq+CmEGOXfvlTtEL2nuGtr9PewxkgnOjZpUy+d\n" 165 | "4TvuXJbNQc8f4AMWL/tO9w0Fk80rWKp9ea8/df4qMq5qlFWlx6yOLQxumNOmECKb\n" 166 | "WpkUQDIDJEoFUzKMVuJf4KO/FJ345+BNLGgbJ6WujreoM1X/gYfdnJ/J\n" 167 | "-----END CERTIFICATE-----\n", 168 | "jvTp/wX1TYtByB1m+Pbyo0lnCOLIsyGCH7wke8AUs3BpnwZJtAuEJkvQL2/9n4s5wUmUl4aCI4BwpraNx4RtEXMe5qg5T1LVTGliMRpKasKsW//e+RinhejgCuzoH26dyF8iY2ZZ/5D1ilgeijhV/vBka5twt399mXwaYdCwFYE=") 169 | != 1) { 170 | printf("RSA-SHA1 verify-signature test failed.\n"); 171 | fail|=1; 172 | } else if (loglevel) 173 | printf("RSA-SHA1 verify-signature test successful.\n"); 174 | 175 | // report 176 | if (fail) { 177 | printf("\n !!! One or more tests from http://wiki.oauth.net/TestCases failed.\n\n"); 178 | } else { 179 | printf(" *** http://wiki.oauth.net/TestCases verified sucessfully.\n"); 180 | } 181 | 182 | return (fail?1:0); 183 | } 184 | -------------------------------------------------------------------------------- /configure.ac: -------------------------------------------------------------------------------- 1 | AC_PREREQ(2.57) 2 | AC_INIT([liboauth], m4_esyscmd_s([sed -ne 's/^#define LIBOAUTH_VERSION "\(.*\)"/\1/p' src/oauth.h]), [robin AT gareus DOT org], [], [http://liboauth.sourceforge.net/]) 3 | #AM_MAINTAINER_MODE 4 | 5 | AC_PATH_PROG(SED, sed, "", $PATH:/bin:/usr/bin:/usr/local/bin) 6 | if test -z "$SED"; then 7 | AC_MSG_WARN([sed was not found]) 8 | fi 9 | 10 | AC_MSG_CHECKING([liboauth version]) 11 | VERSION=`$SED -ne 's/^#define LIBOAUTH_VERSION "\(.*\)"/\1/p' ${srcdir}/src/oauth.h 2>/dev/null` 12 | AC_MSG_RESULT($VERSION) 13 | if test -z "$VERSION"; then 14 | AC_MSG_ERROR([version number can not be retrieved from src/oauth.h]) 15 | fi 16 | 17 | VERSION_CUR=`$SED -ne 's/^#define LIBOAUTH_CUR *\([0-9]*\)/\1/p' ${srcdir}/src/oauth.h 2>/dev/null` 18 | VERSION_REV=`$SED -ne 's/^#define LIBOAUTH_REV *\([0-9]*\)/\1/p' ${srcdir}/src/oauth.h 2>/dev/null` 19 | VERSION_AGE=`$SED -ne 's/^#define LIBOAUTH_AGE *\([0-9]*\)/\1/p' ${srcdir}/src/oauth.h 2>/dev/null` 20 | VERSION_INFO=${VERSION_CUR}:${VERSION_REV}:${VERSION_AGE} 21 | 22 | AC_CONFIG_SRCDIR([src/oauth.c]) 23 | AC_CONFIG_TESTDIR([tests]) 24 | AC_CANONICAL_TARGET([]) 25 | AC_COPYRIGHT([Copyright (C) Robin Gareus 2007-2012]) 26 | AM_INIT_AUTOMAKE 27 | 28 | AM_CONFIG_HEADER(src/config.h) 29 | 30 | AC_SUBST(VERSION) 31 | AC_SUBST(VERSION_INFO) 32 | ISODATE=`date +%Y-%m-%d` 33 | AC_SUBST(ISODATE) 34 | 35 | AC_CANONICAL_HOST 36 | 37 | AC_PROG_INSTALL 38 | AC_PROG_CC 39 | AC_PROG_MAKE_SET 40 | AC_PROG_LN_S 41 | AC_PROG_LIBTOOL 42 | AM_PROG_LIBTOOL 43 | AM_PROG_CC_C_O 44 | AC_LIBTOOL_WIN32_DLL 45 | AC_CONFIG_MACRO_DIR([m4]) 46 | 47 | AC_HEADER_STDC 48 | AC_CHECK_HEADERS(unistd.h time.h string.h alloca.h stdio.h stdarg.h math.h) 49 | 50 | AC_HEADER_MAJOR 51 | AC_FUNC_ALLOCA 52 | AC_STRUCT_TM 53 | AC_STRUCT_ST_BLOCKS 54 | AC_FUNC_CLOSEDIR_VOID 55 | 56 | AH_TEMPLATE([HAVE_STRTOK_R], [Define as 1 if the c library provides strtok_r]) 57 | AH_TEMPLATE([HAVE_CURL], [Define as 1 if you have libcurl]) 58 | AH_TEMPLATE([USE_BUILTIN_HASH], [Define to use neither NSS nor OpenSSL]) 59 | AH_TEMPLATE([USE_NSS], [Define to use NSS instead of OpenSSL]) 60 | AH_TEMPLATE([HAVE_SHELL_CURL], [Define if you can invoke curl via a shell command. This is only used if HAVE_CURL is not defined.]) 61 | AH_TEMPLATE([OAUTH_CURL_TIMEOUT], [Define the number of seconds for the HTTP request to timeout; if not defined no timeout (or libcurl default) is used.]) 62 | 63 | EXESUF= 64 | TEST_UNICODE=-DTEST_UNICODE 65 | 66 | dnl *** Target specific settings *** 67 | case $target_os in 68 | *darwin*) 69 | ;; 70 | *mingw32*|*win*) 71 | EXESUF=.exe 72 | TEST_UNICODE= 73 | ;; 74 | *) 75 | ;; 76 | esac 77 | AC_SUBST(TEST_UNICODE) 78 | AC_SUBST(EXESUF) 79 | 80 | dnl *** misc complier/linker flags *** 81 | LIBOAUTH_CFLAGS="-Wall" 82 | LIBOAUTH_LDFLAGS="${LIBOAUTH_CFLAGS} -export-symbols-regex '^oauth_.*'" 83 | #LIBOAUTH_CFLAGS="${LIBOAUTH_CFLAGS} -g -posix -std=c99 -pedantic" 84 | 85 | AC_MSG_CHECKING([if -Wl,--as-needed works]) 86 | LDFLAGS_save=$LDFLAGS 87 | LDFLAGS="$LDFLAGS -Wl,--as-needed" 88 | AC_TRY_LINK([], [], 89 | [ 90 | AC_MSG_RESULT([yes]) 91 | LIBOAUTH_LDFLAGS="$LIBOAUTH_LDFLAGS -Wl,--as-needed" 92 | ], 93 | [AC_MSG_RESULT([no])]) 94 | LDFLAGS=$LDFLAGS_save 95 | 96 | AC_SUBST(LIBOAUTH_CFLAGS) 97 | AC_SUBST(LIBOAUTH_LDFLAGS) 98 | 99 | 100 | dnl *** PKGconfig oauth.pc.in *** 101 | PC_LIB="" 102 | 103 | dnl *** configuration options *** 104 | AC_ARG_ENABLE(curl, AC_HELP_STRING([--disable-curl],[do not use (command-line) curl])) 105 | AC_ARG_ENABLE(libcurl, AC_HELP_STRING([--disable-libcurl],[do not use libcurl])) 106 | AC_ARG_ENABLE(builtinhash, AC_HELP_STRING([--enable-builtinhash],[do use neither NSS nor OpenSSL: only HMAC/SHA1 signatures - no RSA/PK11])) 107 | AC_ARG_ENABLE(nss, AC_HELP_STRING([--enable-nss],[use NSS instead of OpenSSL])) 108 | AC_ARG_WITH([curltimeout], AC_HELP_STRING([--with-curltimeout@<:@=@:>@],[use CURLOPT_TIMEOUT with libcurl HTTP requests. Timeout is given in seconds (default=60). Note: using this option also sets CURLOPT_NOSIGNAL. see http://curl.haxx.se/libcurl/c/curl_easy_setopt.html#CURLOPTTIMEOUT])) 109 | 110 | AC_CHECK_FUNC(strtok_r, [AC_DEFINE(HAVE_STRTOK_R, 1)], []) 111 | 112 | report_curl="no" 113 | dnl ** check for commandline executable curl 114 | if test "${enable_curl}" != "no"; then 115 | AC_PATH_PROG(CURLCMD, curl, no, $PATH:/bin:/usr/bin:/usr/local/bin) 116 | if test "$CURLCMD" != "no"; then 117 | AC_DEFINE(HAVE_SHELL_CURL, 1) 118 | report_curl="shell command" 119 | fi 120 | fi 121 | 122 | dnl ** check for libcurl 123 | AS_IF([test "${enable_libcurl}" != "no"], [ 124 | PKG_CHECK_MODULES(CURL, libcurl, 125 | [ AC_DEFINE(HAVE_CURL, 1) HAVE_CURL=1 PC_LIB="$PC_LIB`$PKG_CONFIG --static --libs libcurl` " report_curl="libcurl" ] , 126 | [ 127 | AC_CHECK_HEADERS(curl/curl.h) 128 | AC_CHECK_LIB([curl], [curl_global_init], 129 | [AC_DEFINE(HAVE_CURL, 1) HAVE_CURL=1 PC_LIB="$PC_LIB-lcurl " report_curl="libcurl" ] 130 | ) 131 | ] 132 | ) 133 | ]) 134 | 135 | report_curltimeout="-" 136 | if test -n "${with_curltimeout}"; then 137 | if test "${with_curltimeout}" = "yes"; then 138 | AC_DEFINE(OAUTH_CURL_TIMEOUT, 60) 139 | report_curltimeout="60" 140 | else 141 | if test "${with_curltimeout}" -gt 0; then 142 | AC_DEFINE_UNQUOTED(OAUTH_CURL_TIMEOUT, [${with_curltimeout}]) 143 | report_curltimeout=${with_curltimeout} 144 | fi 145 | fi 146 | fi 147 | 148 | AC_SUBST(CURL_CFLAGS) 149 | AC_SUBST(CURL_LIBS) 150 | 151 | dnl ** crypto/hash lib (OpenSSL or NSS) 152 | AS_IF([test "${enable_builtinhash}" = "yes"], [ 153 | AC_DEFINE(USE_BUILTIN_HASH, 1) USE_BUILTIN_HASH=1 154 | HASH_LIBS="" 155 | HASH_CFLAGS="" 156 | report_hash="built-in HMAC/SHA1 - no RSA" 157 | AC_MSG_NOTICE([ 158 | using built-in HMAC/SHA1 hash algorithm without RSA/PK11 support. 159 | This option is not recommended for general use and should only 160 | be used on small devices (AVR, mircocontrollers) where neither 161 | NSS nor OpenSSL is available. 162 | ]) 163 | ], [ 164 | AS_IF([test "${enable_nss}" = "yes"], [ 165 | PKG_CHECK_MODULES(NSS, nss, 166 | [ AC_DEFINE(USE_NSS, 1) USE_NSS=1 PC_LIB="$PC_LIB`$PKG_CONFIG --static --libs nss` " 167 | HASH_LIBS=${NSS_LIBS} 168 | HASH_CFLAGS=${NSS_CFLAGS} 169 | report_hash="NSS" ]) 170 | ], [ 171 | PKG_CHECK_MODULES(OPENSSL, libcrypto, 172 | [ PC_LIB="$PC_LIB`$PKG_CONFIG --static --libs libcrypto` " 173 | HASH_LIBS=${OPENSSL_LIBS} 174 | HASH_CFLAGS=${OPENSSL_CFLAGS} 175 | report_hash="OpenSSL" ] , 176 | [ 177 | AC_CHECK_HEADERS(openssl/hmac.h) 178 | if test -z "${HASH_LIBS}"; then 179 | HASH_LIBS="-lcrypto" 180 | fi 181 | if test -z "${HASH_CFLAGS}"; then 182 | HASH_CFLAGS="" 183 | fi 184 | report_hash="OpenSSL" 185 | PC_LIB="$PC_LIB${HASH_LIBS} " 186 | AC_MSG_NOTICE([ 187 | 188 | NOTE: OpenSSL is not compatible with GPL applications. 189 | Even if only linked with GPL code you are not allowed to distibute your app. 190 | However liboauth provides an exeption (to the GPL) to circumvent this issue 191 | (see README, src/hash.c). Nevertheless, double-check your licensing. 192 | 193 | liboauth itself is licensed under MIT license and comatible with the GPL. 194 | 195 | Either way, you are probably better off using NSS (configure --enable-nss); 196 | future versions of liboauth will default to the Mozilla NSS. 197 | 198 | see http://people.gnome.org/~markmc/openssl-and-the-gpl.html 199 | ]) 200 | ] 201 | ) 202 | ]) 203 | ]) 204 | 205 | AC_SUBST(HASH_LIBS) 206 | AC_SUBST(HASH_CFLAGS) 207 | 208 | dnl *** doxygen *** 209 | AC_ARG_VAR(DOXYGEN, Doxygen) 210 | AC_PATH_PROG(DOXYGEN, doxygen, no) 211 | 212 | if test "$DOXYGEN" != "no"; then 213 | DOXMAKE='run "make dox" to generate API html reference: doc/html/index.html' 214 | fi 215 | 216 | dnl *** graphviz *** 217 | dnl (needed for Doxyfile.in) 218 | AC_ARG_VAR(DOT, The 'dot' program from graphviz) 219 | AC_PATH_PROG(DOT, dot, no) 220 | if test "$DOT" != "no"; then 221 | HAVEDOT=YES 222 | DOTPATH=$( dirname "$DOT" ) 223 | else 224 | HAVEDOT=NO 225 | fi 226 | AC_SUBST(HAVEDOT) 227 | AC_SUBST(DOTPATH) 228 | 229 | 230 | dnl *** perl *** 231 | dnl (needed for Doxyfile.in) 232 | AC_ARG_VAR(PERL, Perl) 233 | AC_PATH_PROG(PERL, perl, no) 234 | if test "$PERL" = "no"; then 235 | AC_MSG_WARN([dude, where's your perl? doxygen will not like this!)]) 236 | fi 237 | 238 | # PKGconfig oauth.pc.in 239 | AC_SUBST(PC_LIB) 240 | 241 | 242 | dnl *** output *** 243 | subdirs="src doc tests" 244 | AC_SUBST(subdirs) 245 | 246 | AC_OUTPUT(Makefile src/Makefile doc/Makefile tests/Makefile liboauth.lsm oauth.pc Doxyfile doc/mainpage.dox) 247 | 248 | AC_MSG_NOTICE([ 249 | 250 | liboauth configured: 251 | ----------------------- 252 | 253 | version: $VERSION 254 | interface revision: $VERSION_INFO 255 | hash/signature: $report_hash 256 | http integration: $report_curl 257 | libcurl-timeout: $report_curltimeout 258 | generate documentation: $DOXYGEN 259 | installation prefix: $prefix 260 | CFLAGS: $LIBOAUTH_CFLAGS $CFLAGS 261 | LDFLAGS: $LIBOAUTH_LDFLAGS $LDFLAGS 262 | 263 | type "make" followed my "make install" as root. 264 | $DOXMAKE 265 | ]) 266 | -------------------------------------------------------------------------------- /src/sha1.c: -------------------------------------------------------------------------------- 1 | /* This code is public-domain - it is based on libcrypt 2 | * placed in the public domain by Wei Dai and other contributors. 3 | */ 4 | // gcc -Wall -DSHA1TEST -o sha1test sha1.c && ./sha1test 5 | 6 | #include 7 | #include 8 | 9 | 10 | #ifdef __BIG_ENDIAN__ 11 | # define SHA_BIG_ENDIAN 12 | #elif defined __LITTLE_ENDIAN__ 13 | /* override */ 14 | #elif defined __BYTE_ORDER 15 | # if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 16 | # define SHA_BIG_ENDIAN 17 | # endif 18 | #else // ! defined __LITTLE_ENDIAN__ 19 | # include // machine/endian.h 20 | # if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ 21 | # define SHA_BIG_ENDIAN 22 | # endif 23 | #endif 24 | 25 | 26 | /* header */ 27 | 28 | #define HASH_LENGTH 20 29 | #define BLOCK_LENGTH 64 30 | 31 | typedef struct sha1nfo { 32 | uint32_t buffer[BLOCK_LENGTH/4]; 33 | uint32_t state[HASH_LENGTH/4]; 34 | uint32_t byteCount; 35 | uint8_t bufferOffset; 36 | uint8_t keyBuffer[BLOCK_LENGTH]; 37 | uint8_t innerHash[HASH_LENGTH]; 38 | } sha1nfo; 39 | 40 | /* public API - prototypes - TODO: doxygen*/ 41 | 42 | /** 43 | */ 44 | void sha1_init(sha1nfo *s); 45 | /** 46 | */ 47 | void sha1_writebyte(sha1nfo *s, uint8_t data); 48 | /** 49 | */ 50 | void sha1_write(sha1nfo *s, const char *data, size_t len); 51 | /** 52 | */ 53 | uint8_t* sha1_result(sha1nfo *s); 54 | /** 55 | */ 56 | void sha1_initHmac(sha1nfo *s, const uint8_t* key, int keyLength); 57 | /** 58 | */ 59 | uint8_t* sha1_resultHmac(sha1nfo *s); 60 | 61 | 62 | /* code */ 63 | #define SHA1_K0 0x5a827999 64 | #define SHA1_K20 0x6ed9eba1 65 | #define SHA1_K40 0x8f1bbcdc 66 | #define SHA1_K60 0xca62c1d6 67 | 68 | void sha1_init(sha1nfo *s) { 69 | s->state[0] = 0x67452301; 70 | s->state[1] = 0xefcdab89; 71 | s->state[2] = 0x98badcfe; 72 | s->state[3] = 0x10325476; 73 | s->state[4] = 0xc3d2e1f0; 74 | s->byteCount = 0; 75 | s->bufferOffset = 0; 76 | } 77 | 78 | uint32_t sha1_rol32(uint32_t number, uint8_t bits) { 79 | return ((number << bits) | (number >> (32-bits))); 80 | } 81 | 82 | void sha1_hashBlock(sha1nfo *s) { 83 | uint8_t i; 84 | uint32_t a,b,c,d,e,t; 85 | 86 | a=s->state[0]; 87 | b=s->state[1]; 88 | c=s->state[2]; 89 | d=s->state[3]; 90 | e=s->state[4]; 91 | for (i=0; i<80; i++) { 92 | if (i>=16) { 93 | t = s->buffer[(i+13)&15] ^ s->buffer[(i+8)&15] ^ s->buffer[(i+2)&15] ^ s->buffer[i&15]; 94 | s->buffer[i&15] = sha1_rol32(t,1); 95 | } 96 | if (i<20) { 97 | t = (d ^ (b & (c ^ d))) + SHA1_K0; 98 | } else if (i<40) { 99 | t = (b ^ c ^ d) + SHA1_K20; 100 | } else if (i<60) { 101 | t = ((b & c) | (d & (b | c))) + SHA1_K40; 102 | } else { 103 | t = (b ^ c ^ d) + SHA1_K60; 104 | } 105 | t+=sha1_rol32(a,5) + e + s->buffer[i&15]; 106 | e=d; 107 | d=c; 108 | c=sha1_rol32(b,30); 109 | b=a; 110 | a=t; 111 | } 112 | s->state[0] += a; 113 | s->state[1] += b; 114 | s->state[2] += c; 115 | s->state[3] += d; 116 | s->state[4] += e; 117 | } 118 | 119 | void sha1_addUncounted(sha1nfo *s, uint8_t data) { 120 | uint8_t * const b = (uint8_t*) s->buffer; 121 | #ifdef SHA_BIG_ENDIAN 122 | b[s->bufferOffset] = data; 123 | #else 124 | b[s->bufferOffset ^ 3] = data; 125 | #endif 126 | s->bufferOffset++; 127 | if (s->bufferOffset == BLOCK_LENGTH) { 128 | sha1_hashBlock(s); 129 | s->bufferOffset = 0; 130 | } 131 | } 132 | 133 | void sha1_writebyte(sha1nfo *s, uint8_t data) { 134 | ++s->byteCount; 135 | sha1_addUncounted(s, data); 136 | } 137 | 138 | void sha1_write(sha1nfo *s, const char *data, size_t len) { 139 | for (;len--;) sha1_writebyte(s, (uint8_t) *data++); 140 | } 141 | 142 | void sha1_pad(sha1nfo *s) { 143 | // Implement SHA-1 padding (fips180-2 §5.1.1) 144 | 145 | // Pad with 0x80 followed by 0x00 until the end of the block 146 | sha1_addUncounted(s, 0x80); 147 | while (s->bufferOffset != 56) sha1_addUncounted(s, 0x00); 148 | 149 | // Append length in the last 8 bytes 150 | sha1_addUncounted(s, 0); // We're only using 32 bit lengths 151 | sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths 152 | sha1_addUncounted(s, 0); // So zero pad the top bits 153 | sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8 154 | sha1_addUncounted(s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as 155 | sha1_addUncounted(s, s->byteCount >> 13); // byte. 156 | sha1_addUncounted(s, s->byteCount >> 5); 157 | sha1_addUncounted(s, s->byteCount << 3); 158 | } 159 | 160 | uint8_t* sha1_result(sha1nfo *s) { 161 | // Pad to complete the last block 162 | sha1_pad(s); 163 | 164 | #ifndef SHA_BIG_ENDIAN 165 | // Swap byte order back 166 | int i; 167 | for (i=0; i<5; i++) { 168 | s->state[i]= 169 | (((s->state[i])<<24)& 0xff000000) 170 | | (((s->state[i])<<8) & 0x00ff0000) 171 | | (((s->state[i])>>8) & 0x0000ff00) 172 | | (((s->state[i])>>24)& 0x000000ff); 173 | } 174 | #endif 175 | 176 | // Return pointer to hash (20 characters) 177 | return (uint8_t*) s->state; 178 | } 179 | 180 | #define HMAC_IPAD 0x36 181 | #define HMAC_OPAD 0x5c 182 | 183 | void sha1_initHmac(sha1nfo *s, const uint8_t* key, int keyLength) { 184 | uint8_t i; 185 | memset(s->keyBuffer, 0, BLOCK_LENGTH); 186 | if (keyLength > BLOCK_LENGTH) { 187 | // Hash long keys 188 | sha1_init(s); 189 | for (;keyLength--;) sha1_writebyte(s, *key++); 190 | memcpy(s->keyBuffer, sha1_result(s), HASH_LENGTH); 191 | } else { 192 | // Block length keys are used as is 193 | memcpy(s->keyBuffer, key, keyLength); 194 | } 195 | // Start inner hash 196 | sha1_init(s); 197 | for (i=0; ikeyBuffer[i] ^ HMAC_IPAD); 199 | } 200 | } 201 | 202 | uint8_t* sha1_resultHmac(sha1nfo *s) { 203 | uint8_t i; 204 | // Complete inner hash 205 | memcpy(s->innerHash,sha1_result(s),HASH_LENGTH); 206 | // Calculate outer hash 207 | sha1_init(s); 208 | for (i=0; ikeyBuffer[i] ^ HMAC_OPAD); 209 | for (i=0; iinnerHash[i]); 210 | return sha1_result(s); 211 | } 212 | 213 | /* self-test */ 214 | 215 | #if SHA1TEST 216 | #include 217 | 218 | uint8_t hmacKey1[]={ 219 | 0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f, 220 | 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f, 221 | 0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x29,0x2a,0x2b,0x2c,0x2d,0x2e,0x2f, 222 | 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f 223 | }; 224 | uint8_t hmacKey2[]={ 225 | 0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,0x3a,0x3b,0x3c,0x3d,0x3e,0x3f, 226 | 0x40,0x41,0x42,0x43 227 | }; 228 | uint8_t hmacKey3[]={ 229 | 0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5a,0x5b,0x5c,0x5d,0x5e,0x5f, 230 | 0x60,0x61,0x62,0x63,0x64,0x65,0x66,0x67,0x68,0x69,0x6a,0x6b,0x6c,0x6d,0x6e,0x6f, 231 | 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f, 232 | 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, 233 | 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, 234 | 0xa0,0xa1,0xa2,0xa3,0xa4,0xa5,0xa6,0xa7,0xa8,0xa9,0xaa,0xab,0xac,0xad,0xae,0xaf, 235 | 0xb0,0xb1,0xb2,0xb3 236 | }; 237 | uint8_t hmacKey4[]={ 238 | 0x70,0x71,0x72,0x73,0x74,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f, 239 | 0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x8a,0x8b,0x8c,0x8d,0x8e,0x8f, 240 | 0x90,0x91,0x92,0x93,0x94,0x95,0x96,0x97,0x98,0x99,0x9a,0x9b,0x9c,0x9d,0x9e,0x9f, 241 | 0xa0 242 | }; 243 | 244 | void printHash(uint8_t* hash) { 245 | int i; 246 | for (i=0; i<20; i++) { 247 | printf("%02x", hash[i]); 248 | } 249 | printf("\n"); 250 | } 251 | 252 | 253 | int main (int argc, char **argv) { 254 | uint32_t a; 255 | sha1nfo s; 256 | 257 | // SHA tests 258 | printf("Test: FIPS 180-2 C.1 and RFC3174 7.3 TEST1\n"); 259 | printf("Expect:a9993e364706816aba3e25717850c26c9cd0d89d\n"); 260 | printf("Result:"); 261 | sha1_init(&s); 262 | sha1_write(&s, "abc", 3); 263 | printHash(sha1_result(&s)); 264 | printf("\n\n"); 265 | 266 | printf("Test: FIPS 180-2 C.2 and RFC3174 7.3 TEST2\n"); 267 | printf("Expect:84983e441c3bd26ebaae4aa1f95129e5e54670f1\n"); 268 | printf("Result:"); 269 | sha1_init(&s); 270 | sha1_write(&s, "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", 56); 271 | printHash(sha1_result(&s)); 272 | printf("\n\n"); 273 | 274 | printf("Test: RFC3174 7.3 TEST4\n"); 275 | printf("Expect:dea356a2cddd90c7a7ecedc5ebb563934f460452\n"); 276 | printf("Result:"); 277 | sha1_init(&s); 278 | for (a=0; a<80; a++) sha1_write(&s, "01234567", 8); 279 | printHash(sha1_result(&s)); 280 | printf("\n\n"); 281 | 282 | // HMAC tests 283 | printf("Test: FIPS 198a A.1\n"); 284 | printf("Expect:4f4ca3d5d68ba7cc0a1208c9c61e9c5da0403c0a\n"); 285 | printf("Result:"); 286 | sha1_initHmac(&s, hmacKey1, 64); 287 | sha1_write(&s, "Sample #1",9); 288 | printHash(sha1_resultHmac(&s)); 289 | printf("\n\n"); 290 | 291 | printf("Test: FIPS 198a A.2\n"); 292 | printf("Expect:0922d3405faa3d194f82a45830737d5cc6c75d24\n"); 293 | printf("Result:"); 294 | sha1_initHmac(&s, hmacKey2, 20); 295 | sha1_write(&s, "Sample #2", 9); 296 | printHash(sha1_resultHmac(&s)); 297 | printf("\n\n"); 298 | 299 | printf("Test: FIPS 198a A.3\n"); 300 | printf("Expect:bcf41eab8bb2d802f3d05caf7cb092ecf8d1a3aa\n"); 301 | printf("Result:"); 302 | sha1_initHmac(&s, hmacKey3,100); 303 | sha1_write(&s, "Sample #3", 9); 304 | printHash(sha1_resultHmac(&s)); 305 | printf("\n\n"); 306 | 307 | printf("Test: FIPS 198a A.4\n"); 308 | printf("Expect:9ea886efe268dbecce420c7524df32e0751a2a26\n"); 309 | printf("Result:"); 310 | sha1_initHmac(&s, hmacKey4,49); 311 | sha1_write(&s, "Sample #4", 9); 312 | printHash(sha1_resultHmac(&s)); 313 | printf("\n\n"); 314 | 315 | // Long tests 316 | printf("Test: FIPS 180-2 C.3 and RFC3174 7.3 TEST3\n"); 317 | printf("Expect:34aa973cd4c4daa4f61eeb2bdbad27316534016f\n"); 318 | printf("Result:"); 319 | sha1_init(&s); 320 | for (a=0; a<1000000; a++) sha1_writebyte(&s, 'a'); 321 | printHash(sha1_result(&s)); 322 | 323 | return 0; 324 | } 325 | #endif /* self-test */ 326 | -------------------------------------------------------------------------------- /src/hash.c: -------------------------------------------------------------------------------- 1 | /* 2 | * hash algorithms used in OAuth 3 | * 4 | * Copyright 2007-2012 Robin Gareus 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | 26 | #if HAVE_CONFIG_H 27 | # include 28 | #endif 29 | 30 | #if USE_BUILTIN_HASH // built-in / AVR -- TODO: check license of sha1.c 31 | #include 32 | #include "oauth.h" // oauth_encode_base64 33 | #include "xmalloc.h" 34 | 35 | #include "sha1.c" // TODO: sha1.h ; Makefile.am: add sha1.c 36 | 37 | /* API */ 38 | char *oauth_sign_hmac_sha1_raw (const char *m, const size_t ml, const char *k, const size_t kl) { 39 | sha1nfo s; 40 | sha1_initHmac(&s, (const uint8_t*) k, kl); 41 | sha1_write(&s, m, ml); 42 | unsigned char *digest = sha1_resultHmac(&s); 43 | return oauth_encode_base64(HASH_LENGTH, digest); 44 | } 45 | 46 | char *oauth_sign_hmac_sha1 (const char *m, const char *k) { 47 | return(oauth_sign_hmac_sha1_raw (m, strlen(m), k, strlen(k))); 48 | } 49 | 50 | char *oauth_body_hash_file(char *filename) { 51 | size_t len=0; 52 | char fb[BUFSIZ]; 53 | sha1nfo s; 54 | 55 | FILE *F= fopen(filename, "r"); 56 | 57 | if (!F) return NULL; 58 | sha1_init(&s); 59 | 60 | while (!feof(F) && (len=fread(fb,sizeof(char),BUFSIZ, F))>0) { 61 | sha1_write(&s, fb, len); 62 | } 63 | fclose(F); 64 | 65 | unsigned char *dgst = xmalloc(HASH_LENGTH*sizeof(char)); // oauth_body_hash_encode frees the digest.. 66 | memcpy(dgst, sha1_result(&s), HASH_LENGTH); 67 | return oauth_body_hash_encode(HASH_LENGTH, dgst); 68 | } 69 | 70 | char *oauth_body_hash_data(size_t length, const char *data) { 71 | sha1nfo s; 72 | sha1_init(&s); 73 | for (;length--;) sha1_writebyte(&s, *data++); 74 | 75 | unsigned char *dgst = xmalloc(HASH_LENGTH*sizeof(char)); // oauth_body_hash_encode frees the digest.. 76 | memcpy(dgst, sha1_result(&s), HASH_LENGTH); 77 | return oauth_body_hash_encode(HASH_LENGTH, dgst); 78 | } 79 | 80 | char *oauth_sign_rsa_sha1 (const char *m, const char *k) { 81 | /* NOT RSA/PK11 support */ 82 | return xstrdup("---RSA/PK11-is-not-supported-by-this-version-of-liboauth---"); 83 | } 84 | 85 | int oauth_verify_rsa_sha1 (const char *m, const char *c, const char *sig) { 86 | /* NOT RSA/PK11 support */ 87 | return -1; // mismatch , error 88 | } 89 | 90 | #elif defined (USE_NSS) 91 | /* use http://www.mozilla.org/projects/security/pki/nss/ for hash/sign */ 92 | 93 | #include 94 | #include 95 | #include 96 | #include "xmalloc.h" 97 | #include "oauth.h" // oauth base64 encode fn's. 98 | 99 | // NSS includes 100 | #include "pk11pub.h" 101 | #include "nss.h" 102 | #include "base64.h" 103 | #include "keyhi.h" 104 | #include "cryptohi.h" 105 | #include "cert.h" 106 | 107 | #if 1 // work-around compiler-warning 108 | // see http://bugzilla.mozilla.org/show_bug.cgi?id=243245#c3 109 | extern CERTCertificate * 110 | __CERT_DecodeDERCertificate (SECItem *derSignedCert, PRBool copyDER, char *nickname); 111 | #endif 112 | 113 | static const char NS_CERT_HEADER[] = "-----BEGIN CERTIFICATE-----"; 114 | static const char NS_CERT_TRAILER[] = "-----END CERTIFICATE-----"; 115 | static const char NS_PRIV_HEADER[] = "-----BEGIN PRIVATE KEY-----"; 116 | static const char NS_PRIV_TRAILER[] = "-----END PRIVATE KEY-----"; 117 | 118 | void oauth_init_nss() { 119 | static short nss_initialized = 0; 120 | if (!nss_initialized) { NSS_NoDB_Init(NULL); nss_initialized=1;} 121 | } 122 | 123 | /** 124 | * Removes heading & trailing strings; used only internally. 125 | * similar to NSS-source/nss/lib/pkcs7/certread.c 126 | * 127 | * the returned string (if not NULL) needs to be freed by the caller 128 | */ 129 | char *oauth_strip_pkcs(const char *txt, const char *h, const char *t) { 130 | char *start, *end, *rv; 131 | size_t len; 132 | if ((start=strstr(txt, h))==NULL) return NULL; 133 | start+=strlen(h); 134 | while (*start=='\r' || *start=='\n') start++; 135 | if ((end=strstr(start, t))==NULL) return NULL; 136 | end--; 137 | while (*end=='\r' || *end=='\n') end--; 138 | len = end-start+2; 139 | rv = xmalloc(len*sizeof(char)); 140 | memcpy(rv,start,len); 141 | rv[len-1]='\0'; 142 | return rv; 143 | } 144 | 145 | char *oauth_sign_hmac_sha1 (const char *m, const char *k) { 146 | return(oauth_sign_hmac_sha1_raw (m, strlen(m), k, strlen(k))); 147 | } 148 | 149 | char *oauth_sign_hmac_sha1_raw (const char *m, const size_t ml, const char *k, const size_t kl) { 150 | PK11SlotInfo *slot = NULL; 151 | PK11SymKey *pkey = NULL; 152 | PK11Context *context = NULL; 153 | unsigned char digest[20]; // Is there a way to tell how large the output is? 154 | unsigned int len; 155 | SECStatus s; 156 | SECItem keyItem, noParams; 157 | char *rv=NULL; 158 | 159 | keyItem.type = siBuffer; 160 | keyItem.data = (unsigned char*) k; 161 | keyItem.len = kl; 162 | 163 | noParams.type = siBuffer; 164 | noParams.data = NULL; 165 | noParams.len = 0; 166 | 167 | oauth_init_nss(); 168 | 169 | slot = PK11_GetInternalKeySlot(); 170 | if (!slot) goto looser; 171 | pkey = PK11_ImportSymKey(slot, CKM_SHA_1_HMAC, PK11_OriginUnwrap, CKA_SIGN, &keyItem, NULL); 172 | if (!pkey) goto looser; 173 | context = PK11_CreateContextBySymKey(CKM_SHA_1_HMAC, CKA_SIGN, pkey, &noParams); 174 | if (!context) goto looser; 175 | 176 | s = PK11_DigestBegin(context); 177 | if (s != SECSuccess) goto looser; 178 | s = PK11_DigestOp(context, (unsigned char*) m, ml); 179 | if (s != SECSuccess) goto looser; 180 | s = PK11_DigestFinal(context, digest, &len, sizeof digest); 181 | if (s != SECSuccess) goto looser; 182 | 183 | rv=oauth_encode_base64(len, digest); 184 | 185 | looser: 186 | if (context) PK11_DestroyContext(context, PR_TRUE); 187 | if (pkey) PK11_FreeSymKey(pkey); 188 | if (slot) PK11_FreeSlot(slot); 189 | return rv; 190 | } 191 | 192 | char *oauth_sign_rsa_sha1 (const char *m, const char *k) { 193 | PK11SlotInfo *slot = NULL; 194 | SECKEYPrivateKey *pkey = NULL; 195 | SECItem signature; 196 | SECStatus s; 197 | SECItem der; 198 | char *rv=NULL; 199 | 200 | char *key = oauth_strip_pkcs(k, NS_PRIV_HEADER, NS_PRIV_TRAILER); 201 | if (!key) return NULL; 202 | 203 | oauth_init_nss(); 204 | 205 | slot = PK11_GetInternalKeySlot(); 206 | if (!slot) goto looser; 207 | s = ATOB_ConvertAsciiToItem(&der, key); 208 | if (s != SECSuccess) goto looser; 209 | s = PK11_ImportDERPrivateKeyInfoAndReturnKey(slot, &der, NULL, NULL, PR_FALSE, PR_TRUE, KU_ALL, &pkey, NULL); 210 | SECITEM_FreeItem(&der, PR_FALSE); 211 | if (s != SECSuccess) goto looser; 212 | if (!pkey) goto looser; 213 | if (pkey->keyType != rsaKey) goto looser; 214 | s = SEC_SignData(&signature, (unsigned char*) m, strlen(m), pkey, SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE); 215 | if (s != SECSuccess) goto looser; 216 | 217 | rv=oauth_encode_base64(signature.len, signature.data); 218 | SECITEM_FreeItem(&signature, PR_FALSE); 219 | 220 | looser: 221 | if (pkey) SECKEY_DestroyPrivateKey(pkey); 222 | if (slot) PK11_FreeSlot(slot); 223 | xfree(key); 224 | return rv; 225 | } 226 | 227 | int oauth_verify_rsa_sha1 (const char *m, const char *c, const char *sig) { 228 | PK11SlotInfo *slot = NULL; 229 | SECKEYPublicKey *pkey = NULL; 230 | CERTCertificate *cert = NULL; 231 | SECItem signature; 232 | SECStatus s; 233 | SECItem der; 234 | int rv=0; 235 | 236 | char *key = oauth_strip_pkcs(c, NS_CERT_HEADER, NS_CERT_TRAILER); 237 | if (!key) return 0; 238 | 239 | oauth_init_nss(); 240 | 241 | s = ATOB_ConvertAsciiToItem(&signature, (char*) sig); // XXX cast (const char*) -> (char*) 242 | if (s != SECSuccess) goto looser; 243 | slot = PK11_GetInternalKeySlot(); 244 | if (!slot) goto looser; 245 | s = ATOB_ConvertAsciiToItem(&der, key); 246 | if (s != SECSuccess) goto looser; 247 | cert = __CERT_DecodeDERCertificate(&der, PR_TRUE, NULL); 248 | SECITEM_FreeItem(&der, PR_FALSE); 249 | if (!cert) goto looser; 250 | pkey = CERT_ExtractPublicKey(cert); 251 | if (!pkey) goto looser; 252 | if (pkey->keyType != rsaKey) goto looser; 253 | 254 | s = VFY_VerifyData((unsigned char*) m, strlen(m), pkey, &signature, SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE, NULL); 255 | if (s == SECSuccess) rv=1; 256 | #if 0 257 | else if (PR_GetError()!= SEC_ERROR_BAD_SIGNATURE) rv=-1; 258 | #endif 259 | 260 | looser: 261 | if (pkey) SECKEY_DestroyPublicKey(pkey); 262 | if (slot) PK11_FreeSlot(slot); 263 | xfree(key); 264 | return rv; 265 | } 266 | 267 | char *oauth_body_hash_file(char *filename) { 268 | PK11SlotInfo *slot = NULL; 269 | PK11Context *context = NULL; 270 | unsigned char digest[20]; // Is there a way to tell how large the output is? 271 | unsigned int len; 272 | SECStatus s; 273 | char *rv=NULL; 274 | size_t bl; 275 | unsigned char fb[BUFSIZ]; 276 | unsigned char *dgst; 277 | 278 | FILE *F= fopen(filename, "r"); 279 | if (!F) return NULL; 280 | 281 | oauth_init_nss(); 282 | 283 | slot = PK11_GetInternalKeySlot(); 284 | if (!slot) goto looser; 285 | context = PK11_CreateDigestContext(SEC_OID_SHA1); 286 | if (!context) goto looser; 287 | 288 | s = PK11_DigestBegin(context); 289 | if (s != SECSuccess) goto looser; 290 | while (!feof(F) && (bl=fread(fb,sizeof(char),BUFSIZ, F))>0) { 291 | s = PK11_DigestOp(context, (unsigned char*) fb, bl); 292 | if (s != SECSuccess) goto looser; 293 | } 294 | s = PK11_DigestFinal(context, digest, &len, sizeof digest); 295 | if (s != SECSuccess) goto looser; 296 | 297 | dgst = xmalloc(len*sizeof(char)); // oauth_body_hash_encode frees the digest.. 298 | memcpy(dgst, digest, len); 299 | rv=oauth_body_hash_encode(len, dgst); 300 | 301 | looser: 302 | fclose(F); 303 | if (context) PK11_DestroyContext(context, PR_TRUE); 304 | if (slot) PK11_FreeSlot(slot); 305 | return rv; 306 | } 307 | 308 | char *oauth_body_hash_data(size_t length, const char *data) { 309 | PK11SlotInfo *slot = NULL; 310 | PK11Context *context = NULL; 311 | unsigned char digest[20]; // Is there a way to tell how large the output is? 312 | unsigned int len; 313 | SECStatus s; 314 | char *rv=NULL; 315 | 316 | oauth_init_nss(); 317 | 318 | slot = PK11_GetInternalKeySlot(); 319 | if (!slot) goto looser; 320 | context = PK11_CreateDigestContext(SEC_OID_SHA1); 321 | if (!context) goto looser; 322 | 323 | s = PK11_DigestBegin(context); 324 | if (s != SECSuccess) goto looser; 325 | s = PK11_DigestOp(context, (unsigned char*) data, length); 326 | if (s != SECSuccess) goto looser; 327 | s = PK11_DigestFinal(context, digest, &len, sizeof digest); 328 | if (s != SECSuccess) goto looser; 329 | 330 | unsigned char *dgst = xmalloc(len*sizeof(char)); // oauth_body_hash_encode frees the digest.. 331 | memcpy(dgst, digest, len); 332 | rv=oauth_body_hash_encode(len, dgst); 333 | 334 | looser: 335 | if (context) PK11_DestroyContext(context, PR_TRUE); 336 | if (slot) PK11_FreeSlot(slot); 337 | return rv; 338 | } 339 | 340 | #else 341 | /* use http://www.openssl.org/ for hash/sign */ 342 | 343 | #ifdef _GNU_SOURCE 344 | /* 345 | * In addition, as a special exception, the copyright holders give 346 | * permission to link the code of portions of this program with the 347 | * OpenSSL library under certain conditions as described in each 348 | * individual source file, and distribute linked combinations 349 | * including the two. 350 | * You must obey the GNU General Public License in all respects 351 | * for all of the code used other than OpenSSL. If you modify 352 | * file(s) with this exception, you may extend this exception to your 353 | * version of the file(s), but you are not obligated to do so. If you 354 | * do not wish to do so, delete this exception statement from your 355 | * version. If you delete this exception statement from all source 356 | * files in the program, then also delete it here. 357 | */ 358 | #endif 359 | 360 | #include 361 | #include 362 | #include 363 | #include "xmalloc.h" 364 | #include "oauth.h" // base64 encode fn's. 365 | #include 366 | 367 | char *oauth_sign_hmac_sha1 (const char *m, const char *k) { 368 | return(oauth_sign_hmac_sha1_raw (m, strlen(m), k, strlen(k))); 369 | } 370 | 371 | char *oauth_sign_hmac_sha1_raw (const char *m, const size_t ml, const char *k, const size_t kl) { 372 | unsigned char result[EVP_MAX_MD_SIZE]; 373 | unsigned int resultlen = 0; 374 | 375 | HMAC(EVP_sha1(), k, kl, 376 | (unsigned char*) m, ml, 377 | result, &resultlen); 378 | 379 | return(oauth_encode_base64(resultlen, result)); 380 | } 381 | 382 | #include 383 | #include 384 | #include 385 | #include 386 | 387 | char *oauth_sign_rsa_sha1 (const char *m, const char *k) { 388 | unsigned char *sig = NULL; 389 | unsigned char *passphrase = NULL; 390 | unsigned int len=0; 391 | EVP_MD_CTX* md_ctx = EVP_MD_CTX_create(); 392 | 393 | EVP_PKEY *pkey; 394 | BIO *in; 395 | in = BIO_new_mem_buf((unsigned char*) k, strlen(k)); 396 | pkey = PEM_read_bio_PrivateKey(in, NULL, 0, passphrase); // generate sign 397 | BIO_free(in); 398 | 399 | if (pkey == NULL) { 400 | //fprintf(stderr, "liboauth/OpenSSL: can not read private key\n"); 401 | return xstrdup("liboauth/OpenSSL: can not read private key"); 402 | } 403 | 404 | len = EVP_PKEY_size(pkey); 405 | sig = (unsigned char*)xmalloc((len+1)*sizeof(char)); 406 | 407 | EVP_SignInit(md_ctx, EVP_sha1()); 408 | EVP_SignUpdate(md_ctx, m, strlen(m)); 409 | if (EVP_SignFinal (md_ctx, sig, &len, pkey)) { 410 | char *tmp; 411 | sig[len] = '\0'; 412 | tmp = oauth_encode_base64(len,sig); 413 | OPENSSL_free(sig); 414 | EVP_PKEY_free(pkey); 415 | EVP_MD_CTX_destroy (md_ctx); 416 | return tmp; 417 | } 418 | EVP_MD_CTX_destroy (md_ctx); 419 | return xstrdup("liboauth/OpenSSL: rsa-sha1 signing failed"); 420 | } 421 | 422 | int oauth_verify_rsa_sha1 (const char *m, const char *c, const char *s) { 423 | EVP_MD_CTX* md_ctx = EVP_MD_CTX_create(); 424 | EVP_PKEY *pkey; 425 | BIO *in; 426 | X509 *cert = NULL; 427 | unsigned char *b64d; 428 | int slen, err; 429 | 430 | in = BIO_new_mem_buf((unsigned char*)c, strlen(c)); 431 | cert = PEM_read_bio_X509(in, NULL, 0, NULL); 432 | if (cert) { 433 | pkey = (EVP_PKEY *) X509_get_pubkey(cert); 434 | X509_free(cert); 435 | } else { 436 | pkey = PEM_read_bio_PUBKEY(in, NULL, 0, NULL); 437 | } 438 | BIO_free(in); 439 | if (pkey == NULL) { 440 | //fprintf(stderr, "could not read cert/pubkey.\n"); 441 | return -2; 442 | } 443 | 444 | b64d= (unsigned char*) xmalloc(sizeof(char)*strlen(s)); 445 | slen = oauth_decode_base64(b64d, s); 446 | 447 | EVP_VerifyInit(md_ctx, EVP_sha1()); 448 | EVP_VerifyUpdate(md_ctx, m, strlen(m)); 449 | err = EVP_VerifyFinal(md_ctx, b64d, slen, pkey); 450 | EVP_MD_CTX_destroy(md_ctx); 451 | EVP_PKEY_free(pkey); 452 | xfree(b64d); 453 | return (err); 454 | } 455 | 456 | 457 | /** 458 | * http://oauth.googlecode.com/svn/spec/ext/body_hash/1.0/oauth-bodyhash.html 459 | */ 460 | char *oauth_body_hash_file(char *filename) { 461 | unsigned char fb[BUFSIZ]; 462 | EVP_MD_CTX* ctx = EVP_MD_CTX_create(); 463 | size_t len=0; 464 | unsigned char *md; 465 | FILE *F= fopen(filename, "r"); 466 | if (!F) return NULL; 467 | 468 | EVP_MD_CTX_init(ctx); 469 | EVP_DigestInit(ctx,EVP_sha1()); 470 | while (!feof(F) && (len=fread(fb,sizeof(char),BUFSIZ, F))>0) { 471 | EVP_DigestUpdate(ctx, fb, len); 472 | } 473 | fclose(F); 474 | len=0; 475 | md=(unsigned char*) xcalloc(EVP_MD_size(EVP_sha1()),sizeof(unsigned char)); 476 | EVP_DigestFinal(ctx, md,(unsigned int*) &len); 477 | EVP_MD_CTX_destroy(ctx); 478 | return oauth_body_hash_encode(len, md); 479 | } 480 | 481 | char *oauth_body_hash_data(size_t length, const char *data) { 482 | EVP_MD_CTX* ctx = EVP_MD_CTX_create(); 483 | size_t len=0; 484 | unsigned char *md; 485 | md=(unsigned char*) xcalloc(EVP_MD_size(EVP_sha1()),sizeof(unsigned char)); 486 | EVP_MD_CTX_init(ctx); 487 | EVP_DigestInit(ctx,EVP_sha1()); 488 | EVP_DigestUpdate(ctx, data, length); 489 | EVP_DigestFinal(ctx, md,(unsigned int*) &len); 490 | EVP_MD_CTX_destroy(ctx); 491 | return oauth_body_hash_encode(len, md); 492 | } 493 | 494 | #endif 495 | 496 | // vi: sts=2 sw=2 ts=2 497 | -------------------------------------------------------------------------------- /INSTALL: -------------------------------------------------------------------------------- 1 | Installation Instructions 2 | ************************* 3 | 4 | Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation, 5 | Inc. 6 | 7 | Copying and distribution of this file, with or without modification, 8 | are permitted in any medium without royalty provided the copyright 9 | notice and this notice are preserved. This file is offered as-is, 10 | without warranty of any kind. 11 | 12 | Basic Installation 13 | ================== 14 | 15 | Briefly, the shell commands `./configure; make; make install' should 16 | configure, build, and install this package. The following 17 | more-detailed instructions are generic; see the `README' file for 18 | instructions specific to this package. Some packages provide this 19 | `INSTALL' file but do not implement all of the features documented 20 | below. The lack of an optional feature in a given package is not 21 | necessarily a bug. More recommendations for GNU packages can be found 22 | in *note Makefile Conventions: (standards)Makefile Conventions. 23 | 24 | The `configure' shell script attempts to guess correct values for 25 | various system-dependent variables used during compilation. It uses 26 | those values to create a `Makefile' in each directory of the package. 27 | It may also create one or more `.h' files containing system-dependent 28 | definitions. Finally, it creates a shell script `config.status' that 29 | you can run in the future to recreate the current configuration, and a 30 | file `config.log' containing compiler output (useful mainly for 31 | debugging `configure'). 32 | 33 | It can also use an optional file (typically called `config.cache' 34 | and enabled with `--cache-file=config.cache' or simply `-C') that saves 35 | the results of its tests to speed up reconfiguring. Caching is 36 | disabled by default to prevent problems with accidental use of stale 37 | cache files. 38 | 39 | If you need to do unusual things to compile the package, please try 40 | to figure out how `configure' could check whether to do them, and mail 41 | diffs or instructions to the address given in the `README' so they can 42 | be considered for the next release. If you are using the cache, and at 43 | some point `config.cache' contains results you don't want to keep, you 44 | may remove or edit it. 45 | 46 | The file `configure.ac' (or `configure.in') is used to create 47 | `configure' by a program called `autoconf'. You need `configure.ac' if 48 | you want to change it or regenerate `configure' using a newer version 49 | of `autoconf'. 50 | 51 | The simplest way to compile this package is: 52 | 53 | 1. `cd' to the directory containing the package's source code and type 54 | `./configure' to configure the package for your system. 55 | 56 | Running `configure' might take a while. While running, it prints 57 | some messages telling which features it is checking for. 58 | 59 | 2. Type `make' to compile the package. 60 | 61 | 3. Optionally, type `make check' to run any self-tests that come with 62 | the package, generally using the just-built uninstalled binaries. 63 | 64 | 4. Type `make install' to install the programs and any data files and 65 | documentation. When installing into a prefix owned by root, it is 66 | recommended that the package be configured and built as a regular 67 | user, and only the `make install' phase executed with root 68 | privileges. 69 | 70 | 5. Optionally, type `make installcheck' to repeat any self-tests, but 71 | this time using the binaries in their final installed location. 72 | This target does not install anything. Running this target as a 73 | regular user, particularly if the prior `make install' required 74 | root privileges, verifies that the installation completed 75 | correctly. 76 | 77 | 6. You can remove the program binaries and object files from the 78 | source code directory by typing `make clean'. To also remove the 79 | files that `configure' created (so you can compile the package for 80 | a different kind of computer), type `make distclean'. There is 81 | also a `make maintainer-clean' target, but that is intended mainly 82 | for the package's developers. If you use it, you may have to get 83 | all sorts of other programs in order to regenerate files that came 84 | with the distribution. 85 | 86 | 7. Often, you can also type `make uninstall' to remove the installed 87 | files again. In practice, not all packages have tested that 88 | uninstallation works correctly, even though it is required by the 89 | GNU Coding Standards. 90 | 91 | 8. Some packages, particularly those that use Automake, provide `make 92 | distcheck', which can by used by developers to test that all other 93 | targets like `make install' and `make uninstall' work correctly. 94 | This target is generally not run by end users. 95 | 96 | Compilers and Options 97 | ===================== 98 | 99 | Some systems require unusual options for compilation or linking that 100 | the `configure' script does not know about. Run `./configure --help' 101 | for details on some of the pertinent environment variables. 102 | 103 | You can give `configure' initial values for configuration parameters 104 | by setting variables in the command line or in the environment. Here 105 | is an example: 106 | 107 | ./configure CC=c99 CFLAGS=-g LIBS=-lposix 108 | 109 | *Note Defining Variables::, for more details. 110 | 111 | Compiling For Multiple Architectures 112 | ==================================== 113 | 114 | You can compile the package for more than one kind of computer at the 115 | same time, by placing the object files for each architecture in their 116 | own directory. To do this, you can use GNU `make'. `cd' to the 117 | directory where you want the object files and executables to go and run 118 | the `configure' script. `configure' automatically checks for the 119 | source code in the directory that `configure' is in and in `..'. This 120 | is known as a "VPATH" build. 121 | 122 | With a non-GNU `make', it is safer to compile the package for one 123 | architecture at a time in the source code directory. After you have 124 | installed the package for one architecture, use `make distclean' before 125 | reconfiguring for another architecture. 126 | 127 | On MacOS X 10.5 and later systems, you can create libraries and 128 | executables that work on multiple system types--known as "fat" or 129 | "universal" binaries--by specifying multiple `-arch' options to the 130 | compiler but only a single `-arch' option to the preprocessor. Like 131 | this: 132 | 133 | ./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ 134 | CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \ 135 | CPP="gcc -E" CXXCPP="g++ -E" 136 | 137 | This is not guaranteed to produce working output in all cases, you 138 | may have to build one architecture at a time and combine the results 139 | using the `lipo' tool if you have problems. 140 | 141 | Installation Names 142 | ================== 143 | 144 | By default, `make install' installs the package's commands under 145 | `/usr/local/bin', include files under `/usr/local/include', etc. You 146 | can specify an installation prefix other than `/usr/local' by giving 147 | `configure' the option `--prefix=PREFIX', where PREFIX must be an 148 | absolute file name. 149 | 150 | You can specify separate installation prefixes for 151 | architecture-specific files and architecture-independent files. If you 152 | pass the option `--exec-prefix=PREFIX' to `configure', the package uses 153 | PREFIX as the prefix for installing programs and libraries. 154 | Documentation and other data files still use the regular prefix. 155 | 156 | In addition, if you use an unusual directory layout you can give 157 | options like `--bindir=DIR' to specify different values for particular 158 | kinds of files. Run `configure --help' for a list of the directories 159 | you can set and what kinds of files go in them. In general, the 160 | default for these options is expressed in terms of `${prefix}', so that 161 | specifying just `--prefix' will affect all of the other directory 162 | specifications that were not explicitly provided. 163 | 164 | The most portable way to affect installation locations is to pass the 165 | correct locations to `configure'; however, many packages provide one or 166 | both of the following shortcuts of passing variable assignments to the 167 | `make install' command line to change installation locations without 168 | having to reconfigure or recompile. 169 | 170 | The first method involves providing an override variable for each 171 | affected directory. For example, `make install 172 | prefix=/alternate/directory' will choose an alternate location for all 173 | directory configuration variables that were expressed in terms of 174 | `${prefix}'. Any directories that were specified during `configure', 175 | but not in terms of `${prefix}', must each be overridden at install 176 | time for the entire installation to be relocated. The approach of 177 | makefile variable overrides for each directory variable is required by 178 | the GNU Coding Standards, and ideally causes no recompilation. 179 | However, some platforms have known limitations with the semantics of 180 | shared libraries that end up requiring recompilation when using this 181 | method, particularly noticeable in packages that use GNU Libtool. 182 | 183 | The second method involves providing the `DESTDIR' variable. For 184 | example, `make install DESTDIR=/alternate/directory' will prepend 185 | `/alternate/directory' before all installation names. The approach of 186 | `DESTDIR' overrides is not required by the GNU Coding Standards, and 187 | does not work on platforms that have drive letters. On the other hand, 188 | it does better at avoiding recompilation issues, and works well even 189 | when some directory options were not specified in terms of `${prefix}' 190 | at `configure' time. 191 | 192 | Optional Features 193 | ================= 194 | 195 | If the package supports it, you can cause programs to be installed 196 | with an extra prefix or suffix on their names by giving `configure' the 197 | option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'. 198 | 199 | Some packages pay attention to `--enable-FEATURE' options to 200 | `configure', where FEATURE indicates an optional part of the package. 201 | They may also pay attention to `--with-PACKAGE' options, where PACKAGE 202 | is something like `gnu-as' or `x' (for the X Window System). The 203 | `README' should mention any `--enable-' and `--with-' options that the 204 | package recognizes. 205 | 206 | For packages that use the X Window System, `configure' can usually 207 | find the X include and library files automatically, but if it doesn't, 208 | you can use the `configure' options `--x-includes=DIR' and 209 | `--x-libraries=DIR' to specify their locations. 210 | 211 | Some packages offer the ability to configure how verbose the 212 | execution of `make' will be. For these packages, running `./configure 213 | --enable-silent-rules' sets the default to minimal output, which can be 214 | overridden with `make V=1'; while running `./configure 215 | --disable-silent-rules' sets the default to verbose, which can be 216 | overridden with `make V=0'. 217 | 218 | Particular systems 219 | ================== 220 | 221 | On HP-UX, the default C compiler is not ANSI C compatible. If GNU 222 | CC is not installed, it is recommended to use the following options in 223 | order to use an ANSI C compiler: 224 | 225 | ./configure CC="cc -Ae -D_XOPEN_SOURCE=500" 226 | 227 | and if that doesn't work, install pre-built binaries of GCC for HP-UX. 228 | 229 | HP-UX `make' updates targets which have the same time stamps as 230 | their prerequisites, which makes it generally unusable when shipped 231 | generated files such as `configure' are involved. Use GNU `make' 232 | instead. 233 | 234 | On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot 235 | parse its `' header file. The option `-nodtk' can be used as 236 | a workaround. If GNU CC is not installed, it is therefore recommended 237 | to try 238 | 239 | ./configure CC="cc" 240 | 241 | and if that doesn't work, try 242 | 243 | ./configure CC="cc -nodtk" 244 | 245 | On Solaris, don't put `/usr/ucb' early in your `PATH'. This 246 | directory contains several dysfunctional programs; working variants of 247 | these programs are available in `/usr/bin'. So, if you need `/usr/ucb' 248 | in your `PATH', put it _after_ `/usr/bin'. 249 | 250 | On Haiku, software installed for all users goes in `/boot/common', 251 | not `/usr/local'. It is recommended to use the following options: 252 | 253 | ./configure --prefix=/boot/common 254 | 255 | Specifying the System Type 256 | ========================== 257 | 258 | There may be some features `configure' cannot figure out 259 | automatically, but needs to determine by the type of machine the package 260 | will run on. Usually, assuming the package is built to be run on the 261 | _same_ architectures, `configure' can figure that out, but if it prints 262 | a message saying it cannot guess the machine type, give it the 263 | `--build=TYPE' option. TYPE can either be a short name for the system 264 | type, such as `sun4', or a canonical name which has the form: 265 | 266 | CPU-COMPANY-SYSTEM 267 | 268 | where SYSTEM can have one of these forms: 269 | 270 | OS 271 | KERNEL-OS 272 | 273 | See the file `config.sub' for the possible values of each field. If 274 | `config.sub' isn't included in this package, then this package doesn't 275 | need to know the machine type. 276 | 277 | If you are _building_ compiler tools for cross-compiling, you should 278 | use the option `--target=TYPE' to select the type of system they will 279 | produce code for. 280 | 281 | If you want to _use_ a cross compiler, that generates code for a 282 | platform different from the build platform, you should specify the 283 | "host" platform (i.e., that on which the generated programs will 284 | eventually be run) with `--host=TYPE'. 285 | 286 | Sharing Defaults 287 | ================ 288 | 289 | If you want to set default values for `configure' scripts to share, 290 | you can create a site shell script called `config.site' that gives 291 | default values for variables like `CC', `cache_file', and `prefix'. 292 | `configure' looks for `PREFIX/share/config.site' if it exists, then 293 | `PREFIX/etc/config.site' if it exists. Or, you can set the 294 | `CONFIG_SITE' environment variable to the location of the site script. 295 | A warning: not all `configure' scripts look for a site script. 296 | 297 | Defining Variables 298 | ================== 299 | 300 | Variables not defined in a site shell script can be set in the 301 | environment passed to `configure'. However, some packages may run 302 | configure again during the build, and the customized values of these 303 | variables may be lost. In order to avoid this problem, you should set 304 | them in the `configure' command line, using `VAR=value'. For example: 305 | 306 | ./configure CC=/usr/local2/bin/gcc 307 | 308 | causes the specified `gcc' to be used as the C compiler (unless it is 309 | overridden in the site shell script). 310 | 311 | Unfortunately, this technique does not work for `CONFIG_SHELL' due to 312 | an Autoconf bug. Until the bug is fixed you can use this workaround: 313 | 314 | CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash 315 | 316 | `configure' Invocation 317 | ====================== 318 | 319 | `configure' recognizes the following options to control how it 320 | operates. 321 | 322 | `--help' 323 | `-h' 324 | Print a summary of all of the options to `configure', and exit. 325 | 326 | `--help=short' 327 | `--help=recursive' 328 | Print a summary of the options unique to this package's 329 | `configure', and exit. The `short' variant lists options used 330 | only in the top level, while the `recursive' variant lists options 331 | also present in any nested packages. 332 | 333 | `--version' 334 | `-V' 335 | Print the version of Autoconf used to generate the `configure' 336 | script, and exit. 337 | 338 | `--cache-file=FILE' 339 | Enable the cache: use and save the results of the tests in FILE, 340 | traditionally `config.cache'. FILE defaults to `/dev/null' to 341 | disable caching. 342 | 343 | `--config-cache' 344 | `-C' 345 | Alias for `--cache-file=config.cache'. 346 | 347 | `--quiet' 348 | `--silent' 349 | `-q' 350 | Do not print messages saying which checks are being made. To 351 | suppress all normal output, redirect it to `/dev/null' (any error 352 | messages will still be shown). 353 | 354 | `--srcdir=DIR' 355 | Look for the package's source code in directory DIR. Usually 356 | `configure' can determine that directory automatically. 357 | 358 | `--prefix=DIR' 359 | Use DIR as the installation prefix. *note Installation Names:: 360 | for more details, including other options available for fine-tuning 361 | the installation locations. 362 | 363 | `--no-create' 364 | `-n' 365 | Run the configure checks, but stop before creating any output 366 | files. 367 | 368 | `configure' also accepts some other, not widely useful, options. Run 369 | `configure --help' for more details. 370 | 371 | -------------------------------------------------------------------------------- /COPYING.GPL: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Library General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 19yy 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License 307 | along with this program; if not, write to the Free Software 308 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 309 | 310 | 311 | Also add information on how to contact you by electronic and paper mail. 312 | 313 | If the program is interactive, make it output a short notice like this 314 | when it starts in an interactive mode: 315 | 316 | Gnomovision version 69, Copyright (C) 19yy name of author 317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 318 | This is free software, and you are welcome to redistribute it 319 | under certain conditions; type `show c' for details. 320 | 321 | The hypothetical commands `show w' and `show c' should show the appropriate 322 | parts of the General Public License. Of course, the commands you use may 323 | be called something other than `show w' and `show c'; they could even be 324 | mouse-clicks or menu items--whatever suits your program. 325 | 326 | You should also get your employer (if you work as a programmer) or your 327 | school, if any, to sign a "copyright disclaimer" for the program, if 328 | necessary. Here is a sample; alter the names: 329 | 330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 331 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 332 | 333 | , 1 April 1989 334 | Ty Coon, President of Vice 335 | 336 | This General Public License does not permit incorporating your program into 337 | proprietary programs. If your program is a subroutine library, you may 338 | consider it more useful to permit linking proprietary applications with the 339 | library. If this is what you want to do, use the GNU Library General 340 | Public License instead of this License. 341 | -------------------------------------------------------------------------------- /src/oauth_http.c: -------------------------------------------------------------------------------- 1 | /* 2 | * OAuth http functions in POSIX-C. 3 | * 4 | * Copyright 2007-2011 Robin Gareus 5 | * 6 | * Permission is hereby granted, free of charge, to any person obtaining a copy 7 | * of this software and associated documentation files (the "Software"), to deal 8 | * in the Software without restriction, including without limitation the rights 9 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | * copies of the Software, and to permit persons to whom the Software is 11 | * furnished to do so, subject to the following conditions: 12 | * 13 | * The above copyright notice and this permission notice shall be included in 14 | * all copies or substantial portions of the Software. 15 | * 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22 | * THE SOFTWARE. 23 | * 24 | */ 25 | #if HAVE_CONFIG_H 26 | # include 27 | #endif 28 | 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | #ifdef WIN32 35 | # define snprintf _snprintf 36 | #endif 37 | 38 | #include "xmalloc.h" 39 | #include "oauth.h" 40 | 41 | #define OAUTH_USER_AGENT "liboauth-agent/" VERSION 42 | 43 | #ifdef HAVE_CURL /* HTTP requests via libcurl */ 44 | #include 45 | 46 | # define GLOBAL_CURL_ENVIROMENT_OPTIONS \ 47 | if (getenv("CURLOPT_PROXYAUTH")){ \ 48 | curl_easy_setopt(curl, CURLOPT_PROXYAUTH, CURLAUTH_ANY); \ 49 | } \ 50 | if (getenv("CURLOPT_SSL_VERIFYPEER")){ \ 51 | curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, (long) atol(getenv("CURLOPT_SSL_VERIFYPEER")) ); \ 52 | } \ 53 | if (getenv("CURLOPT_CAINFO")){ \ 54 | curl_easy_setopt(curl, CURLOPT_CAINFO, getenv("CURLOPT_CAINFO") ); \ 55 | } \ 56 | if (getenv("CURLOPT_FOLLOWLOCATION")){ \ 57 | curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, (long) atol(getenv("CURLOPT_FOLLOWLOCATION")) ); \ 58 | } \ 59 | if (getenv("CURLOPT_FAILONERROR")){ \ 60 | curl_easy_setopt(curl, CURLOPT_FAILONERROR, (long) atol(getenv("CURLOPT_FAILONERROR")) ); \ 61 | } 62 | 63 | struct MemoryStruct { 64 | char *data; 65 | size_t size; //< bytes remaining (r), bytes accumulated (w) 66 | 67 | size_t start_size; //< only used with ..AndCall() 68 | void (*callback)(void*,int,size_t,size_t); //< only used with ..AndCall() 69 | void *callback_data; //< only used with ..AndCall() 70 | }; 71 | 72 | static size_t 73 | WriteMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data) { 74 | size_t realsize = size * nmemb; 75 | struct MemoryStruct *mem = (struct MemoryStruct *)data; 76 | 77 | mem->data = (char *)xrealloc(mem->data, mem->size + realsize + 1); 78 | if (mem->data) { 79 | memcpy(&(mem->data[mem->size]), ptr, realsize); 80 | mem->size += realsize; 81 | mem->data[mem->size] = 0; 82 | } 83 | return realsize; 84 | } 85 | 86 | static size_t 87 | ReadMemoryCallback(void *ptr, size_t size, size_t nmemb, void *data) { 88 | struct MemoryStruct *mem = (struct MemoryStruct *)data; 89 | size_t realsize = size * nmemb; 90 | if (realsize > mem->size) realsize = mem->size; 91 | memcpy(ptr, mem->data, realsize); 92 | mem->size -= realsize; 93 | mem->data += realsize; 94 | return realsize; 95 | } 96 | 97 | static size_t 98 | WriteMemoryCallbackAndCall(void *ptr, size_t size, size_t nmemb, void *data) { 99 | struct MemoryStruct *mem = (struct MemoryStruct *)data; 100 | size_t ret=WriteMemoryCallback(ptr,size,nmemb,data); 101 | mem->callback(mem->callback_data,0,mem->size,mem->size); 102 | return ret; 103 | } 104 | 105 | static size_t 106 | ReadMemoryCallbackAndCall(void *ptr, size_t size, size_t nmemb, void *data) { 107 | struct MemoryStruct *mem = (struct MemoryStruct *)data; 108 | size_t ret=ReadMemoryCallback(ptr,size,nmemb,data); 109 | mem->callback(mem->callback_data,1,mem->start_size-mem->size,mem->start_size); 110 | return ret; 111 | } 112 | 113 | /** 114 | * cURL http post function. 115 | * the returned string (if not NULL) needs to be freed by the caller 116 | * 117 | * @param u url to retrieve 118 | * @param p post parameters 119 | * @param customheader specify custom HTTP header (or NULL for none) 120 | * @return returned HTTP 121 | */ 122 | char *oauth_curl_post (const char *u, const char *p, const char *customheader) { 123 | CURL *curl; 124 | CURLcode res; 125 | struct curl_slist *slist=NULL; 126 | 127 | struct MemoryStruct chunk; 128 | chunk.data=NULL; 129 | chunk.size = 0; 130 | 131 | curl = curl_easy_init(); 132 | if(!curl) return NULL; 133 | curl_easy_setopt(curl, CURLOPT_URL, u); 134 | curl_easy_setopt(curl, CURLOPT_POSTFIELDS, p); 135 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); 136 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); 137 | if (customheader) { 138 | slist = curl_slist_append(slist, customheader); 139 | curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist); 140 | } 141 | curl_easy_setopt(curl, CURLOPT_USERAGENT, OAUTH_USER_AGENT); 142 | #ifdef OAUTH_CURL_TIMEOUT 143 | curl_easy_setopt(curl, CURLOPT_TIMEOUT, OAUTH_CURL_TIMEOUT); 144 | curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); 145 | #endif 146 | GLOBAL_CURL_ENVIROMENT_OPTIONS; 147 | res = curl_easy_perform(curl); 148 | curl_slist_free_all(slist); 149 | if (res) { 150 | return NULL; 151 | } 152 | 153 | curl_easy_cleanup(curl); 154 | return (chunk.data); 155 | } 156 | 157 | /** 158 | * cURL http get function. 159 | * the returned string (if not NULL) needs to be freed by the caller 160 | * 161 | * @param u url to retrieve 162 | * @param q optional query parameters 163 | * @param customheader specify custom HTTP header (or NULL for none) 164 | * @return returned HTTP 165 | */ 166 | char *oauth_curl_get (const char *u, const char *q, const char *customheader) { 167 | CURL *curl; 168 | CURLcode res; 169 | struct curl_slist *slist=NULL; 170 | char *t1=NULL; 171 | struct MemoryStruct chunk; 172 | 173 | if (q) { 174 | t1=(char*)xmalloc(sizeof(char)*(strlen(u)+strlen(q)+2)); 175 | strcpy(t1,u); strcat(t1,"?"); strcat(t1,q); 176 | } 177 | 178 | chunk.data=NULL; 179 | chunk.size = 0; 180 | 181 | curl = curl_easy_init(); 182 | if(!curl) { 183 | xfree(t1); 184 | return NULL; 185 | } 186 | curl_easy_setopt(curl, CURLOPT_URL, q?t1:u); 187 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); 188 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); 189 | if (customheader) { 190 | slist = curl_slist_append(slist, customheader); 191 | curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist); 192 | } 193 | #if 0 // TODO - support request methods.. 194 | if (0) 195 | curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "HEAD"); 196 | else if (0) 197 | curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE"); 198 | #endif 199 | curl_easy_setopt(curl, CURLOPT_USERAGENT, OAUTH_USER_AGENT); 200 | #ifdef OAUTH_CURL_TIMEOUT 201 | curl_easy_setopt(curl, CURLOPT_TIMEOUT, OAUTH_CURL_TIMEOUT); 202 | curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); 203 | #endif 204 | GLOBAL_CURL_ENVIROMENT_OPTIONS; 205 | res = curl_easy_perform(curl); 206 | curl_slist_free_all(slist); 207 | xfree(t1); 208 | curl_easy_cleanup(curl); 209 | 210 | if (res) { 211 | return NULL; 212 | } 213 | return (chunk.data); 214 | } 215 | 216 | /** 217 | * cURL http post raw data from file. 218 | * the returned string needs to be freed by the caller 219 | * 220 | * @param u url to retrieve 221 | * @param fn filename of the file to post along (max 2GB) 222 | * @param len length of the file in bytes. set to '0' for autodetection 223 | * @param customheader specify custom HTTP header (or NULL for default) 224 | * the default header adds "Content-Type: image/jpeg;" 225 | * @return returned HTTP or NULL on error 226 | */ 227 | char *oauth_curl_post_file (const char *u, const char *fn, size_t len, const char *customheader) { 228 | CURL *curl; 229 | CURLcode res; 230 | struct curl_slist *slist=NULL; 231 | struct MemoryStruct chunk; 232 | FILE *f; 233 | long filelen; 234 | 235 | chunk.data=NULL; 236 | chunk.size=0; 237 | 238 | if (customheader) 239 | slist = curl_slist_append(slist, customheader); 240 | else 241 | slist = curl_slist_append(slist, "Content-Type: image/jpeg;"); // good guess :) 242 | 243 | f = fopen(fn,"r"); 244 | if (!f) return NULL; 245 | 246 | fseek(f, 0L, SEEK_END); 247 | filelen = ftell(f); 248 | fseek(f, 0L, SEEK_SET); 249 | 250 | if (!len || len > filelen) { 251 | len = filelen; 252 | } 253 | 254 | curl = curl_easy_init(); 255 | if(!curl) { 256 | fclose(f); 257 | return NULL; 258 | } 259 | curl_easy_setopt(curl, CURLOPT_URL, u); 260 | curl_easy_setopt(curl, CURLOPT_POST, 1); 261 | curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, len); 262 | curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist); 263 | curl_easy_setopt(curl, CURLOPT_READDATA, f); 264 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); 265 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); 266 | curl_easy_setopt(curl, CURLOPT_USERAGENT, OAUTH_USER_AGENT); 267 | #ifdef OAUTH_CURL_TIMEOUT 268 | curl_easy_setopt(curl, CURLOPT_TIMEOUT, OAUTH_CURL_TIMEOUT); 269 | curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); 270 | #endif 271 | GLOBAL_CURL_ENVIROMENT_OPTIONS; 272 | res = curl_easy_perform(curl); 273 | curl_slist_free_all(slist); 274 | fclose(f); 275 | if (res) { 276 | // error 277 | return NULL; 278 | } 279 | 280 | curl_easy_cleanup(curl); 281 | return (chunk.data); 282 | } 283 | 284 | /** 285 | * http send raw data, with callback. 286 | * the returned string needs to be freed by the caller 287 | * 288 | * more documentation in oauth.h 289 | * 290 | * @param u url to retrieve 291 | * @param data data to post along 292 | * @param len length of the file in bytes. set to '0' for autodetection 293 | * @param customheader specify custom HTTP header (or NULL for default) 294 | * the default header adds "Content-Type: image/jpeg;" 295 | * @param callback specify the callback function 296 | * @param callback_data specify data to pass to the callback function 297 | * @return returned HTTP reply or NULL on error 298 | */ 299 | char *oauth_curl_send_data_with_callback (const char *u, const char *data, size_t len, const char *customheader, void (*callback)(void*,int,size_t,size_t), void *callback_data, const char *httpMethod) { 300 | CURL *curl; 301 | CURLcode res; 302 | struct curl_slist *slist=NULL; 303 | struct MemoryStruct chunk; 304 | struct MemoryStruct rdnfo; 305 | 306 | chunk.data=NULL; 307 | chunk.size=0; 308 | chunk.start_size=0; 309 | chunk.callback=callback; 310 | chunk.callback_data=callback_data; 311 | rdnfo.data=(char *)data; 312 | rdnfo.size=len; 313 | rdnfo.start_size=len; 314 | rdnfo.callback=callback; 315 | rdnfo.callback_data=callback_data; 316 | 317 | if (customheader) 318 | slist = curl_slist_append(slist, customheader); 319 | else 320 | slist = curl_slist_append(slist, "Content-Type: image/jpeg;"); 321 | 322 | curl = curl_easy_init(); 323 | if(!curl) return NULL; 324 | curl_easy_setopt(curl, CURLOPT_URL, u); 325 | curl_easy_setopt(curl, CURLOPT_POST, 1); 326 | if (httpMethod) curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, httpMethod); 327 | curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, len); 328 | curl_easy_setopt(curl, CURLOPT_HTTPHEADER, slist); 329 | curl_easy_setopt(curl, CURLOPT_READDATA, (void *)&rdnfo); 330 | if (callback) 331 | curl_easy_setopt(curl, CURLOPT_READFUNCTION, ReadMemoryCallbackAndCall); 332 | else 333 | curl_easy_setopt(curl, CURLOPT_READFUNCTION, ReadMemoryCallback); 334 | curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&chunk); 335 | if (callback) 336 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallbackAndCall); 337 | else 338 | curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback); 339 | curl_easy_setopt(curl, CURLOPT_USERAGENT, OAUTH_USER_AGENT); 340 | #ifdef OAUTH_CURL_TIMEOUT 341 | curl_easy_setopt(curl, CURLOPT_TIMEOUT, OAUTH_CURL_TIMEOUT); 342 | curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1); 343 | #endif 344 | GLOBAL_CURL_ENVIROMENT_OPTIONS; 345 | res = curl_easy_perform(curl); 346 | curl_slist_free_all(slist); 347 | if (res) { 348 | // error 349 | return NULL; 350 | } 351 | 352 | curl_easy_cleanup(curl); 353 | return (chunk.data); 354 | } 355 | 356 | /** 357 | * http post raw data. 358 | * the returned string needs to be freed by the caller 359 | * 360 | * more documentation in oauth.h 361 | * 362 | * @param u url to retrieve 363 | * @param data data to post along 364 | * @param len length of the file in bytes. set to '0' for autodetection 365 | * @param customheader specify custom HTTP header (or NULL for default) 366 | * @return returned HTTP reply or NULL on error 367 | */ 368 | char *oauth_curl_post_data(const char *u, const char *data, size_t len, const char *customheader) { 369 | return oauth_curl_send_data_with_callback(u, data, len, customheader, NULL, NULL, NULL); 370 | } 371 | 372 | char *oauth_curl_send_data (const char *u, const char *data, size_t len, const char *customheader, const char *httpMethod) { 373 | return oauth_curl_send_data_with_callback(u, data, len, customheader, NULL, NULL, httpMethod); 374 | } 375 | 376 | char *oauth_curl_post_data_with_callback (const char *u, const char *data, size_t len, const char *customheader, void (*callback)(void*,int,size_t,size_t), void *callback_data) { 377 | return oauth_curl_send_data_with_callback(u, data, len, customheader, callback, callback_data, NULL); 378 | } 379 | 380 | #endif // libcURL. 381 | 382 | 383 | #ifdef HAVE_SHELL_CURL /* HTTP requests via command-line curl */ 384 | 385 | // command line presets and ENV variable name 386 | #define _OAUTH_ENV_HTTPCMD "OAUTH_HTTP_CMD" 387 | #define _OAUTH_ENV_HTTPGET "OAUTH_HTTP_GET_CMD" 388 | 389 | #ifdef OAUTH_CURL_TIMEOUT 390 | 391 | #define cpxstr(s) cpstr(s) 392 | #define cpstr(s) #s 393 | 394 | #ifndef _OAUTH_DEF_HTTPCMD 395 | # define _OAUTH_DEF_HTTPCMD "curl -sA '"OAUTH_USER_AGENT"' -m "cpxstr(OAUTH_CURL_TIMEOUT)" -d '%p' '%u' " 396 | //alternative: "wget -q -U 'liboauth-agent/0.1' --post-data='%p' '%u' " 397 | #endif 398 | 399 | #ifndef _OAUTH_DEF_HTTPGET 400 | # define _OAUTH_DEF_HTTPGET "curl -sA '"OAUTH_USER_AGENT"' -m "cpxstr(OAUTH_CURL_TIMEOUT)" '%u' " 401 | //alternative: "wget -q -U 'liboauth-agent/0.1' '%u' " 402 | #endif 403 | 404 | #else // no timeout 405 | 406 | #ifndef _OAUTH_DEF_HTTPCMD 407 | # define _OAUTH_DEF_HTTPCMD "curl -sA '"OAUTH_USER_AGENT"' -d '%p' '%u' " 408 | //alternative: "wget -q -U 'liboauth-agent/0.1' --post-data='%p' '%u' " 409 | #endif 410 | 411 | #ifndef _OAUTH_DEF_HTTPGET 412 | # define _OAUTH_DEF_HTTPGET "curl -sA '"OAUTH_USER_AGENT"' '%u' " 413 | //alternative: "wget -q -U 'liboauth-agent/0.1' '%u' " 414 | #endif 415 | 416 | #endif 417 | 418 | #include 419 | 420 | /** 421 | * escape URL for use in String Quotes (aka shell single quotes). 422 | * the returned string needs to be xfree()d by the calling function 423 | * 424 | * WARNING: this function only escapes single-quotes (') 425 | * 426 | * 427 | * RFC2396 defines the following 428 | * reserved = ";" | "/" | "?" | ":" | "@" | "&" | "=" | "+" | "$" | "," 429 | * besides alphanum the following are allowed as unreserved: 430 | * mark = "-" | "_" | "." | "!" | "~" | "*" | "'" | "(" | ")" 431 | * 432 | * checking `echo '-_.!~*()'` it seems we 433 | * just need to escape the tick (') itself from "'" to "'\''" 434 | * 435 | * In C shell, the "!" character may need a backslash before it. 436 | * It depends on the characters next to it. If it is surrounded by spaces, 437 | * you don't need to use a backslash. 438 | * (here: we'd always need to escape it for c shell) 439 | * @todo: escape '!' for c-shell curl/wget commandlines 440 | * 441 | * @param cmd URI string or parameter to be escaped 442 | * @return escaped parameter 443 | */ 444 | char *oauth_escape_shell (const char *cmd) { 445 | char *esc = xstrdup(cmd); 446 | char *tmp = esc; 447 | int idx; 448 | while ((tmp=strchr(tmp,'\''))) { 449 | idx = tmp-esc; 450 | esc=(char*)xrealloc(esc,(strlen(esc)+5)*sizeof(char)); 451 | memmove(esc+idx+4,esc+idx+1, strlen(esc+idx)); 452 | esc[idx+1]='\\'; esc[idx+2]='\''; esc[idx+3]='\''; 453 | tmp=esc+(idx+4); 454 | } 455 | 456 | // TODO escape '!' if CSHELL ?! 457 | 458 | return esc; 459 | } 460 | 461 | /** 462 | * execute command via shell and return it's output. 463 | * This is used to call 'curl' or 'wget'. 464 | * the command is used as is and needs to be properly escaped. 465 | * 466 | * @param cmd the commandline to execute 467 | * @return stdout string that needs to be freed or NULL if there's no output 468 | */ 469 | char *oauth_exec_shell (const char *cmd) { 470 | #ifdef DEBUG_OAUTH 471 | printf("DEBUG: executing: %s\n",cmd); 472 | #endif 473 | FILE *in = popen (cmd, "r"); 474 | size_t len = 0; 475 | size_t alloc = 0; 476 | char *data = NULL; 477 | int rcv = 1; 478 | if (!in) return NULL; 479 | while (rcv > 0 && !feof(in)) { 480 | alloc +=1024; 481 | data = (char*)xrealloc(data, alloc * sizeof(char)); 482 | rcv = fread(data + (alloc-1024), sizeof(char), 1024, in); 483 | len += rcv; 484 | } 485 | pclose(in); 486 | #ifdef DEBUG_OAUTH 487 | printf("DEBUG: read %i bytes\n",len); 488 | #endif 489 | data[len]=0; 490 | #ifdef DEBUG_OAUTH 491 | if (data) printf("DEBUG: return: %s\n",data); 492 | else printf("DEBUG: NULL data\n"); 493 | #endif 494 | return (data); 495 | } 496 | 497 | /** 498 | * send POST via a command line HTTP client, wait for it to finish 499 | * and return the content of the reply. requires a command-line HTTP client 500 | * 501 | * see \ref oauth_http_post 502 | * 503 | * @param u url to query 504 | * @param p postargs to send along with the HTTP request. 505 | * @return In case of an error NULL is returned; otherwise a pointer to the 506 | * replied content from HTTP server. latter needs to be freed by caller. 507 | */ 508 | char *oauth_exec_post (const char *u, const char *p) { 509 | char cmd[BUFSIZ]; 510 | char *t1,*t2; 511 | char *cmdtpl = getenv(_OAUTH_ENV_HTTPCMD); 512 | if (!cmdtpl) cmdtpl = xstrdup (_OAUTH_DEF_HTTPCMD); 513 | else cmdtpl = xstrdup (cmdtpl); // clone getenv() string. 514 | 515 | // add URL and post param - error if no '%p' or '%u' present in definition 516 | t1=strstr(cmdtpl, "%p"); 517 | t2=strstr(cmdtpl, "%u"); 518 | if (!t1 || !t2) { 519 | fprintf(stderr, "\nliboauth: invalid HTTP command. set the '%s' environment variable.\n\n",_OAUTH_ENV_HTTPCMD); 520 | xfree(cmdtpl); 521 | return(NULL); 522 | } 523 | // TODO: check if there are exactly two '%' in cmdtpl 524 | *(++t1)= 's'; *(++t2)= 's'; 525 | if (t1>t2) { 526 | t1=oauth_escape_shell(u); 527 | t2=oauth_escape_shell(p); 528 | } else { 529 | t1=oauth_escape_shell(p); 530 | t2=oauth_escape_shell(u); 531 | } 532 | snprintf(cmd, BUFSIZ, cmdtpl, t1, t2); 533 | xfree(cmdtpl); 534 | xfree(t1); xfree(t2); 535 | return oauth_exec_shell(cmd); 536 | } 537 | 538 | /** 539 | * send GET via a command line HTTP client 540 | * and return the content of the reply.. 541 | * requires a command-line HTTP client. 542 | * 543 | * Note: u and q are just concatenated with a '?' in between unless q is NULL. in which case only u will be used. 544 | * 545 | * see \ref oauth_http_get 546 | * 547 | * @param u base url to get 548 | * @param q query string to send along with the HTTP request. 549 | * @return In case of an error NULL is returned; otherwise a pointer to the 550 | * replied content from HTTP server. latter needs to be freed by caller. 551 | */ 552 | char *oauth_exec_get (const char *u, const char *q) { 553 | char cmd[BUFSIZ]; 554 | char *cmdtpl, *t1, *e1; 555 | 556 | if (!u) return (NULL); 557 | 558 | cmdtpl = getenv(_OAUTH_ENV_HTTPGET); 559 | if (!cmdtpl) cmdtpl = xstrdup (_OAUTH_DEF_HTTPGET); 560 | else cmdtpl = xstrdup (cmdtpl); // clone getenv() string. 561 | 562 | // add URL and post param - error if no '%p' or '%u' present in definition 563 | t1=strstr(cmdtpl, "%u"); 564 | if (!t1) { 565 | fprintf(stderr, "\nliboauth: invalid HTTP command. set the '%s' environment variable.\n\n",_OAUTH_ENV_HTTPGET); 566 | xfree(cmdtpl); 567 | return(NULL); 568 | } 569 | *(++t1)= 's'; 570 | 571 | e1 = oauth_escape_shell(u); 572 | if (q) { 573 | char *e2; 574 | e2 = oauth_escape_shell(q); 575 | t1=(char*)xmalloc(sizeof(char)*(strlen(e1)+strlen(e2)+2)); 576 | strcpy(t1,e1); strcat(t1,"?"); strcat(t1,e2); 577 | xfree(e2); 578 | } 579 | snprintf(cmd, BUFSIZ, cmdtpl, q?t1:e1); 580 | xfree(cmdtpl); 581 | xfree(e1); 582 | if (q) xfree(t1); 583 | return oauth_exec_shell(cmd); 584 | } 585 | #endif // command-line curl. 586 | 587 | /* wrapper functions */ 588 | 589 | /** 590 | * do a HTTP GET request, wait for it to finish 591 | * and return the content of the reply. 592 | * (requires libcurl or a command-line HTTP client) 593 | * 594 | * more documentation in oauth.h 595 | * 596 | * @param u base url to get 597 | * @param q query string to send along with the HTTP request or NULL. 598 | * @return In case of an error NULL is returned; otherwise a pointer to the 599 | * replied content from HTTP server. latter needs to be freed by caller. 600 | */ 601 | char *oauth_http_get (const char *u, const char *q) { 602 | #ifdef HAVE_CURL 603 | return oauth_curl_get(u,q,NULL); 604 | #elif defined(HAVE_SHELL_CURL) 605 | return oauth_exec_get(u,q); 606 | #else 607 | return NULL; 608 | #endif 609 | } 610 | 611 | /** 612 | * do a HTTP GET request, wait for it to finish 613 | * and return the content of the reply. 614 | * (requires libcurl) 615 | * 616 | * @param u base url to get 617 | * @param q query string to send along with the HTTP request or NULL. 618 | * @param customheader specify custom HTTP header (or NULL for none) 619 | * @return In case of an error NULL is returned; otherwise a pointer to the 620 | * replied content from HTTP server. latter needs to be freed by caller. 621 | */ 622 | char *oauth_http_get2 (const char *u, const char *q, const char *customheader) { 623 | #ifdef HAVE_CURL 624 | return oauth_curl_get(u,q,customheader); 625 | #else 626 | return NULL; 627 | #endif 628 | } 629 | 630 | /** 631 | * do a HTTP POST request, wait for it to finish 632 | * and return the content of the reply. 633 | * (requires libcurl or a command-line HTTP client) 634 | * 635 | * more documentation in oauth.h 636 | * 637 | * @param u url to query 638 | * @param p postargs to send along with the HTTP request. 639 | * @return In case of an error NULL is returned; otherwise a pointer to the 640 | * replied content from HTTP server. latter needs to be freed by caller. 641 | */ 642 | char *oauth_http_post (const char *u, const char *p) { 643 | #ifdef HAVE_CURL 644 | return oauth_curl_post(u,p,NULL); 645 | #elif defined(HAVE_SHELL_CURL) 646 | return oauth_exec_post(u,p); 647 | #else 648 | return NULL; 649 | #endif 650 | } 651 | 652 | 653 | /** 654 | * do a HTTP POST request, wait for it to finish 655 | * and return the content of the reply. 656 | * (requires libcurl) 657 | * 658 | * more documentation in oauth.h 659 | * 660 | * @param u url to query 661 | * @param p postargs to send along with the HTTP request. 662 | * @param customheader specify custom HTTP header (or NULL for none) 663 | * @return In case of an error NULL is returned; otherwise a pointer to the 664 | * replied content from HTTP server. latter needs to be freed by caller. 665 | */ 666 | char *oauth_http_post2 (const char *u, const char *p, const char *customheader) { 667 | #ifdef HAVE_CURL 668 | return oauth_curl_post(u,p,customheader); 669 | #else 670 | return NULL; 671 | #endif 672 | } 673 | 674 | /** 675 | * http post raw data from file. 676 | * the returned string needs to be freed by the caller 677 | * 678 | * more documentation in oauth.h 679 | * 680 | * @param u url to retrieve 681 | * @param fn filename of the file to post along 682 | * @param len length of the file in bytes. set to '0' for autodetection 683 | * @param customheader specify custom HTTP header (or NULL for default) 684 | * @return returned HTTP reply or NULL on error 685 | */ 686 | char *oauth_post_file (const char *u, const char *fn, const size_t len, const char *customheader){ 687 | #ifdef HAVE_CURL 688 | return oauth_curl_post_file (u, fn, len, customheader); 689 | #elif defined(HAVE_SHELL_CURL) 690 | fprintf(stderr, "\nliboauth: oauth_post_file requires libcurl. libcurl is not available.\n\n"); 691 | return NULL; 692 | #else 693 | return NULL; 694 | #endif 695 | } 696 | 697 | /** 698 | * http post raw data. 699 | * the returned string needs to be freed by the caller 700 | * 701 | * more documentation in oauth.h 702 | * 703 | * @param u url to retrieve 704 | * @param data data to post along 705 | * @param len length of the file in bytes. set to '0' for autodetection 706 | * @param customheader specify custom HTTP header (or NULL for default) 707 | * @return returned HTTP reply or NULL on error 708 | */ 709 | char *oauth_post_data (const char *u, const char *data, size_t len, const char *customheader) { 710 | #ifdef HAVE_CURL 711 | return oauth_curl_post_data (u, data, len, customheader); 712 | #elif defined(HAVE_SHELL_CURL) 713 | fprintf(stderr, "\nliboauth: oauth_post_file requires libcurl. libcurl is not available.\n\n"); 714 | return NULL; 715 | #else 716 | return (NULL); 717 | #endif 718 | } 719 | 720 | char *oauth_send_data (const char *u, const char *data, size_t len, const char *customheader, const char *httpMethod) { 721 | #ifdef HAVE_CURL 722 | return oauth_curl_send_data (u, data, len, customheader, httpMethod); 723 | #elif defined(HAVE_SHELL_CURL) 724 | fprintf(stderr, "\nliboauth: oauth_send_file requires libcurl. libcurl is not available.\n\n"); 725 | return NULL; 726 | #else 727 | return (NULL); 728 | #endif 729 | } 730 | 731 | char *oauth_post_data_with_callback (const char *u, const char *data, size_t len, const char *customheader, void (*callback)(void*,int,size_t,size_t), void *callback_data) { 732 | #ifdef HAVE_CURL 733 | return oauth_curl_post_data_with_callback(u, data, len, customheader, callback, callback_data); 734 | #elif defined(HAVE_SHELL_CURL) 735 | fprintf(stderr, "\nliboauth: oauth_post_data_with_callback requires libcurl.\n\n"); 736 | return NULL; 737 | #else 738 | return (NULL); 739 | #endif 740 | } 741 | /* vi:set ts=2 sts=2 sw=2: */ 742 | --------------------------------------------------------------------------------