tag:blogger.com,1999:blog-17640375402754777492024-03-12T19:42:37.015-04:00The Perils and Triumphs of Being a GeekJonathon Reinharthttp://www.blogger.com/profile/04790032076191957141noreply@blogger.comBlogger35125tag:blogger.com,1999:blog-1764037540275477749.post-15504053866154059532016-11-16T20:33:00.000-05:002017-05-11T12:29:40.482-04:00Windows-Python-PyInstaller GitLab CI Runner<h3>Install Windows Server 2012 R2 "Server Core"</h3>
<h3>Enable Remote Desktop</h3>
<a href="https://blogs.technet.microsoft.com/bruce_adamczak/2013/02/12/windows-2012-core-survival-guide-remote-desktop/" target="_blank">Windows 2012 Core Survival Guide – Remote Desktop</a>
<h3>Set up runner</h3>
<ul>
<li>Create home directory <code>c:\users\gitlab-runner\</code></li>
<li><code>net user gitlab-runner P@55w0rd</code></li>
<li><code>icacls c:\users\gitlab-runner gitlab-runner:(CI)(OI)(F)</code></li>
<li>Use <code>secedit</code> to add <code>SeServiceLogonRight</code> to user</li>
<li><code>gitlab-ci-multi-runner install --user .\gitlab-runner --password P@55w0rd</code></li>
<li><code>wmic useraccount GET Name,FullName,Status,Disabled,PasswordExpires /all</code></li>
<li><code>wmic useraccount WHERE "Name='gitlab-runner'" SET PasswordExpires=FALSE</code></li>
</ul>
<h3>Install Python</h3>
<ul>
<li>Install 32-bit MSI to <code>C:\Python27_32\</code> (Yes, add to PATH)</li>
<li>Install 64-bit MSI to <code>C:\Python27_64\</code></li>
</ul>
<h3>Pywin32 and Pypiwin32 (32 and 64)</h3>
<h3>Install PyInstaller</h3>
<code>C:\Python27_32\python.exe setup.py install</code>
<h3>Install Git</h3>
<ul>
<li>Use git commands in git bash and cmd</li>
</ul>
Jonathon Reinharthttp://www.blogger.com/profile/04790032076191957141noreply@blogger.com0tag:blogger.com,1999:blog-1764037540275477749.post-36083294592603225262016-04-14T20:26:00.000-04:002016-11-16T20:27:53.838-05:00Fun experiences using Wine in Docker (part 2)<p>After the last post about running <a href="http://jonathonreinhart.blogspot.com/2016/04/fun-experiences-using-wine-in-docker.html">Wine in Docker</a>, it was time to try and actually use the image to perform a build.</p>
<p>The first time I tried, the build crashed due to some sort of exception. It turns out the following sequence of events was to blame:</p>
<ul>
<li>NMAKE, running under <code>wine</code>, loads <code>msvcrt80.dll</code></li>
<li>During its <code>DllMain</code>, this DLL calls <code>_wfindfirst64i32()</code>, passing it the path to <code>Microsoft.VC80.CRT.mainfest</code></li>
<li>Internally, <code>_wfindfirst64i32</code> will:
<ul>
<li>Call <code>FindFirstFileW</code> which returns a <code>WIN32_FIND_DATAW</code> structure, which includes a <code>FILETIME</code> member for each of creation, last access, and last write times.</li>
<li>Pass each of those timestamps to a function that:
<ul>
<li>Calls <code>FileTimeToLocalFileTime</code> to convert it to local time</li>
<li>Calls <code>FileTimeToSystemTime</code> to convert it to a <code>SYSTEMTIME</code> structure</li>
<li>Passes each member of the <code>SYSTEMTIME</code> structure as arguments to another function, which raises an <code>INVALID_PARAMETER</code> exception (<code>0xC000000D</code>) if the <code>Year</code> argument is not between 1970 and 3000, inclusive</li>
</ul>
</li>
</ul>
</li>
</ul>
<p>When Docker, using its union filesystem, starts the container, the file access times are zero, which is midnight, 1970-01-01. When this date is converted to local time (in EST timezone, which is UTC-5), the timestamp is five hours <i>before</i> midnight, 1970-01-01, which puts the year at 1969. This caused an exception to be raised whenever NMAKE would run.</p>
<p>The solution was quite simple: Removing <code>/etc/localtime</code> made the system use UTC time, which avoids the problem.</p>
<p><i>(When I find my notes, I will explain how I leveraged WINE's debugging facilities to track down this very elusive problem.</i></p>Jonathon Reinharthttp://www.blogger.com/profile/04790032076191957141noreply@blogger.com0tag:blogger.com,1999:blog-1764037540275477749.post-24892589878633787582016-04-13T21:21:00.001-04:002016-04-13T22:00:40.435-04:00Fun experiences using Wine in Docker<h3>Background</h3>
<p>I sometimes work with a legacy codebase that targets both Windows and Linux; the build system is GNU Make-based, and builds on Linux. For the Windows components, the build system invokes <a href="https://msdn.microsoft.com/en-us/library/dd9y37ha.aspx target="_blank">NMAKE</a>, using <a href="https://www.winehq.org/" target="_blank">Wine</a>. Yes, it's messy; yes I want to replace it; but no there's no time budgeted right now.</p>
<p>Lately, I've been moving more and more of our build infrastructure to <a href="https://www.docker.com/" target="_blank">Docker</a>. It makes keeping the build environments up-to-date for developers easier, and simplifies the setup for Continuous Integration. Check out my tool, <a href="https://github.com/JonathonReinhart/scuba" target="_blank">Scuba</a> for using Docker to perform local builds, and <a href="https://about.gitlab.com/gitlab-ci/" target="_blank">GitLab CI</a>.</p>
<p>You can see where this is going. I decided to convert our legacy build VM into a Docker image; Wine and NMAKE included. I didn't know what I was getting myself into.</p>
<h3>VM to Docker Image</h3>
<p>Of course, the right way to create a Docker image is to use a <a href="https://docs.docker.com/engine/reference/builder/" target="_blank">Dockerfile</a>. However, this current VM had experienced years of tweaks, potentially relying on subtle toolchain-version-specific quirks. I wasn't about to re-build it from scratch, so I decided to convert the VM filesystem directly to a Docker image.</p>
<p>The initial conversion turned out to be straightforward. First, I cloned the VM, so I could work destructively. Next, I uninstalled everything that wasn't necessary for a Docker image (including KDE, X11, firewall, etc.) Then, I powered down the cloned VM, and mounted its virtual disk under another VM, running Docker. From there, it's as simple as using Tar to create the Docker image:<br/>
<pre># cd /mnt/buildvm; tar -c * | docker import --change='CMD /bin/bash' - buildsys:1</pre><br/>
This adds all of the directories from the mounted build VM disk, and creates a tar stream which is piped into <code>docker import -</code> (where <code>-</code> means standard input). Note that I'm also setting the `CMD` to be `/bin/bash`; this way, the image can be run by simply using <code>docker run -it buildsys:1</code>, without having to specify <code>/bin/bash</code> every run.</p>
<p>After the initial conversion was done and I no longer needed to "boot" in the conventional way, I continued to run the image, removing more stuff, like:
<ul>
<li><code>rpm -e --nodeps kernel-xxx</code> (You don't need a kernel when running under Docker, but don't want to remove other things that "depend" on it.)</li>
<li><code>yum remove dracut grub plymouth</code>
<li><code>yum clean all && rm -rf /var/cache/yum</code></li>
<li><code>rm -rf /var/log/* /tmp/*</code></li>
</ul>
I definitely had to be careful not to remove things that Wine unexpectedly relied upon. As I did this, I occasionally ran the image through a <code>docker export</code> / <code>docker import</code> cycle to actually reduce the virtual size of the image.
</p>
<h3>Wine without X11</h3>
<p>The first time I tried to run <code>wine</code> in a Docker container, I was met with the following warnings/errors:
<pre>Application tried to create a window, but no driver could be loaded.
Make sure that your X server is running and that $DISPLAY is set correctly.</pre>
Googling for the error yielded some results from some other guys crazy enough to try using Wine in Docker also, like <a href="http://superuser.com/questions/902175/run-wine-totally-headless" target="_blank">this SuperUser post</a> and <a href="https://github.com/monokrome/docker-wine" target="_blank">this GitHub project</a>. It seemed that I would need some sort of X server after all, and that <a href="https://en.wikipedia.org/wiki/Xvfb" target="_blank">Xvfb (X Virtual FrameBuffer)</a> was the solution.</p>
<p>You can simply run <code>xvfb-run wine whatever.exe</code>, and this will avoid the "no $DISPLAY" problems. Great. However, I didn't want to change any of our code to have to run under Docker. Specifically, I didn't want to track down every invocation of <code>wine</code> and prefix it with <code>xvfb-run</code>; what if we are running on native X?</p>
<p>Instead, I came up with what I believe is a novel solution: <a href="https://docs.docker.com/engine/reference/builder/#entrypoint" target="_blank"><code>ENTRYPOINT</code></a>. This essentially prefixes the user's command with whatever is specified in ENTRYPOINT - just what we want to do with <code>xvfb-run</code>. So the last time I re-imported the tarball, I added <code>--change='ENTRYPOINT xvfb-run'</code>. There's probably a way to do this after it's been imported, but this was the most convenient at the time.</p>
<p>Now, when I run <code>docker run --rm -it buildsys:1 /bin/bash</code>, I can verify that <code>$DISPLAY</code> is set, and Wine is happy. For now.</p>
<p><i>More to come...</i></p>Jonathon Reinharthttp://www.blogger.com/profile/04790032076191957141noreply@blogger.com0tag:blogger.com,1999:blog-1764037540275477749.post-72694209889108282652015-11-20T19:30:00.000-05:002015-11-20T19:30:16.222-05:00Installing ESXi in a QEMU-KVM virtual machine, under libvirt / virt-manager<p>For a test setup, it may be useful to install VMware ESXi in a QEMU-KVM guest. If, like me, you're using libvirt (using virt-manager) to manage your VMs, here's some information to get this set up. I'm using Fedora 22, and ESXi 5.5.0.</p>
<p>There are other posts explaining how to set this up, but I wanted to share my experience, which is specific to virt-manager, and the newer QEMU.</p>
<p>Here's a step-by-step procedure for getting this working.</p>
<br/>
<h3>Add required KVM kernel module parameters:</h3>
<ol>
<li>Edit (or create) <code>/etc/modprobe.d/kvm-intel.conf</code> to look like this:
<pre>options kvm ignore_msrs=1
options kvm-intel nested=y ept=y
</pre></li>
<li>Remove the KVM module and re-load it with the new parameters: <pre># modprobe -r kvm-intel kvm; modprobe kvm kvm-intel</pre></li>
</ol>
<br/>
<h3>Setup ESXi VM guest configuration:</h3>
<ol>
<li>Create your ESXi VM using virt-manager.</li>
<li>Change the NIC to <code>vmxnet3</code>. You'll have to manually type this in; it won't be in the drop-down.</li>
<li>You'll need at least 2 GiB of RAM. <i>(During install it actually came back with:</i> <pre><MEMORY_SIZE ERROR: This host has 2.00 GiB of RAM. 3.97 GiB are needed></pre></li>
<li>Edit the config for this VM (named "esxi-test" here):
<pre># virsh -c 'qemu:///system' edit esxi-test</pre></li>
<li>Edit the first line of the XML file to be:
<pre><domain type='kvm' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'></pre>
</li>
<li>Change the CPU type:
<pre><cpu mode='host-passthrough'/></pre></li>
<li>Add this block anywhere inside of <code><domain>...</domain></code>:
<pre>
<qemu:commandline>
<qemu:arg value='-machine'/>
<qemu:arg value='vmport=off'/>
</qemu:commandline>
</pre>
<li>Save and quit</li>
</ol>
Boot into the ESXi installer, and enjoy!
<p>In dmesg, I see kvm spewing these messages, which probably have to do with ignroe_msrs:
<pre>kvm [3864]: vcpu0 ignored rdmsr: 0x34
kvm [3864]: vcpu0 ignored rdmsr: 0x34
</pre></p>
<br/>
<h3>ESXi 6.0.0 Notes:</h3>
<p>I tried to use ESXi 6.0.0, but it didn't seem to find a network card, even though I specified <code>vmnet3</code>. These notes apply to 6.0.0:</p>
<ul>
<li>Note that the installer appears to hang at "user loaded successfully." for about 110 seconds. "Running nfcd start" also takes a while. I have no idea why.</li>
</ul>
<h3>Resources</h3>
<ul>
<li><a href="https://rwmj.wordpress.com/2014/05/19/notes-on-getting-vmware-esxi-to-run-under-kvm/" target="_blank">Notes on getting VMware ESXi to run under KVM</a> (rwmj.wordpress.com) - The patch to QEMU is no longer necessary; as of at least 2.3.1, QEMU accepts the option: <code>-machine vmport=off</code> to accomplish the same. (Here's the <a href="https://lists.gnu.org/archive/html/qemu-devel/2014-05/msg03806.html" target="_blank">patch adding the option</a>.)</li>
<li><a href="https://communities.vmware.com/thread/451412" target="_blank">ESXi inside KVM</a> (communities.vmware.com) - This is the original thread where people managed to figure this out.</li>
<li><a href="http://mattinaction.blogspot.com/2014/05/install-and-run-full-functional-vmware.html" target="_blank">Install and run a full functional VMware ESX Hypervisor within a KVM virtual machine</a> (mattinaction.blogspot.com) - Another blog post explaining the same</a>
<li><a href="http://blog.vmsplice.net/2011/04/how-to-pass-qemu-command-line-options.html" target="_blank">How to pass QEMU command-line options through libvirt</a> (blog.vmsplice.net)</li>
<li><a href="https://software.intel.com/en-us/blogs/2014/12/12/enabling-virtual-machine-control-structure-shadowing-on-a-nested-virtual-machine" target="_blank">Enabling Virtual Machine Control Structure Shadowing On A Nested Virtual Machine</a> (software.intel.com) - Even though my CPU doesn't support nested VMCS, this was still useful, and provided the clue to use <code>cpu mode='host-passthrough'</code></li>
</ul>Jonathon Reinharthttp://www.blogger.com/profile/04790032076191957141noreply@blogger.com0tag:blogger.com,1999:blog-1764037540275477749.post-62079496657744914142015-07-09T16:27:00.000-04:002015-07-09T16:27:24.222-04:00Tools<p>Every geek has his/her favorite set of tools for accomplishing various tasks. Here are mine.</p>
<p>I tend to split my time between Linux and Windows so where possible there will be solutions for both. Preference is of course given to cross-platform <a href="https://en.wikipedia.org/wiki/Free_and_open-source_software" target="_blank">FOSS</a> projects.</p>
<ul>
<li>Markdown editing:
<ul>
<li>Windows: <a href="https://cloose.github.io/CuteMarkEd/" target="_blank">CuteMarkEd</a></li>
<li>Linux: <a href="http://sourceforge.net/projects/retext/" target="_blank">ReText</a></li>
</ul>
</li>
</ul>
<p>This will be updated as I run across new tools or inventory the ones I use.</p>Jonathon Reinharthttp://www.blogger.com/profile/04790032076191957141noreply@blogger.com0tag:blogger.com,1999:blog-1764037540275477749.post-43679704574029165092015-01-28T03:42:00.001-05:002015-06-27T14:56:04.617-04:00"Installing" Zotero<p>I've been playing with a new research tool called <a href="https://www.zotero.org/">Zotero</a>, which helps you keep track of research papers, etc. as you come across them.</p>
<p>I'm using their <a href="https://www.zotero.org/support/installation">standalone version</a>, which Chrome can push to via an extension. So far it seems <i>really</i> nice.</p>
<p>Zotero doesn't come with an installer on Linux, and I wanted to put it somewhere more permanent than my Downloads directory. So I did the following which makes Zotero feel very at home on my Centos 7 machine.</p>
<ol>
<li><a href="https://www.zotero.org/download/">Download the Linux tar.bz2 file</a></li>
<li>Switch to root, and move the tar.bz2 file to </code>/opt</code> and extract it. Then rename the output directory:</br>
<pre>$ sudo su -
# mv Zotero-4.0.25.2_linux-x86_64.tar.bz2 /opt
# cd /opt
# tar xf Zotero-4.0.25.2_linux-x86_64.tar.bz2
# rm Zotero-4.0.25.2_linux-x86_64.tar.bz2
# mv Zotero_linux-x86_64 zotero
</pre></li>
<li>Retrieve the Zotero icon and add it to the icons/ directory:<br/>
<pre># wget -O zotero/icons/zotero-new-z-48px.png https://raw.githubusercontent.com/zotero/zotero/4.0/chrome/skin/default/zotero/zotero-new-z-48px.png</pre>
</li>
<li>Now as your user, create the desktop shortcut, using this <a href="http://goo.gl/BAJhYu">.desktop file I put together</a>:<br/>
<pre># exit
$ wget -O ~/.local/share/applications/zotero.desktop http://goo.gl/BAJhYu
</pre>
</li>
</ol>
Note that the standalone version of Zotero keeps its local data in <a href="https://www.zotero.org/support/zotero_data"><code>~/.zotero</code></a>.
That's it! Enjoy!Jonathon Reinharthttp://www.blogger.com/profile/04790032076191957141noreply@blogger.com0tag:blogger.com,1999:blog-1764037540275477749.post-69284263926179774092015-01-26T01:59:00.001-05:002015-01-26T01:59:16.177-05:00My favorite Windows tweaks<ul>
<li><a href="http://www.sevenforums.com/tutorials/156518-show-hide-hidden-files-add-context-menu.html">Show - Hide Hidden Files - Add to Context Menu</a></li>
</ul>Jonathon Reinharthttp://www.blogger.com/profile/04790032076191957141noreply@blogger.com0tag:blogger.com,1999:blog-1764037540275477749.post-16829178045924221342015-01-25T21:56:00.000-05:002015-01-25T21:56:20.909-05:00Installing rdesktop on Centos 7<p>I'll briefly summarize <a href="http://hasis053341.blogspot.com/2014/07/Rdesktop-on-centos-7.html" target="_blank">this blog post</a> on installing rdesktop on Centos 7.</p>
<p>First, we'll set up the RPM build environment (as your local user):</p>
<pre>
$ sudo yum install rpm-build make gcc
$ mkdir -p ~/rpmbuild/{BUILD,RPMS,SOURCES,SPECS,SRPMS}
$ echo '%_topdir %(echo $HOME)/rpmbuild' > ~/.rpmmacros
</pre>
<p>Now, fetch and install the source package:</p>
<pre>
$ wget http://pkgs.repoforge.org/rdesktop/rdesktop-1.8.2-0.1.rfx.src.rpm
$ rpm -i rdesktop-1.8.2-0.1.rfx.src.rpm
</pre>
<p>Install devel dependencies and build:</p>
<pre>
$ sudo yum install openssl-devel libXt-devel libsamplerate-devel pcsc-lite-devel
$ rpmbuild -ba ~/rpmbuild/SPECS/rdesktop.spec
$ sudo yum localinstall ~rpmbuild/RPMS/x86_64/rdesktop-1.8.2-0.1.el7.centos.x86_64.rpm
</pre>Jonathon Reinharthttp://www.blogger.com/profile/04790032076191957141noreply@blogger.com0tag:blogger.com,1999:blog-1764037540275477749.post-23928190240077021122015-01-24T18:28:00.002-05:002015-06-08T06:59:43.654-04:00Connecting to a Cisco ASA VPN with DoD CAC on CentOS 7<p><big><b><i>Update: I've created scripts to automate much of this process. You can find them on <a href="https://github.com/JonathonReinhart/linux-cac-setup" target="_blank">GitHub</a>.</i></b></big></p>
<hr/>
<p>I often need to connect to a <a href="https://en.wikipedia.org/wiki/Virtual_private_network">VPN</a> with a <a href="http://www.cisco.com/c/en/us/products/security/adaptive-security-appliance-asa-software/index.html">Cisco ASA</a> box at the head-end, using a DoD <a href="https://en.wikipedia.org/wiki/Common_Access_Card">CAC</a> (<a href="https://en.wikipedia.org/wiki/Smart_card">smart card</a>) for authentication.</p>
<p>On Windows, this is often accomplished using Cisco's AnyConnect VPN client software. On Linux however, that option would never work for me. I tried to download it from the VPN https site, but it wouldn't load.</p>
<p>On Linux, we have an open-source alternative, called <i><a href="http://www.infradead.org/openconnect/index.html">openconnect</a></i>. The difficult part is getting it to use our smart card, and present the correct certificate to the VPN.</p>
<p>I found the following pages very useful in trying to get this all to work:</p>
<ul>
<li><a href="http://www.gooze.eu/forums/support/howto-connect-to-cisco-anyconnect-vpn-using-openconnect-and-pki-token">Howto: Connect to Cisco AnyConnect VPN using OpenConnect and PKI Token
</a></li>
<li><a href="http://lists.infradead.org/pipermail/openconnect-devel/2012-July/000643.html">CAC modules</a> - openconnect-devel mailing list</li>
<li><a href="http://www.gnutls.org/manual/html_node/p11tool-Invocation.html">p11tool Invocation</a></li>
</ul>
<p>openconnect uses <a href="http://p11-glue.freedesktop.org/p11-kit.html">p11-kit</a> to interact with PKCS #11 modules. (<a href="https://en.wikipedia.org/wiki/PKCS_11">PKCS #11</a> is the standard for interfacing with cryptographic tokens, like smart cards.) The first thing we need to do is tell p11-kit to use the libcoolkey pkcs11 module. Do this by creating a new file named <code>/etc/pkcs11/modules/libcoolkey.module</code>, and adding the following line to it:</p>
<pre>module:/usr/lib64/pkcs11/libcoolkeypk11.so
</pre>
<hr/>
<p>Next, we'll use <code>p11tool --list-tokens</code> to list all of the tokens on our system. You should see your smart card in this list. Mine showed up like this (along with others):</p>
<pre>$ p11tool --list-tokens
...
Token 6:
URL: pkcs11:model=;manufacturer=;serial=;token=REINHART.JONATHON.RICHARD.xxxxxxxx
Label: REINHART.JONATHON.RICHARD.xxxxxxxx
Manufacturer:
Model:
Serial:
</pre>
<hr/>
<p>Now, we want to look at all of the certificates available on our smart card. We'll use <code>p11tool --list-all-certs [url]</code>, where <code>[url]</code> is the URL of our smart card token from the previous step:</p>
<pre>$ p11tool --list-all-certs pkcs11:model=;manufacturer=;serial=;token=REINHART.JONATHON.RICHARD.xxxx
Object 0:
URL: pkcs11:model=;manufacturer=;serial=;token=REINHART.JONATHON.RICHARD.xxxxxx;id=%01;object=CAC%20ID%20Certificate;object-type=cert
Type: X.509 Certificate
Label: CAC ID Certificate
ID: 00:01
Object 1:
URL: pkcs11:model=;manufacturer=;serial=;token=REINHART.JONATHON.RICHARD.xxxxxx;id=%02;object=CAC%20Email%20Signature%20Certificate;object-type=cert
Type: X.509 Certificate
Label: CAC Email Signature Certificate
ID: 00:02
Object 2:
URL: pkcs11:model=;manufacturer=;serial=;token=REINHART.JONATHON.RICHARD.xxxxxx;id=%03;object=CAC%20Email%20Encryption%20Certificate;object-type=cert
Type: X.509 Certificate
Label: CAC Email Encryption Certificate
ID: 00:03
</pre>
<pre>So we can see the three certificates available on our smart card.</pre>
<hr/>
<p>The Windows AnyConnect software will pop-up a dialog asking you to select the certificate for authentication when the server asks for a client certificate. openconnect currently has no such functionality, so we need to explicitly tell openconnect which certificate to use. In my case, I already knew it was the certificate with <code>ID: 00:02</code>, the "CAC Email Signature Certificate". So I pass the -c option, with the minimal URL to unambiguously refer to that certificate:</p>
<pre>$ sudo openconnect -c 'pkcs11:token=REINHART.JONATHON.RICHARD.xxxxxx;id=%02' vpn.example.com
</pre>
<p>Note that I had to use <code>sudo</code> because openconnect will invoke some scripts to set up the tun device and routing.</p>
<p>At this point, openconnect should ask for your PIN, and then successfully connect to the VPN! If not, you may need to try the other certificates, by changing the id= part of the certificate URL.</p>
<p>Finally, there are still a few outstanding warnings that occur during this process:</p>
<ul>
<li><code>Certificate from VPN server "vpn.example.com" failed verification. Reason: signer not found</code> - I need to determine which certificate this is exactly, and how to add it to my trusted certificate store.</li>
</ul>
<p><i>Note: I've had to install various packages and make various changes in playing with my smart card, so if something isn't working for you, or I've skipped a step, please leave a comment so I can make this post more accurate. Thanks!</i></p>
<p><i>
Update: Additional steps - I'll work these in above at some point:<br/>
<ul>
<li><code>yum install coolkey</code></li>
<li><code>service pcscd start</code> (on Fedora 21) </li>
</ul>
</i></p>
<!--
http://geekblood.com/2014/08/11/rdp-and-centos-7/
http://hasis053341.blogspot.com/2014/07/Rdesktop-on-centos-7.htm
-->Jonathon Reinharthttp://www.blogger.com/profile/04790032076191957141noreply@blogger.com0tag:blogger.com,1999:blog-1764037540275477749.post-89906220220952867352015-01-24T00:31:00.000-05:002015-01-24T00:31:04.255-05:00Adding storage to Proxmox VE<p>The <a href="http://www.amazon.com/dp/B006G0V12O/?smid=AAXJV48TYCF6G">1 TB drives</a> for my HP server came today. Scott at <a href="http://www.amazon.com/gp/node/index.html?merchant=AAXJV48TYCF6G">All Computer Parts</a> was very helpful and quick to reply. I quickly went to hot-plugging them into my server running <a href="https://pve.proxmox.com/wiki/Main_Page">Proxmox VE</a>.</p>
<p>After the drives spun-up, I logged into the <a href="http://www8.hp.com/us/en/products/server-software/product-detail.html?oid=344313">HP System Management Homepage</a> (<a href="http://h20564.www2.hp.com/hpsc/swd/public/detail?swItemId=MTX_5154ce407f49401881413b0fa8">download</a>) and opened the <a href="http://www.hp.com/ctg/Manual/c00709035.pdf">HP Array Configuration Utility</a>. From there, I selected 3 of the unassigned drives and created an array. I then crated a RAID 5 logical drive using all of the space available on the array (1.8 TB). Finally, I added the remaining drive as a hot-spare, by selecting the array, and clicking "Spare Management". This way, if one drive goes offline, the hot-spare will immediate take its place, and the array will be rebuilt.</p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsVNp33xG2-6Ou5nKk5BkA1dD6VR-AI-Ch43UM_6Y6Gqhe8gkUB9-Z4tDySsIba8dE7QegJIe__y4RnRu4BNu0HQQDw1dv9GKSAmq3o4563nKEgWBnebp5dap5V_ApL_lZFQl7KfUJAiQ/s1600/raid.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhsVNp33xG2-6Ou5nKk5BkA1dD6VR-AI-Ch43UM_6Y6Gqhe8gkUB9-Z4tDySsIba8dE7QegJIe__y4RnRu4BNu0HQQDw1dv9GKSAmq3o4563nKEgWBnebp5dap5V_ApL_lZFQl7KfUJAiQ/s1600/raid.png" /></a></div>
<p>The logical disk is immediately detected by the Linux kernel, evidenced by /var/log/messages:</p>
<pre>Jan 23 22:38:40 dragster kernel: hpsa 0000:04:00.0: Direct-Access device c0b0t0l1 added.
Jan 23 22:38:40 dragster kernel: scsi 0:0:0:1: Direct-Access HP LOGICAL VOLUME 6.40 PQ: 0 ANSI: 5
Jan 23 22:38:40 dragster kernel: sd 0:0:0:1: Attached scsi generic sg3 type 0
Jan 23 22:38:40 dragster kernel: sd 0:0:0:1: [sdb] 3906918832 512-byte logical blocks: (2.00 TB/1.81 TiB)
Jan 23 22:38:40 dragster kernel: sd 0:0:0:1: [sdb] Write Protect is off
Jan 23 22:38:40 dragster kernel: sd 0:0:0:1: [sdb] Write cache: disabled, read cache: enabled, doesn't support DPO or FUA
Jan 23 22:38:40 dragster kernel: sdb: unknown partition table
Jan 23 22:38:40 dragster kernel: sd 0:0:0:1: [sdb] Attached SCSI disk
</pre>
<p>Proxmox <a href="http://pve.proxmox.com/wiki/Storage_Model#LVM_Groups_with_Local_Backing">works well with LVM</a>. It actually works directly with <a href="https://www.centos.org/docs/5/html/Cluster_Logical_Volume_Manager/LVM_definition.html">LVM</a> volume groups, creating logical volumes on-the-fly for new VMs, etc. You can find detailed information on the Proxmox wiki, but the procedure was quite simple:</p>
<ol>
<li>Create the LVM physical volume on the physical disk: (In this case, the "physical disk" was a RAID logical disk)<br/>
<pre># pvcreate /dev/sdb
Physical volume "/dev/sdb" successfully created</pre><br/>
Note that I created the physical volume directly on the block device, without partitioning the drive. LVM <a href="http://serverfault.com/questions/439022/does-lvm-need-a-partition-table">does not require a partition table</a>, and I'm not booting to the disk, so there was no need.</li>
<li>Create a LVM volume group from that single physical volume:<br/>
<pre># vgcreate raid5vg /dev/sdb
Volume group "raid5vg" successfully created</pre></li>
</ol>
<p>And we're ready to go! List the LVM volume groups with the <code>vgs</code> command:<br/>
<pre># vgs
VG #PV #LV #SN Attr VSize VFree
pve 1 3 0 wz--n- 67.83g 8.50g
raid5vg 1 1 0 wz--n- 1.82t 1.80t</pre></p>
<p>Now it's time to tell Proxmox about the new storage. Log into the Proxmox web UI, and select the "Datacenter" node in the tree. On the <b>Storage</b> tab, select Add > LVM. On that dialog, we select the new volume group and given it a name (I made it the same as the vg).<p>
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr5EqOzr_R7-szJ0_Qm8WiMrhON1y1vHkbhnS2FoXJprtbcctCa1n07wj-O8PDKFGqoMTpXZCDPmZNQC322AECH8bc3Uw-lTTD1xXprXYjf9mPD1qj4G3XSnui9EZTcf9jUbsAJFNNLrk/s1600/raid.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgr5EqOzr_R7-szJ0_Qm8WiMrhON1y1vHkbhnS2FoXJprtbcctCa1n07wj-O8PDKFGqoMTpXZCDPmZNQC322AECH8bc3Uw-lTTD1xXprXYjf9mPD1qj4G3XSnui9EZTcf9jUbsAJFNNLrk/s1600/raid.png" /></a></div>
<p>And your storage is made available to Proxmox!<p>
<p>I went ahead and moved the couple VMs I had from the old main storage to the new array. You can do this by highlighting the Hard Disk on the VM's <b>Hardware</b> tab, and clicking "Move disk".</p>Jonathon Reinharthttp://www.blogger.com/profile/04790032076191957141noreply@blogger.com0tag:blogger.com,1999:blog-1764037540275477749.post-59140807407115879082015-01-10T07:15:00.000-05:002015-01-10T07:15:44.679-05:00Add Suspend and Hibernate to GNOME 3 shell status menu in CentOS 7<p>I spent days searching for the <i>Suspend</i> option in my new CentOS 7 installation.</p>
<p>Well, I finally found it, but it wasn't as easy as you'd expect.</p>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9VgKzO2et_Y6o5ee-fStP6p16t9f_u24vf1PfUPTX-tjo-EFUayl7T1gO24Fsv7oSlgYqMNMhjWQUyMZ_eXD4JYFzikV_c5MLB2uxamwk02e5r_9SiUqHgWFMIsWFBYxOvXknx9HmVEA/s1600/Screenshot+from+2015-01-10+07:02:34.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi9VgKzO2et_Y6o5ee-fStP6p16t9f_u24vf1PfUPTX-tjo-EFUayl7T1gO24Fsv7oSlgYqMNMhjWQUyMZ_eXD4JYFzikV_c5MLB2uxamwk02e5r_9SiUqHgWFMIsWFBYxOvXknx9HmVEA/s1600/Screenshot+from+2015-01-10+07:02:34.png" height="400" width="320" /></a><br />
<br />
<p>First you need to install the <code>gnome-shell-extension-alternative-status-menu</code> extension, as well as <code>gnome-tweak-tool</code>:</p>
<pre>
$ sudo yum install gnome-shell-extension-alternative-status-menu gnome-tweak-tool
</pre>
<p>Next, log-out and log back in.</p>
<p>Then, use <code>gnome-tweak-tool</code> to enable the fancy new extension:</p>
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKEvnBF5KKtaOhvw8OqU5hZJUVgL1BMfZ8Ibqez_AMi0zp0grs5NHLWTbXjijpcDv_DdRpCUNluyaSgG6PSNeJO5cThyx6SpsD04rRlteIfw0Y0SfekaqxZ_PKH2UdIVUSxe3aTGphe48/s1600/tweak.png" imageanchor="1"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjKEvnBF5KKtaOhvw8OqU5hZJUVgL1BMfZ8Ibqez_AMi0zp0grs5NHLWTbXjijpcDv_DdRpCUNluyaSgG6PSNeJO5cThyx6SpsD04rRlteIfw0Y0SfekaqxZ_PKH2UdIVUSxe3aTGphe48/s400/tweak.png" /></a>
<p>And there you have it; a menu that Windows has had by default for a decade.</p>Jonathon Reinharthttp://www.blogger.com/profile/04790032076191957141noreply@blogger.com1tag:blogger.com,1999:blog-1764037540275477749.post-86133509624508407882015-01-03T02:17:00.002-05:002015-01-03T02:19:12.228-05:00Dual Booting with GRUB2 (CentOS 7) and Windows 7<p><b>TL;DR:</b>You need to install the <code>ntfs-3g</code> package, in order for <code>os-prober</code> to detect Windows installations. This allows <code>grub2-mkconfig</code> to automatically generate an entry for dual-booting into Windows.</p>
<hr/>
<p>Doing a lot more hardware hacking these days, I've felt constrained running Linux in a VM all the time. I was especially disappointed that <a href="https://www.virtualbox.org/ticket/4032">VirtualBox doesn't expose nested Intel VT-x</a> features to its guests. So I've decided to try dual-booting again, going with the very stable <a href="http://www.centos.org/download/">CentOS</a> 7.</p>
<p>Not willing to sacrifice any space on my Windows SSD, I put another Crucial SSD in my machine - this time the <a href="https://www.google.com/shopping/product/18358276604549477971">256 GB version of their newer MX100 series</a>. Downloading the NetInstall ISO and pointing at a relatively close mirror gave a very satisfying install experience. Having the whole drive made things quite easy as well - except for the actual Dual-Booting part.</p>
<p>I wasn't terribly surprised that the setup process didn't automatically add a <a href="https://fedoraproject.org/wiki/GRUB_2?rd=Grub2">GRUB 2</a> entry for booting to my Windows 7 drive. Everything I read indicated that simply running <code>grub2-mkconfig</code> should set up the GRUB config script to include Windows. Yet, it wasn't working for me. Supposedly GRUB 2 uses <code>os-prober</code> to automatically detect other OSes and generate boot entries for them. However, running <code>os-prober</code> showed no Windows install, even though my drive was clearly visible.</p>
<p>After stumbling across this <a href="http://www.linuxquestions.org/questions/linux-newbie-8/centos-7-dual-boot-with-windows-4175514202/page2.html#post5224749">post on LinuxQustions.org</a>, it turns out that the <a href="http://en.wikipedia.org/wiki/NTFS-3G">NTFS-3g</a> package (for mounting NTFS volumes) isn't installed by default, and <code>os-prober</code> needs this the mount the drive and detect the installed OS. After installing <code>ntfs-3g</code> (from the <a href="http://fedoraproject.org/wiki/EPEL">EPEL</a> repository), I was able to run <code>grub2-mkconfig -o /boot/grub2/grub.cfg</code> and successfully add an entry for Windows 7.</p>Jonathon Reinharthttp://www.blogger.com/profile/04790032076191957141noreply@blogger.com0tag:blogger.com,1999:blog-1764037540275477749.post-73148924906883933032014-12-30T06:59:00.001-05:002015-01-10T05:25:57.115-05:00Installing Nemiver on Centos 7<p>I recently heard about <a href="https://wiki.gnome.org/Apps/Nemiver">Nemiver</a>, a standalone C/C++ debugger for GNOME, and wanted to give it a try.</p>
<p>My current Linux development box is running CentOS 7. While <a href="http://pkgs.org/centos-6/epel-x86_64/nemiver-0.8.2el6-1.el6.x86_64.rpm.html">Nemiver packages exist for CentOS 6</a>, the same cannot be said for CentOS 7. So I proceeded to build it from source.</p>
<p>First, I went ahead and cloned the Git repository: <code>git clone git://git.gnome.org/nemiver</code></p>
<p>After running the <code>./autogen.sh</code> script, it was clear that I was in for several iterations of dependency installation. I'll save you the trouble:</p>
<code>sudo yum install gnome-common intltool yelp-devel yelp-tools boost-devel sqlite-devel GConf2-devel libgtop2-devel glibmm24-devel gtkmm30-devel gtk3-devel gtksourceview3-devel vte3 vte3-devel</code>
<p>Note that I do have the EPEL repository enabled, so I'm not sure if some of those packages came from EPEL or not.</p>
<p>Unfortunately, there seems to be no <code>gtksourceviewmm-3.0</code> package for CentOS 7 either! Sure, why not install that one from source, too?</p>
<p>First, download <a href="http://pkgs.fedoraproject.org/repo/pkgs/gtksourceviewmm3/"><code>gtksourceviewmm-3.2.0.tar.xz</code></a> (or later). By default, <code>configure</code> defaults to <code>PREFIX=/usr/local</code>. If you don't change this, <code>pkg-config</code> won't know where do find it. So <code>./configure --prefix=/usr --libdir=/usr/lib64</code> seems to be what we want. Then <code>make</code>, <code>sudo make install</code> as usual.</p>
<p>Now, you should be able to finish configuring and making Nemiver!</p>
<p>Note that there also seemed to be a build issue in <code>src/confmgr/nmv-gconf-mgr.cc</code>. The following patch took care of it for me - not sure how this went unnoticed.</p>
<pre>
--- a/src/confmgr/nmv-gconf-mgr.cc
+++ b/src/confmgr/nmv-gconf-mgr.cc
@@ -32,6 +32,7 @@
NEMIVER_BEGIN_NAMESPACE (nemiver)
using nemiver::common::GCharSafePtr;
+using nemiver::common::GErrorSafePtr;
class GConfMgr : public IConfMgr {
GConfMgr (const GConfMgr &);
</pre>
<p>Until this is fixed, you can use my fork at <code>git@github.com:JonathonReinhart/nemiver.git</code></p>
Jonathon Reinharthttp://www.blogger.com/profile/04790032076191957141noreply@blogger.com0tag:blogger.com,1999:blog-1764037540275477749.post-56045773781660263972014-10-23T18:13:00.001-04:002015-02-07T13:38:04.253-05:00GitLab time zone issues<a href="https://about.gitlab.com/" target="_blank">GitLab</a> is a great open source GitHub clone, which I've started using for tracking my personal Git repos.<br />
<br />
One frustrating thing I've found with GitLab however, is its handling of time zones.<br />
<br />
Read:<br />
<ul>
<li><a href="https://github.com/gitlabhq/gitlabhq/issues/7049" target="_blank">Wrong time on gitlab events #7049</a></li>
<li><a href="http://feedback.gitlab.com/forums/176466-general/suggestions/5742594-allow-user-to-select-their-timezone-in-profile" target="_blank">Allow user to select their timezone in profile</a></li>
<li><a href="http://feedback.gitlab.com/forums/176466-general/suggestions/5890076-add-timezone-configuration-to-gitlab-yml" target="_blank">Add timezone configuration to gitlab.yml</a></li>
</ul>
<br />
Apparently GitLab doesn't detect the user's timezone (or store it in their profile) and display times accordingly. Everything outside of the Git timestamps appears to be tracked in UTC.<br />
<br />
To fix this for my local server, I edited<br />
<code>/opt/gitlab/embedded/service/gitlab-rails/config/application.rb</code><br />
and specified<br />
<code>config.time_zone = 'Eastern Time (US & Canada)'</code><br />
<code><br /></code>
<h3>Update:</h3>
<p>In <a href="https://gitlab.com/gitlab-org/gitlab-ce/blob/7-7-stable/CHANGELOG" target="_blank">version 7.5.0</a>, this configuration option was moved to <code>gitlab.yml</code>. Now you don't have to re-set this option after every upgrade. Instructions for how to set it for an Omnibus install (in <code>/etc/gitlab/gitlab.rb</code>) are <a href="https://github.com/gitlabhq/gitlabhq/pull/8015#issuecomment-72840835" target="_blank">here</a>.</p>Jonathon Reinharthttp://www.blogger.com/profile/04790032076191957141noreply@blogger.com1tag:blogger.com,1999:blog-1764037540275477749.post-61070014298014634972014-05-28T23:31:00.003-04:002014-05-29T00:49:03.629-04:00TrueCrypt-endToday, the TrueCrypt website and SourceForge project page suddenly changed, indicating the end of TrueCrypt development. truecrypt.org now redirects to their <a href="http://truecrypt.sourceforge.net/">SourceForge project page</a>, and the content has been replaced with a surprising message:
<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_NAiM70UZs4pe0XnkGeoY3Gs56p1Phw1OfBcGLIlFyeDvf22AmDEUj5TPXr2_5vjh4EBjMu0PwuWL9aPSWfw_bUitqkajjC6BTfGbl2l1qhyphenhyphenkmFcEoaXMgPR9xjsnM1RBawwjCVjO7A8/s1600/Capture.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi_NAiM70UZs4pe0XnkGeoY3Gs56p1Phw1OfBcGLIlFyeDvf22AmDEUj5TPXr2_5vjh4EBjMu0PwuWL9aPSWfw_bUitqkajjC6BTfGbl2l1qhyphenhyphenkmFcEoaXMgPR9xjsnM1RBawwjCVjO7A8/s1600/Capture.PNG" height="341" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Not only has development officially ceased, but TrueCrypt is being declared "not secure", and the official webpage is suggesting that people <i>migrate to BitLocker!</i> (<a href="http://windows.microsoft.com/en-us/windows7/products/features/bitlocker" target="_blank">BitLocker</a> is the drive encryption solution built in to some versions of Windows Vista and later.) Furthermore, a new version 7.2 had been released, which warns users that TrueCrypt is insecure. The repository had been scrubbed, and all previous binaries had been deleted.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
I'm sure you could almost hear the collective <b><i>WTF?!</i></b> from everyone in the <a href="http://en.wikipedia.org/wiki/Information_security" target="_blank">InfoSec</a> community.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
A series of edits indicating that the software had been discontinued were even posted to the <a href="http://en.wikipedia.org/wiki/TrueCrypt" target="_blank">TrueCrypt Wikipedia page</a> by a user with the handle <a href="http://en.wikipedia.org/wiki/Special:Contributions/Truecrypt-end" target="_blank">Truecrypt-end</a>.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
At first, it seemed like some pranksters had managed to take over the TrueCrypt website, and poke fun by suggesting users migrate to their inferior commercial competitor, BitLocker. Well, the <a href="http://dnshistory.org/dns-records/truecrypt.org" target="_blank">DNS records had not changed</a>, so everything was good there. And <a href="https://news.ycombinator.com/item?id=7813121):" target="_blank">SourceForge indicated</a> that there was no suspicious behavior on the account (ya know, aside from closing everything down!)</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Of course there are rumors abound at all of the tech watering holes, from <a href="http://it-beta.slashdot.org/story/14/05/28/2126249/truecrypt-website-says-to-switch-to-bitlocker" target="_blank">Slashdot</a> to the <a href="http://www.reddit.com/r/sysadmin/comments/26pxol/truecrypt_is_dead/" target="_blank">/r/sysadmin subreddit</a> to the <a href="http://security.stackexchange.com/q/58940/35748" target="_blank">InfoSec Stack Exchange</a> site and of course <a href="https://twitter.com/hashtag/TrueCrypt?src=hash" target="_blank">Twitter</a>. While many still believe that the project was hacked, others are pondering the possibility that the devs were asked to insert a back-door, and subject to a gag-order preventing them from disclosing the requirement. The TrueCrypt development team has remained behind the big black curtain for most of its development which makes the situation even more curious. Perhaps a vulnerability had been discovered and the developers simply didn't want to be involved with the product any more. There is certainly no <a href="https://news.ycombinator.com/item?id=7812133" target="_blank">shortage of opinions</a> on the matter. The most interesting theory I've heard is that this is a sort of <a href="http://www.reddit.com/r/netsec/comments/26pz9b/truecrypt_development_has_ended_052814/" target="_blank">warrant canary</a>.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<b>So what about this new version 7.2?</b></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
The binaries were <a href="http://www.reddit.com/r/netsec/comments/26pz9b/truecrypt_development_has_ended_052814/chtl7jb" target="_blank">signed with the same GPG key</a> as all previous releases, indicating that this release was "official", or at least produced by someone with access to the private key.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Internally, the TrueCrypt.exe executable and the truecrypt(-x64).sys drivers were signed (a la Microsoft Authenticode) with a different certificate than 7.1.1, but that certificate expired shortly after the last release. This new certificate was issued (to the same named entity) shortly before the previous certificate expired. It's very unlikely that someone was able to spoof a new certificate in this manner, and had planned it two years ago. [Screenshots tomorrow.]</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
The <a href="https://github.com/warewolf/truecrypt/compare/master...7.2" target="_blank">changes to the latest version</a>'s source code were posted to GitHub. This paints probably the most confusing picture of all. </div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
First, the code has been littered with warning messages and error codes indicating that <a href="https://github.com/warewolf/truecrypt/compare/master...7.2#diff-ab89cf3b379504f57d3f2655ad8c60a1R79" target="_blank">"Using TrueCrypt is not secure"</a>. Next, we see that pretty much all of the code related to creating encrypted volumes has been removed, and replaced with <span style="color: #333333; font-family: Consolas, 'Liberation Mono', Courier, monospace; font-size: 12px;">AbortProcess ("INSECURE_APP");. </span>We also notice that all code related to updates, <a href="https://github.com/warewolf/truecrypt/compare/master...7.2#diff-9fc90217decda8d7d16d55ffaf7401c0L1657" target="_blank">error reporting</a>, <a href="https://github.com/warewolf/truecrypt/compare/master...7.2#diff-9fc90217decda8d7d16d55ffaf7401c0L7987" target="_blank">user's guide/help</a>, or <a href="https://github.com/warewolf/truecrypt/compare/master...7.2#diff-387d555ecb42d81377e57d7190c60d94L591" target="_blank">anything</a> <a href="https://github.com/warewolf/truecrypt/compare/master...7.2#diff-d588c1a136d84cbb36c875bee73e0925L782" target="_blank">pointing back</a> to the TrueCrypt website has been removed. Clearly, the developers consciously made the decision to burn all bridges, and carefully executed a plan to do so.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
What's very bizarre however, is that while there were 4112 deletions, there were also 1760 <i>additions</i> to the code. Along with other minor bugfixes, it appears that <a href="https://github.com/warewolf/truecrypt/compare/master...7.2#diff-21d38496be9ec14e4db3819ba7f36835R6989" target="_blank">in-place decryption</a> was newly implemented. It looks as if this was code that was part of an upcoming release that brought some improvements after a two-year break. Unfortunately, it also came with mass deletions that rendered the software useless for anyone seeking to create encrypted content.</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<i>What are you thoughts?</i></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
Jonathon Reinharthttp://www.blogger.com/profile/04790032076191957141noreply@blogger.com0tag:blogger.com,1999:blog-1764037540275477749.post-22005516120137215032013-03-07T01:31:00.000-05:002013-10-20T13:37:44.674-04:00Gotta catch 'em all: Last-chance exception handling in .NET with WinFormsRecently, I went through the exercise of hooking up a crash-reporting component to a large .NET application using Windows Forms. The goal, of course, is to catch <b>all </b>unhandled exceptions so they can be reported to the developer.<br/>
<br/>
Throughout this post I'll be referring to <a href="http://jonathon.onthefive.com/public/WinFormExceptions/Program.cs" target="_blank">this Program.cs</a>. The code we incrementally un-commented for each of the examples. <small>I'll also link to compiled example executables. If you don't trust my binaries, you can <a href="http://jonathon.onthefive.com/public/WinFormExceptions/WinformsExceptionsTest.zip">compile them yourself</a>.</small><br />
<hr/>
<br/><br/>
<h3>0. No exception handling</h3>
First we see an application that throws exceptions in the UI thread and a background thread, with no handling. Try out <a href="http://jonathon.onthefive.com/public/WinFormExceptions/0_Nothing.exe">0_Nothing.exe</a>.<br />
With no exception handling, background thread exceptions crash hard. UI thread exceptions are handled by the built-in .NET WinForms handler:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHB8qMbE4tU-FLk6QVsnqxPMsAFr2uK0zPIs_Bi20X89SyeCFS8ZGz0zb-jE1ZQ6tMP0zIYw4Jj7Z9eV4J6rBuany_6pN9ztNUNs2rLx3RuLzWC1vquPiPRuuym5ZqBu-SiJluR715tcU/s1600/UnhandledException.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhHB8qMbE4tU-FLk6QVsnqxPMsAFr2uK0zPIs_Bi20X89SyeCFS8ZGz0zb-jE1ZQ6tMP0zIYw4Jj7Z9eV4J6rBuany_6pN9ztNUNs2rLx3RuLzWC1vquPiPRuuym5ZqBu-SiJluR715tcU/s1600/UnhandledException.PNG" /></a></div>
<br />
This has a Continue option which allows the user to ignore the exception and go on. This method is absolutely unacceptable. No exceptions should ever be allowed to be ignored, as the program is in an indeterminate state.<br />
<br/><br/>
<h3>1. try / catch</h3>
The naive approach would be to set up a <code>try</code>/<code>catch</code> block in <code>Main()</code> around the <code>Application.Run()</code> call. See <a href="http://jonathon.onthefive.com/public/WinFormExceptions/1_TryCatch.exe">1_TryCatch.exe</a>.
<br />
<pre>try {
Application.Run(new Form1());
}
catch (Exception ex) {
// ...
}</pre>
We see here that there is no difference between this and the version with no <code>try</code>/<code>catch</code>. This is because the UI thread exceptions are still being handled inside of <code>Application.Run()</code> by the default handler. The <code>try</code>/<code>catch</code> is never used, and background thread exceptions are unaffected.<br/>
<br/><br/>
<h3>2. Application.ThreadException</h3>
Next, we utilize WinForms' <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.application.threadexception.aspx"><code>Application.ThreadException</code></a> event to handle UI thread exceptions. See <a href="http://jonathon.onthefive.com/public/WinFormExceptions/2_Application_ThreadException.exe">2_Application_ThreadException.exe</a>.
<pre>Application.ThreadException += (sender, args) =>
HandleException("Application.ThreadException", args.Exception);</pre>
Here, we see that instead of the unacceptable WinForms handler, our handler was called (for UI thread exceptions). However, as MSDN points out (emphasis mine):
<blockquote>This event allows your Windows Forms application to handle otherwise unhandled exceptions that occur in Windows Forms threads.<br/>...<br/>To catch exceptions that occur in threads not created and owned by Windows Forms, use the <a href="http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx"><code>UnhandledException</code></a> event handler.</blockquote>
So background thread exceptions still crash hard in this example.<br/>
<br/><br/>
<h3>3. AppDomain.UnhandledException</h3>
Now we follow the documentation and hook up the <a href="http://msdn.microsoft.com/en-us/library/system.appdomain.unhandledexception.aspx"><code>AppDomain.UnhandledException</code></a> handler. See <a href="http://jonathon.onthefive.com/public/WinFormExceptions/3_AppDomain_UnhandledException_NoUhandledMode.exe">3_AppDomain_UnhandledException_NoUhandledMode.exe</a>.
<pre>AppDomain.CurrentDomain.UnhandledException += (sender, args) =>
HandleException("AppDomain.UnhandledException", (Exception)args.ExceptionObject);</pre>
Now finally, we are able to catch exceptions on background threads with this handler. UI thread exceptions, however, are still handled by our <code>Application.ThreadException</code> handler.<br/>
<br/><br/>
<h3>4. Application.SetUnhandledExceptionMode</h3>
As mentioned in the MSDN documentation, a call to <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.application.setunhandledexceptionmode.aspx"><code>Application.SetUnhandledExceptionMode</code></a> and passing <a href="http://msdn.microsoft.com/en-us/library/system.windows.forms.unhandledexceptionmode.aspx"><code>UnhandledExceptionMode.ThrowException</code></a> tells Winforms to not use the <code>Application.ThreadException</code> handler. Instead, it lets exceptions bubble out of Application.Run. See this in <a href="http://jonathon.onthefive.com/public/WinFormExceptions/4_Everything.exe">4_Everything.exe</a>.
<pre>Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);</pre>
The result is that the <code>try</code>/<code>catch</code> around <code>Application.Run</code> actually works now: UI thread exceptions are now caught by that handler.<br/>
<br/><br/>
<h3>5. No more try / catch</h3>
Finally, removing the <code>try</code>/<code>catch</code> around <code>Application.Run</code> allows for <u>all</u> unhandled exceptions to be handled via <code>AppDomain.UnhandledException</code>. See <a href="http://jonathon.onthefive.com/public/WinFormExceptions/5_Final.exe">5_Final.exe</a>. This is how we ended up handling everything in our application; we found it ideal to have one route for all<sup><a href="#footnote-1">[1]</a></sup> unhandled exceptions.<br/>
<hr/>
<br/><br/>
<h3>Summary</h3>
It is important to note that all exceptions are handled on the thread that they occurred on. If you're in the same boat I was in, you're stuck with a third-party crash handler component that had to be run on the UI thread. Because of this, I marshal the calls to the UI thread with a call to <code>Control.Invoke()</code>, as usual for cross-thread UI stuff.<br/>
<br/>
<p id="footnote-1">[1] - In fact it gets <i>even more</i> complicated. There are certain scenarios where exceptions that need to cross Kernel or COM boundaries can be swallowed. For example, the <code>Form.OnLoad</code> method is actually a user-mode kernel callback. These are <a href="http://blog.paulbetts.org/index.php/2010/07/20/the-case-of-the-disappearing-onload-exception-user-mode-callback-exceptions-in-x64/">notorious</a> for swallowing exceptions. In cases where we are sufficiently suspect of exceptions, we set up a <code>try</code>/<code>catch</code> and manually hand off the exception to the common handler.</p>
The full source code for my example binaries can be <a href="http://jonathon.onthefive.com/public/WinFormExceptions/WinformsExceptionsTest.zip">downloaded here</a>.Jonathon Reinharthttp://www.blogger.com/profile/04790032076191957141noreply@blogger.com1tag:blogger.com,1999:blog-1764037540275477749.post-6996208534405197712013-02-25T00:49:00.000-05:002013-02-25T00:54:14.204-05:00goto: The Forbidden Fruit<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbXdO5N-pEb8-nsWtU9WC4TjAOsMUYASYdLaqh63uLySwdOx6k1_Zf9Yqzp0iInkfnngpn6YMCc-SyDhiEDtEm1oihuw2GcJEUmhRQXZ-CEEygWqKMnzm6ObaEFmuCSI6E1NouDWSCehc/s1600/goto.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="180" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjbXdO5N-pEb8-nsWtU9WC4TjAOsMUYASYdLaqh63uLySwdOx6k1_Zf9Yqzp0iInkfnngpn6YMCc-SyDhiEDtEm1oihuw2GcJEUmhRQXZ-CEEygWqKMnzm6ObaEFmuCSI6E1NouDWSCehc/s200/goto.png" width="200" /></a></div>
<br />
<br />
Nowdays, it's not hard to find tons of arguments against the use of <code>goto</code> in C (and C-like languages). Post anything to <a href="http://stackoverflow.com/" target="_blank">StackOverflow</a>, about/including <code>goto</code> and you're almost guaranteed to get flamed.<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="http://imgs.xkcd.com/comics/goto.png" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="173" src="http://imgs.xkcd.com/comics/goto.png" width="640" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><br /></td></tr>
</tbody></table>
Just like many good and useful things in our lives (pocketknives, guns, kegs, etc.) it only takes a few people to abuse something before everyone else categorizes it as "bad". But the truth is, <code>goto</code> is a simple tool that, when used correctly, can make a program much easier to write (and even understand!)<br />
<br />
First, let's take a look at how *not* to use <code>goto</code> (this is just a little example, nothing meaningful):<br />
<br />
<code>int foo(int a)<br />
{</code><br />
<code> int bar;</code><br />
<span class="Apple-style-span" style="font-family: monospace;"> while (bar < spam())</span><br />
<code> {</code><br />
<code>loop:</code><br />
<code> bar = a * scale;</code><br />
<code> if (bar > 100) goto toobig;</code><br />
<code> bla(bar);</code><br />
<code> }</code><br />
<code> return bar;</code><br />
<code>toobig:</code><br />
<code> if (bar-tar > 0)</code><br />
<code> return bar;</code><br />
<code> bar -= 5; goto loop;</code><br />
<code><br />
</code><br />
<code> return bar * 2;</code><br />
<code> }<br />
</code><br />
<br />
Wow, that was even hard to come up with, and cetrainly isn't the way to do things. Jumping in and out of control structures is bound to confuse the next guy, and possibly the compiler when it is trying to optimize. <br/><br/>
But in the right places, <code>goto</code> can be extremely useful. Luckily, my opinion here is not alone. In fact, the Linux Kernel (3.8) uses <code>goto</code> over 100,000 times!
<pre>$ find linux-3.8 -iname '*.c' -exec grep 'goto' {} \; | wc -l
104299</pre>
Here is a good example of this programming style in use, from the <a href="http://lxr.linux.no/linux+v3.8/fs/ext4/extents.c#L411">ext4 driver</a>.
<br/><br/>
<hr/>
First, let's look at some bad code. The author does two things that I really dislike: 1) They return all over the place. This is okay, unless (like in this example) you have to deal with resource de-allocation. Here, this leads to a fragile situation with lots of calls to free. 2) They check first for success, which leads to ridiculous amounts of nesting.<br />
<pre>bool baz() {
bool result = false;
uint8_t *buf1 = NULL;
uint8_t *buf2 = NULL;
uint8_t *buf3 = NULL;
// Allocate buffers.
buf1 = malloc(BUF1_SIZE);
if (buf1) {
buf2 = malloc(BUF2_SIZE);
if (buf2) {
buf3 = malloc(BUF3_SIZE);
if (buf3) {
result = use_buffers(buf1, buf2, buf3);
if (result)
printf("Success!\n");
else
fprintf(stderr, "Operation failed.\n");
free(buf3);
free(buf2);
free(buf1);
return result;
}
else {
fprintf(stderr, "Error allocating %d bytes.\n", BUF3_SIZE);
free(buf2);
free(buf1);
return false;
}
}
else {
fprintf(stderr, "Error allocating %d bytes.\n", BUF2_SIZE);
free(buf1);
return false;
}
}
else {
fprintf(stderr, "Error allocating %d bytes.\n", BUF1_SIZE);
return false;
}
}
</pre>
<br />
<hr/>
Using <code>goto</code> and a single exit point clean this mess up very nicely:<br />
<pre>bool baz() {
bool result = false; // Assume failure until proven successful
uint8_t *buf1 = NULL;
uint8_t *buf2 = NULL;
uint8_t *buf3 = NULL;
// Allocate buffers.
buf1 = malloc(BUF1_SIZE);
if (!buf1) {
fprintf(stderr, "Error allocating %d bytes.\n", BUF1_SIZE);
goto exit;
}
buf2 = malloc(BUF2_SIZE);
if (!buf2) {
fprintf(stderr, "Error allocating %d bytes.\n", BUF2_SIZE);
goto exit;
}
buf3 = malloc(BUF3_SIZE);
if (!buf3) {
fprintf(stderr, "Error allocating %d bytes.\n", BUF3_SIZE);
goto exit;
}
// Do something useful
if (!use_buffers(buf1, buf2, buf3)) {
fprintf(stderr, "Operation failed.\n");
goto exit;
}
result = true;
printf("Success!\n");
exit:
if (buf1) free(buf1);
if (buf2) free(buf2);
if (buf3) free(buf3);
return result;
}
</pre>
<br />
This allows for a very straight-forward approach to handling resource allocation/freeing and a clean exit path. It's much easier to maintain as well (imagine having to remove <code>buf2</code> in the first example!)<br/>
<hr/>
An alternative to <code>goto</code> I often see is the dummy do-while loop:
<br />
<pre>bool baz() {
bool result = false;
uint8_t *buf1 = NULL;
uint8_t *buf2 = NULL;
uint8_t *buf3 = NULL;
do {
// Allocate buffers.
buf1 = malloc(BUF1_SIZE);
if (!buf1) {
fprintf(stderr, "Error allocating %d bytes.\n", BUF1_SIZE);
break;
}
buf2 = malloc(BUF2_SIZE);
if (!buf2) {
fprintf(stderr, "Error allocating %d bytes.\n", BUF2_SIZE);
break;
}
buf3 = malloc(BUF3_SIZE);
if (!buf3) {
fprintf(stderr, "Error allocating %d bytes.\n", BUF3_SIZE);
break;
}
// Do something useful
if (!use_buffers(buf1, buf2, buf3)) {
fprintf(stderr, "Operation failed.\n");
break;
}
result = true;
printf("Success!\n");
} while(0);
if (buf1) free(buf1);
if (buf2) free(buf2);
if (buf3) free(buf3);
return result;
}
</pre>
<br />
This isn't terrible, but what about when you want to use an actual loop inside that dummy do-while, and break out of it? PHP includes a <s>nice</s> disgusting feature to <a href="http://php.net/manual/en/control-structures.break.php">break out of multiple levels</a>. In other languages you're screwed, unless you follow the loop with some additional code to check for completion of the loop:<br />
<br />
<pre>bool baz() {
bool result = false;
uint8_t *buf1 = NULL;
uint8_t *buf2 = NULL;
int i;
do {
// Allocate buffers.
buf1 = malloc(BUF1_SIZE);
if (!buf1) {
fprintf(stderr, "Error allocating %d bytes.\n", BUF1_SIZE);
break;
}
buf2 = malloc(BUF2_SIZE);
if (!buf2) {
fprintf(stderr, "Error allocating %d bytes.\n", BUF2_SIZE);
break;
}
// Do something in a loop
for (i=0; i<CONSTANT; ++i) {
if (!use_buffers(buf1, buf2)) {
fprintf(stderr, "Operation #%d failed.\n", i);
break; // Can't get out of the do-while from here!
}
}
// Have to add this ridiculous check, because we could have exited
// the loop early...
if (i==CONSTANT) {
result = true;
printf("Success!\n");
}
} while(0);
if (buf1) free(buf1);
if (buf2) free(buf2);
return result;
}</pre>
In this case, a <code>goto exit;</code> would have worked just fine.
<br/>Jonathon Reinharthttp://www.blogger.com/profile/04790032076191957141noreply@blogger.com0tag:blogger.com,1999:blog-1764037540275477749.post-11088416971766982552013-02-24T23:24:00.000-05:002013-02-24T23:24:13.500-05:00Deftones - You've Seen the Butcher - Timing<br />
Maybe the name of this blog should include something about ADD or OCD. Either way, enough time was spent perfecting this, I figure I might as well share it with the <a href="http://xkcd.com/181/" target="_blank">Interwebs</a>.<br />
<br />
I'm a big fan of <a href="http://www.deftones.com/" target="_blank">Deftones</a> and their 2010 album <a href="http://en.wikipedia.org/wiki/Diamond_Eyes" target="_blank">Diamond Eyes</a> was unsurprisingly awesome. <a href="http://www.youtube.com/watch?v=woAcXSMyCEw" target="_blank">You've Seen the Butcher</a> is an awesome track. The timing is subtly complicated, so I decided to chart it out. Hope this helps someone.<br />
<br />
All time signatures are x/4, and the number of beats in each measure are shown. For many parts of the song, the final measure's number of beats is the same as the part that follows. These are noted.<br />
<br />
<b>Intro</b><br />
lead-in 1<br />
<br />
Guitar-only Alt. 3 and 4<br />
last measure 5<br />
<br />
Heavy riff (no vox) Alt. 3 and 5<br />
last measure 4<br />
<br />
<br />
<b>Verse 1</b><br />
Verse Alt. 3 and 4<br />
last measure 5<br />
<br />
Pre-Chorus Alt. 3 and 5<br />
<br />
Chorus 4<br />
last measure 3<br />
<br />
<br />
<b>Verse 2</b><br />
Verse Alt. 3 and 4<br />
last measure 5<br />
<br />
Pre-Chorus Alt. 3 and 5<br />
<br />
Chorus 4<br />
<br />
<br />
<b>Bridge</b> <i>note the two 6/4 measures</i><br />
<br />
Heavy riff (no vox) 3 5 3 6 3 5 3 5<br />
<br />
Pre-Chorus 3 5 3 6 3 5 3 5<br />
<br />
<br />
<b>Outro</b><br />
Chrous 4<br />
last measure 5<br />
<br />
Ending 3 (free) <br />
Jonathon Reinharthttp://www.blogger.com/profile/04790032076191957141noreply@blogger.com0tag:blogger.com,1999:blog-1764037540275477749.post-85543155063485127562012-12-13T23:56:00.003-05:002013-10-10T00:57:18.458-04:00Named Pipes between C# and PythonThere's a lot of over-complicated information on the internet for communicating between a C# process and a Python process using named pipes on Windows. I'll start with the code:<br />
<br />
<b>C#</b><br />
<blockquote>
<pre>// Open the named pipe.
var server = new NamedPipeServerStream("NPtest");
Console.WriteLine("Waiting for connection...");
server.WaitForConnection();
Console.WriteLine("Connected.");
var br = new BinaryReader(server);
var bw = new BinaryWriter(server);
while (true) {
try {
var len = (int) br.ReadUInt32(); // Read string length
var str = new string(br.ReadChars(len)); // Read string
Console.WriteLine("Read: \"{0}\"", str);
str = new string(str.Reverse().ToArray()); // Just for fun
var buf = Encoding.ASCII.GetBytes(str); // Get ASCII byte array
bw.Write((uint) buf.Length); // Write string length
bw.Write(buf); // Write string
Console.WriteLine("Wrote: \"{0}\"", str);
}
catch (EndOfStreamException) {
break; // When client disconnects
}
}
Console.WriteLine("Client disconnected.");
server.Close();
server.Dispose();
</pre>
</blockquote>
<br />
<b>Python</b><br />
<blockquote>
<pre>import time
import struct
f = open(r'\\.\pipe\NPtest', 'r+b', 0)
i = 1
while True:
s = 'Message[{0}]'.format(i)
i += 1
f.write(struct.pack('I', len(s)) + s) # Write str length and str
f.seek(0) # EDIT: This is also necessary
print 'Wrote:', s
n = struct.unpack('I', f.read(4))[0] # Read str length
s = f.read(n) # Read str
f.seek(0) # Important!!!
print 'Read:', s
time.sleep(2)
</pre>
</blockquote>
In this example, I implement a very simple protocol, where every "message" is a 4-byte integer (<code>UInt32</code> in C#, <code>'I'</code> (un)pack format in Python), which indicates the length of the string that follows. The string is ASCII.
Important things to note here:
<br />
<ul>
<li>Python</li>
<ul>
<li>The third parameter to <code>open()</code> means "unbuffered". Otherwise, it will default to line-buffered, which means it will wait for a newline character before actually sending it through the pipe.</li>
<li>I'm not sure why, but omitting the <code>seek(0)</code> will cause an IOError #0. I was clued to this by a StackOverflow <a href="http://stackoverflow.com/questions/1749001/problem-with-named-pipes-between-c-sharp-and-python">question</a>.</li>
</ul>
</ul>
<div>
References:</div>
<div>
<ul>
<li>.NET <a href="http://msdn.microsoft.com/en-us/library/bb347348.aspx"><code>NamedPipeServerStream</code></a> class on MSDN</li>
<li>Python <a href="http://docs.python.org/2/library/functions.html#open"><code>open()</code></a> method on Python.org</li>
</ul>
</div>Jonathon Reinharthttp://www.blogger.com/profile/04790032076191957141noreply@blogger.com6tag:blogger.com,1999:blog-1764037540275477749.post-42999854973146868432012-11-14T22:39:00.000-05:002012-11-14T22:39:51.084-05:00Rename SVN RepositoryIt happens sometimes: You'd like to rename your SVN repository. Well simply renaming the directory on the server won't do the trick.<br />
<br />
Thanks to <a href="http://mdinescu.com/software-development/2-how-to-rename-a-svn-repository">Miky Dinescu's post</a>, we find that the best way to do this is use <span style="font-family: Courier New, Courier, monospace; font-size: x-small;">svnadmin dump</span> and <span style="font-family: Courier New, Courier, monospace; font-size: x-small;">svnadmin load</span> to export, and import the old repository into a new one, without losing anything.<br />
<br />
I wrapped this process up in a nice, <a href="http://jonathon.onthefive.com/public/renamerepo.sh">foolproof script</a>. Hopefully it makes your life easier.Jonathon Reinharthttp://www.blogger.com/profile/04790032076191957141noreply@blogger.com0tag:blogger.com,1999:blog-1764037540275477749.post-50310522990176509002012-06-09T12:31:00.002-04:002012-06-09T13:19:43.607-04:00Cyanogenmod 9 Nightly!I am happy to say that I am running <a href="http://www.cyanogenmod.com/">Cyanogenmod</a> 9 (<a href="http://get.cm/?device=toro">nightly</a>, dated 20120608) on my Galaxy Nexus!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtBq_3uVDjianxKPxfRj2Ys8aSww0UPT6HH52ahOYujhiWylIV3FHKJJDGutRwUX4MbtUtWC5l2pDdi7QXyzO7rJ9PLALjS_cwNqZuk5I_DKWEdr7_xpl5Ofrdgk2THimGIS2JicMb4l4/s1600/Screenshot_2012-06-09-11-34-31.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="400" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgtBq_3uVDjianxKPxfRj2Ys8aSww0UPT6HH52ahOYujhiWylIV3FHKJJDGutRwUX4MbtUtWC5l2pDdi7QXyzO7rJ9PLALjS_cwNqZuk5I_DKWEdr7_xpl5Ofrdgk2THimGIS2JicMb4l4/s400/Screenshot_2012-06-09-11-34-31.png" width="225" /></a></div>
<br />
I am very happy with it, and have noticed no problems, which is pretty impressive because this is a nightly build, not even a Beta / RC. The CM9 team has done a fantastic job with this version, and stuck very close to the original ICS look and feel. <br />
<br />
Things I am happy about:<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<ul>
<li>The settings menu. The stock build just seems so crippled to me now, after seeing the CM9 settings. It is too expansive to screenshot, but still quite organized. You can tweak everything from display gamma settings, to the lock screen, to individual volumes, to kernel performance, to (my favorite!) the notification LED. <br /><br />Coming from the Incredible, which just had the orange and green notification LED, having an RGB LED that I can play with is great. I have a green blink for texts, slow red for Gmail, and fast light blue for missed calls.</li>
<li>The notification drawer. (I couldn't get a screenshot, because the drawer retracts before it is taken.) I really missed these widgets, and now have quick access buttons to toggle Wi-Fi, LTE (So happy about this one!), GPS, Silent/Vibrate/Loud, and Auto-Rotate. There are other buttons you can add, but these are the ones I wanted. Also, I tweaked the battery icon.</li>
<li>Customizable navigation buttons. I re-ordered the buttons at the bottom (to more closely match my Incredible, actually) and added the search button, which behaves the same way.</li>
<li>All of the familar 'root stuff' built right in. Superuser (of course), Wi-fi tethering, screenshot, etc.</li>
</ul>
<div>
Over I am quite pleased, and will probably keep using this on a day-to-day basis. This is the way Android was meant to be. Can't wait for an RC!<br />
<br />
Additional note: Of course, this comes without the Google Apps, so you'll want to download that zip from <a href="http://goo.im/gapps">goo.im/gapps</a>.</div>
<div>
<br /></div>Jonathon Reinharthttp://www.blogger.com/profile/04790032076191957141noreply@blogger.com0tag:blogger.com,1999:blog-1764037540275477749.post-66767147450567101342012-06-04T12:12:00.000-04:002012-06-09T12:12:42.653-04:00Android 4.0.4 OTA updateA couple days ago, I started getting notifications that a system update was ready for install. This was the <a href="http://www.anandtech.com/show/5882/galaxy-nexus-cdmalte-404-imm76k-update-rolling-out">IMM76K (Android 4.0.4)</a> <span style="border-bottom-style: dotted; border-bottom-width: 1px;" title="Over-the-air">OTA</span> update that people had been impatiently waiting on for a while. After making a nandroid backup (via <span style="border-bottom-style: dotted; border-bottom-width: 1px;" title="Clockworkmod Recovery">CWM</span>), I decided to give it a try.<br />
<br />
The system rebooted, and went to the screen with the android's belly open and the blue spinny thing. Then he was on his back, with the dreaded red triangle. I wasn't surprised that the <span style="border-bottom-style: dotted; border-bottom-width: 1px;" title="Over-the-air">OTA</span> update wasn't going to work with my modified phone.<br />
<br />
This excellent post on xda-developers gave links to the official <a href="http://forum.xda-developers.com/showpost.php?p=20843237">OTA updates</a> for the different versions of the G-Nex. So I downloaded the <a href="http://android.clients.google.com/packages/ota/verizon_prime/12f767e7a5d0.signed-mysid-IMM76K-from-ICL53F.12f767e7.zip"><span style="font-size: x-small;">mysid IMM76K from ICL53F</span></a> update.zip, and <span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">adb push</span>'d it to /sdcard. Rebooting into <span style="border-bottom-style: dotted; border-bottom-width: 1px;" title="Clockworkmod Recovery">CWM</span> recovery, I tried to install the update, but it failed with:<br />
<br />
<div style="font-family: 'Courier New', Courier, monospace; font-size: small; text-indent: 50px;">
assert failed: apply_patch_check("/system/app/VZWBackupAssistant.apk".....</div>
<br />
I knew why it was failing. I had removed some of the VZW garbage apps that cam pre-installed. Luckily, I didn't actually delete them, I had just renamed them to <span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">.apk.REMOVED</span>. After putting them back<sup>1</sup> the update installed successfully.<br />
<br />
<b>Another thing to note -</b> I didn't realize it, but the xda post pointed out this important detail: Verizon <span style="border-bottom-style: dotted; border-bottom-width: 1px;" title="Over-the-air">OTA</span> updates include a script that runs every boot, whose purpose is to restore the recovery image if it is not the expected stock image. The script is at <span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">/system/etc/install-recovery.sh</span> and the recovery image (for flashing) is <span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">/system/recovery-from-boot.p</span>. Thus, if you don't wan't to lose <span style="border-bottom-style: dotted; border-bottom-width: 1px;" title="Clockworkmod Recovery">CWM</span> (or other custom recovery), you need to rename these files.<br />
<br />
Notes:<br />
<span style="font-size: x-small;">1 - I didn't realize it, but ADB is supported in </span><span title="Clockworkmod Recovery"><span style="font-size: x-small;">CWM. When I looked in device manager while my phone was connected and in CWM, I saw one device just named "Full". I manually specified the same Samsung drivers (already installed) from before, and bingo, my phone showed up in </span><span style="font-family: 'Courier New', Courier, monospace; font-size: xx-small;">adb devices</span><span style="font-size: x-small;">.</span></span>Jonathon Reinharthttp://www.blogger.com/profile/04790032076191957141noreply@blogger.com0tag:blogger.com,1999:blog-1764037540275477749.post-67089301424921236722012-05-12T03:12:00.001-04:002012-05-12T03:12:10.352-04:00Galaxy Nexus (CDMA)Well after several months of putting up with my rebooting (sometimes looping) when I used any substantial amount of 3G data, I decided to upgrade. I was looking at the HTC Rezound and the Samsung Galaxy Nexus, and found this really good comparison <a href="http://www.phonearena.com/reviews/Verizon-Galaxy-Nexus-vs-HTC-Rezound_id2938/" target="_blank">article on phoneArena</a>. Ultimately, after many recommendations by friends, I went with the Nexus.<br />
<br />
It arrived, running Android 4.0.2. This time, I lasted about 2 days before rooting it. Everybody has their own half-assed write ups of this, but I wanted to mainly include my sources for some of these files:<br />
<br />
<ul>
<li>ADB / Fastboot Drivers - Samsung
<a href="http://www.samsung.com/us/support/owners/product/SCH-I515MSAVZW" target="_blank">SCH-I515 download page</a></li>
<li>ClockworkMod Recovery -
<a href="http://www.clockworkmod.com/rommanager" target="_blank">ClockworkMod ROM Manager page</a> -
<a href="http://download.clockworkmod.com/recoveries/recovery-clockwork-touch-5.8.0.2-toro.img">recovery-clockwork-touch-5.8.0.2-toro.img</a></li>
<li>Superuser - <a href="http://download.clockworkmod.com/test/su.zip">http://download.clockworkmod.com/test/su.zip</a></li>
</ul>
<br />
<br />
<b>ADB / Fastboot Drivers</b><br />
I downloaded the USB drivers directly from Samsung's site on their <a href="http://www.samsung.com/us/support/owners/product/SCH-I515MSAVZW" target="_blank">SCH-I515 download page</a>. It's a 23MB download which is a bit ridiculous, but I wan unable to isolate exactly which driver was required from the compressed exe.<br />
<br />
After installing them, I was able to plug in my phone, turn on USB debugging, execute "adb devices" and see my device. Next, I rebooted into fastboot mode (hold all three buttons to turn it on). At this point, the device showed up as "Android 1.0". However, I was able to fix that by:<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvTwThg3m60fHmN_qVq_Pz2CTmDHkRoJ3xIVBLDIS0BsF4tyjrPOfPnC5kg05dUzv3amO2Oh1qUuthXtv2-q8ug4swqSHbPKWYglOtsnzQ2M1XcioFl4iHLZfb8nlbyZosx2zpfz7u7zc/s1600/temp1.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgvTwThg3m60fHmN_qVq_Pz2CTmDHkRoJ3xIVBLDIS0BsF4tyjrPOfPnC5kg05dUzv3amO2Oh1qUuthXtv2-q8ug4swqSHbPKWYglOtsnzQ2M1XcioFl4iHLZfb8nlbyZosx2zpfz7u7zc/s1600/temp1.png" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwd7mZvn437tvGbbTH_VbQp3AJRxLy3r4DARLpjbN4oi7O-_VlgVsg-gK5VB3KRhzyyxiwHWaIp4sj5FLC7tWLYuvFhRfKh993qHjRJo0tQF-FQ9hxTlKVCsyz2BmMwnjJ_UWzyM1D7xs/s1600/temp2.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgwd7mZvn437tvGbbTH_VbQp3AJRxLy3r4DARLpjbN4oi7O-_VlgVsg-gK5VB3KRhzyyxiwHWaIp4sj5FLC7tWLYuvFhRfKh993qHjRJo0tQF-FQ9hxTlKVCsyz2BmMwnjJ_UWzyM1D7xs/s1600/temp2.png" /></a></div>
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM-mnOfA9FiKf1YXbjh9DklpTpF1jxDdxTGIFHRAHc8OMmEFT7UtzSnMrNArAB9OqjWkM9orBB46F-b0KDK698ZQ7T000H2t9YUQQCZBHDoEJxVvSBv1wY_U-hca-3IChTg8hyRseevjI/s1600/temp3.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhM-mnOfA9FiKf1YXbjh9DklpTpF1jxDdxTGIFHRAHc8OMmEFT7UtzSnMrNArAB9OqjWkM9orBB46F-b0KDK698ZQ7T000H2t9YUQQCZBHDoEJxVvSBv1wY_U-hca-3IChTg8hyRseevjI/s1600/temp3.png" /></a></div>
<br />
<br />
<br />
<b><br /></b><br />
<b><br /></b><br />
Then, there should be just one "SAMSUNG Android ADB Interface" listed.<br />
<br />
After correcting the driver issue, I was able to execute "fastboot devices" and see my device. <br />
<br />
<b>Unlock Bootloader</b><br />
Next step is "fastboot oem unlock" !<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhULHjZkDl750xOlfi_gez2-3ChmjLr1U6-OfrN4Eo4f9PqT7eyVQ7Ldt6SjqK5__Wme4lALdkV_3pxsEjBovszpWEgC1muiCiGrVY0lPwGBrQviTDBBNh1JBox1Sd-rX5X_GggB-NznS4/s1600/2012-05-11+23.35.38.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhULHjZkDl750xOlfi_gez2-3ChmjLr1U6-OfrN4Eo4f9PqT7eyVQ7Ldt6SjqK5__Wme4lALdkV_3pxsEjBovszpWEgC1muiCiGrVY0lPwGBrQviTDBBNh1JBox1Sd-rX5X_GggB-NznS4/s320/2012-05-11+23.35.38.jpg" width="240" /></a></div>
<br />
After unlocking, I rebooted, and the Google screen now has an unlocked icon!<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2uDrqE3zJZGOMbf2bdf-eY73BjXVQO39Rvd7BM-6qZNb6VqEKCRsNLgf1FTytzwRlM5Q0aO3uzLq4EhtSnTQ7iv-pR_UkEcSh1Iyi6RNp-Ev18jbbq0N9gKvwRa2FG1KqolEoFYzqB1g/s1600/2012-05-11+23.38.06.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEj2uDrqE3zJZGOMbf2bdf-eY73BjXVQO39Rvd7BM-6qZNb6VqEKCRsNLgf1FTytzwRlM5Q0aO3uzLq4EhtSnTQ7iv-pR_UkEcSh1Iyi6RNp-Ev18jbbq0N9gKvwRa2FG1KqolEoFYzqB1g/s320/2012-05-11+23.38.06.jpg" width="240" /></a></div>
<br />
<b>ClockworkMod Recovery</b><br />
After making sure the phone booted OK, I flashed the latest (touch) version of CWM from the <a href="http://www.clockworkmod.com/rommanager" target="_blank">ClockworkMod ROM Manager page</a>. At this time, that version was <a href="http://download.clockworkmod.com/recoveries/recovery-clockwork-touch-5.8.0.2-toro.img">recovery-clockwork-touch-5.8.0.2-toro.img</a>. Simply download and "fastboot flash recovery recovery-clockwork-touch-5.8.0.2-toro.img".<br />
<br />
<b>ROOT</b><br />
Next, I rebooted, and went through the initial setup. Now it's time to actually get root! The page that I had been following included some version of SuperSU. I didn't really want to just use what they gave me, and went on the hunt for the latest su.<br />
<br />
Note for root newbies: "Root" essentially means having access to the <a href="http://dictionary.die.net/su">su</a> ("superuser") binary, which allows a process to run as the root user. On android, "root" is two components: The su binary (linux executable), and Superuser.apk, which is the accompanying Android app, which manages requests for root, logs, etc.<br />
<br />
It appears that <a href="http://androidsu.com/superuser/">androidsu.com</a> is the true "home" of superuser for Android. So I downloaded the latest, Superuser-3.0.7-efghi-signed.zip, and used "adb push ....zip /sdcard/" to push it to my phone.<br />
<br />
Then I rebooted into recovery again ("adb reboot recovery"), and tried to install it, with the “Install zip from sdcard” option. However, I got the following: “E:Error in /sdcard/Superuser-3.0.7-efghi-signed.zip (Status 0)". Doing a little research, I found the following posts:<br />
<br />
<ul>
<li><a href="http://androidsu.com/superuser/#comment-6120">http://androidsu.com/superuser/#comment-6120</a>
</li>
<li><a href="http://www.theandroidsoul.com/root-ice-cream-sandwich-on-att-galaxy-s2-skyrocket/#comment-478881789">http://www.theandroidsoul.com/root-ice-cream-sandwich-on-att-galaxy-s2-skyrocket/#comment-478881789</a>
</li>
</ul>
<div>
I tried everything, but could not get it to install. Instead, I found myself on <a href="http://download.clockworkmod.com/">download.clockworkmod.com</a>. In <a href="http://download.clockworkmod.com/su/">/su/</a>, I found seven different "-test" versions, and in <a href="http://download.clockworkmod.com/test/">/test/</a> there is one su.zip. (I can't for the life of me find the site that linked to that one.) It turns out that that is <a href="http://download.clockworkmod.com/test/su.zip">the one</a> that worked for me. I don't quite understand, but whatever, it successfully installed via CWM. After rebooting, Superuser was installed, and showed the correct version of the binary (and updated it too!).</div>
<div>
<br /></div>
<div>
<b>What's Next</b></div>
<div>
Next, I'm probably going to upgrade to the stock Android 4.0.4 ROM, as it supposedly makes some <a href="http://www.xda-developers.com/android/galaxy-nexus-gets-ics-4-0-4-update/">big improvements</a>. That page links to <a href="http://forum.xda-developers.com/showthread.php?t=1481044">this thread</a>. Also in my sights for a new ROM are this <a href="http://forum.xda-developers.com/showthread.php?t=1631796">IMM76K 4.0.4</a> mod, and of course <a href="http://forum.xda-developers.com/showthread.php?t=1514333">CyanogenMod 9</a>, which is currently available only in nightlies.</div>
<br />
<br />
<b><br /></b><br />
<b>Resources</b><br />
<a href="http://galaxynexusroot.com/galaxy-nexus-root/how-to-root-galaxy-nexus-universal-guidegsmverizonsprintwindowslinuxmac/">http://galaxynexusroot.com/galaxy-nexus-root/how-to-root-galaxy-nexus-universal-guidegsmverizonsprintwindowslinuxmac/</a>Jonathon Reinharthttp://www.blogger.com/profile/04790032076191957141noreply@blogger.com2tag:blogger.com,1999:blog-1764037540275477749.post-85252692812054545172012-04-29T13:57:00.000-04:002012-04-29T13:57:01.467-04:00Never knew Downloader.Agent2.BBLD was so simpleI had just started writing a new C++ console app (under Visual Studio 2010 10.0.40219.1 SP1Rel) to test something out, and had just this:<br />
<br />
<div style="text-align: left;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">#include <stdio.h></span></div>
<div style="text-align: left;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">#include <Windows.h></span></div>
<div style="text-align: left;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><br /></span></div>
<div style="text-align: left;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">int main(int argc, char** argv)</span></div>
<div style="text-align: left;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">{</span></div>
<div style="text-align: left;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span style="white-space: pre;"> </span>return 0;</span></div>
<div style="text-align: left;">
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">}</span></div>
<br />
I unintentionally clicked Start Debugging, and much to my surprise,<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLRAQIGAcfGuS3jeQkJVCcdhjOcle1L8lYAVqBKMCHuo7FWIQwHHTfTABcYPNci_NOF3sbXchM_ZnOTLc6_hGI7jL0zv6m1ESpxu8LR6OIx4EEo1roNFJKwHUVaoYPjiytVd19zteM8Hg/s1600/build_errors.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="156" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjLRAQIGAcfGuS3jeQkJVCcdhjOcle1L8lYAVqBKMCHuo7FWIQwHHTfTABcYPNci_NOF3sbXchM_ZnOTLc6_hGI7jL0zv6m1ESpxu8LR6OIx4EEo1roNFJKwHUVaoYPjiytVd19zteM8Hg/s400/build_errors.PNG" width="400" /></a></div>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWpHd_VMhXpNfW_kHaETWFRFZtrwoNqzObJir2VkHNH-CcEAwj0YtF3q1_xyb4dVAe2c95IcV2PE5CVwmTEJaUl9hHzIP7bT4sYwWBefyfPs1F0I1bYWp3f1k8hPrlvv4PViU62_-MMgo/s1600/error.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="82" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjWpHd_VMhXpNfW_kHaETWFRFZtrwoNqzObJir2VkHNH-CcEAwj0YtF3q1_xyb4dVAe2c95IcV2PE5CVwmTEJaUl9hHzIP7bT4sYwWBefyfPs1F0I1bYWp3f1k8hPrlvv4PViU62_-MMgo/s400/error.PNG" width="400" /></a></div>
<br />
Really? How did I screw up something so simple? Several seconds later AVG popped up this "Resident Shield Alert":<br />
<br />
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3i-VraL1WfSsNvwnbxYIeh78i9HOb1N7G6pq1n1B3WSwgmOd_y8-021IWcdBpLkbdg5dVQ1Y7bpVUL97oJV38i40hu2ajOnYc7q9VSbTwtLiqB2kj2T74S1gS0tp2vjM-rsBUnl5k234/s1600/threat.PNG" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="321" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi3i-VraL1WfSsNvwnbxYIeh78i9HOb1N7G6pq1n1B3WSwgmOd_y8-021IWcdBpLkbdg5dVQ1Y7bpVUL97oJV38i40hu2ajOnYc7q9VSbTwtLiqB2kj2T74S1gS0tp2vjM-rsBUnl5k234/s400/threat.PNG" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Downloader.Agent2.BBLD</td></tr>
</tbody></table>
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
Are you kidding me? So I added a printf...</div>
<div class="separator" style="clear: both; text-align: left;">
<br /></div>
<div class="separator" style="clear: both; text-align: left;">
</div>
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">int main(int argc, char** argv)</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">{</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> printf("WTF is going on\n");</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"><span style="white-space: pre;"> </span>return 0;</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">}</span><br />
<br />
<br />
Again, threat detected! This time Downloader.Agent2.BAZE. I disabled AVG, built it again (successfully!) and threw the EXE into IDA, worried that I had some impressive virus injecting a trojan into EXEs I build. Nothing out of the ordinary found, just the typical complicated CRT startup code, and my simple main().<br />
<br />
I uploaded it to <a href="https://www.virustotal.com/file/ec48b28216e65ba2a4d7d35872810d346e0135c759fa7cb29c7f9a128f802393/analysis/1335719858/" target="_blank">VirusTotal</a> to see if this was just AVG being retarded or what. It had a detection ratio of 8 / 42. Check out that link to see each AV and what they detected it as. <u> It is important to note that AVG picked up the file before it had even finished building (hence the link error) with Resident Shield, but also the finished EXE with a manual scan.</u><br />
<br />
"This is absurd!" I'm thinking. One more try....<br />
<br />
<br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">int main(int argc, char** argv)</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">{</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> printf("WTF is going on\n");</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> getchar();</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> printf("This is ridiculous\n");</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;"> return 0;</span><br />
<span style="font-family: 'Courier New', Courier, monospace; font-size: x-small;">}</span><br />
<br />
<br />
Finally, this one built okay and AVG let it alone. Curious, I uploaded this one to <a href="https://www.virustotal.com/file/3358f50d7378862e2c717c1a1e31f6a051b76b06470272619af333c49442f676/analysis/1335721772/" target="_blank">VirusTotal</a> too. It was picked up by only 1 / 42 AVs: <b>McAfee-GW-Edition</b> identified it as <i>Heuristic.BehavesLike.Win32.Suspicious.H</i>. Sounds more like Heuristic.WeHaveNoIdea.FlagEverything.HJonathon Reinharthttp://www.blogger.com/profile/04790032076191957141noreply@blogger.com3tag:blogger.com,1999:blog-1764037540275477749.post-89632029761654966252011-10-27T22:58:00.000-04:002011-10-27T22:58:33.654-04:00SSDs and Windows 'Users' DirectoryAfter getting my new SSD installed, I really wanted to get everything setup so that my data was safe on the 1 TB RAID 1 array. This meant somehow moving the Users directory from C:\ (the SSD) to D:\ (the RAID). <br />
<br />
The two main approaches are:<br />
<br />
<ol><li>Use an unattend.xml file during Windows installation to specify the Users directory.</li>
<li>Move the Users directory after installation, and create a <a href="http://en.wikipedia.org/wiki/NTFS_junction_point">junction point</a> at the original location to point to the newly located directory. Here, the junction essentially acts as a symbolic link (although symlinks are a <a href="http://en.wikipedia.org/wiki/NTFS_symbolic_link">different thing</a> in NTFS.)</li>
</ol><div>After reading a ton of forum and blog posts, I decided to follow Marilyn O's advice on <a href="http://answers.microsoft.com/en-us/windows/forum/windows_7-security/move-user-folders-off-system-drive-want-all/c8d2aaad-0672-4361-9853-b3f863416483">this question</a> and decided to go with #2, because it is a single point of change, and should be easily reversible.</div><div><br />
</div><div>Here's how I got it working. <i>C: is my SSD where Windows is installed, and D: is the RAID array to which I'm moving my Users directory. Your drives/paths may be different.</i></div><div><ol><li>Install windows as usual. Go a head and get the OS in a working state.<br />
<br />
</li>
<li>Boot to a command line from the install media. Follow <a href="http://forum.bkis.com/showthread.php?361-OG12-Guide-for-using-Windows-7-s-Startup-Repair-tool">these direction</a>s, but on the System Recovery Options dialog, click the last one, Command Prompt.<br />
<br />
</li>
<li>Use<a href="http://technet.microsoft.com/en-us/library/cc733145(WS.10).aspx"> robocopy</a> to make an exact copy of Users to the new location:<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">robocopy /mir /xj C:\Users D:\Users</span><br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;"> /mir</span> makes an exact mirror, and <span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">/xj</span> ignores junction points. Make sure to include these options!<br />
<br />
</li>
<li>Verify that all the data has been successfully copied. Then, remove the original Users directory:<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">rmdir /s /q C:\Users</span><br />
You really <b>have</b> to do this. See comment at the end for why.<br />
<br />
</li>
<li>There is a junction named "Documents and Settings" (remember him from XP?) that currently points to C:\Users for compatibility purposes. We need to first remove him:<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">rd "Documents and Settings"</span><br />
<br />
</li>
<li>Now, make the new junctions pointing to the new Users folder on D: using <a href="http://technet.microsoft.com/en-us/library/cc753194(WS.10).aspx">mklink</a>:<br />
<span class="Apple-style-span" style="font-family: 'Courier New', Courier, monospace;">mklink /j C:\Users D:\Users<br />
mklink /j "C:\Documents and Settings" D:\Users</span><br />
(Yes, Linux users, those arguments are in the opposite order.)<br />
<br />
</li>
<li>Reboot and log in to Windows. If you look in C: in windows explorer, you should see that Users now has a shortcut overlay, indicating that it is a junction point:</li>
</ol><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGNZzfl3WoZtxarT1Vv94tsKoek7NSjV1n5KOySKflXXjBRhoLT5s-_MIGFzohwpfPhIgzhDttF5HzzEmmmIxvx4jABuUCSo2KJ8oZXtHHea0Sz06Axj8p_wuzQPcyH8zYiWkyhZgE0Fc/s1600/Capture.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em; text-align: center;"><img border="0" height="224" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiGNZzfl3WoZtxarT1Vv94tsKoek7NSjV1n5KOySKflXXjBRhoLT5s-_MIGFzohwpfPhIgzhDttF5HzzEmmmIxvx4jABuUCSo2KJ8oZXtHHea0Sz06Axj8p_wuzQPcyH8zYiWkyhZgE0Fc/s320/Capture.PNG" width="320" /></a></div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">Go ahead and play with it; files you make in C:\Users will be there in D:\Users. Now granted, this may be a slight performance hit, because we have moved some important user files (ntuser.dat for example) onto the slower HDD. In my opinion though, this is worth it, considering all of my user data is safe. Additionally, I can back up the entire D: drive, and not worry about wasting space backing up Windows too.</div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;">Notes:</div><br />
I originally just renamed C:\Users to old_users but this caused me to have <i>another</i> Users directory in C: when I looked in windows explorer! And old_users was nowhere to be found. But, everything looked okay from the command line. I even <i>copied</i> it, and had the same results. So there must be some trickery going on that causes windows explorer to show it as Users. Deleting the directory made everything hunky-dory.</div>Jonathon Reinharthttp://www.blogger.com/profile/04790032076191957141noreply@blogger.com2